CACAO
codegen.c
Go to the documentation of this file.
1 /* src/vm/jit/intrp/codegen.c - code generator for Interpreter
2 
3  Copyright (C) 1996-2013
4  CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 
6  This file is part of CACAO.
7 
8  This program is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License as
10  published by the Free Software Foundation; either version 2, or (at
11  your option) any later version.
12 
13  This program is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21  02110-1301, USA.
22 
23 */
24 
25 
26 #include "config.h"
27 
28 #include <assert.h>
29 #include <stdio.h>
30 
31 #if defined(WITH_FFI)
32 # include <ffi.h>
33 #elif defined(WITH_FFCALL)
34 # include <avcall.h>
35 #else
36 # error neither WITH_FFI nor WITH_FFCALL defined
37 #endif
38 
39 #include "vm/types.hpp"
40 
41 #include "arch.hpp"
42 
43 #include "vm/jit/intrp/codegen.h"
44 #include "vm/jit/intrp/intrp.h"
45 
46 #include "mm/memory.hpp"
47 
48 #include "native/native.hpp"
49 
50 #include "vm/jit/builtin.hpp"
51 #include "vm/class.hpp"
52 #include "vm/exceptions.hpp"
53 #include "vm/global.hpp"
54 #include "vm/options.hpp"
55 #include "vm/vm.hpp"
56 
57 #include "vm/jit/asmpart.hpp"
59 #include "vm/jit/dseg.hpp"
60 #include "vm/jit/jit.hpp"
61 #include "vm/jit/parse.hpp"
62 #include "vm/jit/patcher.hpp"
63 #include "vm/jit/stack.hpp"
64 #include "vm/jit/stacktrace.hpp"
65 
66 
67 #define gen_branch(_inst) { \
68  gen_##_inst(cd, 0); \
69  codegen_addreference(cd, BLOCK_OF(iptr->dst.insindex)); \
70 }
71 
72 #define index2offset(_i) (-(_i) * SIZEOF_VOID_P)
73 
74 /* functions used by cacao-gen.i */
75 
76 void genarg_v(codegendata *cd1, Cell v)
77 {
78  Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
79  *((Cell *) *mcodepp) = v;
80  (*mcodepp)++;
81 }
82 
83 void genarg_i(codegendata *cd1, s4 i)
84 {
85  Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
86  *((Cell *) *mcodepp) = i;
87  (*mcodepp)++;
88 }
89 
90 void genarg_b(codegendata *cd1, s4 i)
91 {
92  genarg_i(cd1, i);
93 }
94 
95 void genarg_f(codegendata *cd1, float f)
96 {
97  s4 fi;
98 
99  vm_f2Cell(f,fi);
100  genarg_i(cd1, fi);
101 }
102 
103 void genarg_l(codegendata *cd1, s8 l)
104 {
105  Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
106  vm_l2twoCell(l, ((Cell *) *mcodepp)[1], ((Cell *) *mcodepp)[0]);
107  (*mcodepp) +=2;
108 }
109 
110 void genarg_aRef(codegendata *cd1, java_objectheader *a)
111 {
112  Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
113  *((java_objectheader **) *mcodepp) = a;
114  (*mcodepp)++;
115 }
116 
117 void genarg_aArray(codegendata *cd1, java_arrayheader *a)
118 {
119  Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
120  *((java_arrayheader **) *mcodepp) = a;
121  (*mcodepp)++;
122 }
123 
125 {
126  Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
127  *((Inst ***) *mcodepp) = a;
128  (*mcodepp)++;
129 }
130 
132 {
133  Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
134  *((classinfo **) *mcodepp) = a;
135  (*mcodepp)++;
136 }
137 
139 {
140  Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
141  *((constant_classref **) *mcodepp) = a;
142  (*mcodepp)++;
143 }
144 
145 void genarg_addr(codegendata *cd1, u1 *a)
146 {
147  Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
148  *((u1 **) *mcodepp) = a;
149  (*mcodepp)++;
150 }
151 
153 {
154  Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
155  *((functionptr *) *mcodepp) = a;
156  (*mcodepp)++;
157 }
158 
160 {
161  Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
162  *((fieldinfo **) *mcodepp) = a;
163  (*mcodepp)++;
164 }
165 
167 {
168  Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
169  *((methodinfo **) *mcodepp) = a;
170  (*mcodepp)++;
171 }
172 
174 {
175  Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
176  *((Cell **) *mcodepp) = a;
177  (*mcodepp)++;
178 }
179 
181 {
182  Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
183  *((Inst **) *mcodepp) = a;
184  (*mcodepp)++;
185 }
186 
188 {
189  Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
190  *((unresolved_field **) *mcodepp) = a;
191  (*mcodepp)++;
192 }
193 
195 {
196  Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
197  *((unresolved_method **) *mcodepp) = a;
198  (*mcodepp)++;
199 }
200 
202 {
203  Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
204  *((vftbl_t **) *mcodepp) = a;
205  (*mcodepp)++;
206 }
207 
208 
209 /* include the interpreter generation functions *******************************/
210 
211 /* Do not use "java-gen.i", it does not work with builddir. */
212 #include <java-gen.i>
213 
214 
216 
217 typedef struct builtin_gen builtin_gen;
218 
219 struct builtin_gen {
222 };
223 
225  {BUILTIN_new, gen_NEW, },
226  {BUILTIN_newarray, gen_NEWARRAY, },
227  {BUILTIN_newarray_boolean, gen_NEWARRAY_BOOLEAN,},
228  {BUILTIN_newarray_byte, gen_NEWARRAY_BYTE, },
229  {BUILTIN_newarray_char, gen_NEWARRAY_CHAR, },
230  {BUILTIN_newarray_short, gen_NEWARRAY_SHORT, },
231  {BUILTIN_newarray_int, gen_NEWARRAY_INT, },
232  {BUILTIN_newarray_long, gen_NEWARRAY_LONG, },
233  {BUILTIN_newarray_float, gen_NEWARRAY_FLOAT, },
234  {BUILTIN_newarray_double, gen_NEWARRAY_DOUBLE, },
235  {BUILTIN_arrayinstanceof, gen_ARRAYINSTANCEOF, },
236 
237 #if defined(ENABLE_THREADS)
238  {LOCK_monitor_enter, gen_MONITORENTER, },
239  {LOCK_monitor_exit, gen_MONITOREXIT, },
240 #endif
241 
242 #if !(SUPPORT_FLOAT && SUPPORT_F2L)
243  {BUILTIN_f2l, gen_F2L, },
244 #endif
245 
246 #if !(SUPPORT_DOUBLE && SUPPORT_D2L)
247  {BUILTIN_d2l, gen_D2L, },
248 #endif
249 
250 #if !(SUPPORT_FLOAT && SUPPORT_F2I)
251  {BUILTIN_f2i, gen_F2I, },
252 #endif
253 
254 #if !(SUPPORT_DOUBLE && SUPPORT_D2I)
255  {BUILTIN_d2i, gen_D2I, },
256 #endif
257 
258 #if !SUPPORT_DIVISION
259  {BUILTIN_idiv, gen_IDIV, },
260  {BUILTIN_irem, gen_IREM, },
261 #endif
262 
263 #if !(SUPPORT_DIVISION && SUPPORT_LONG_DIV)
264  {BUILTIN_ldiv, gen_LDIV, },
265  {BUILTIN_lrem, gen_LREM, },
266 #endif
267 
268  {BUILTIN_frem, gen_FREM, },
269  {BUILTIN_drem, gen_DREM, },
270 };
271 
272 
273 /* codegen *********************************************************************
274 
275  Generates machine code.
276 
277 *******************************************************************************/
278 
279 #define I(value) iptr[0].sx.val.i = (value); break;
280 
282 {
283  methodinfo *m;
284  codegendata *cd;
285  registerdata *rd;
286  s4 i, len, s1, s2, d;
287  basicblock *bptr;
288  instruction *iptr;
289  u2 currentline;
290  methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
291  unresolved_method *um;
292  builtintable_entry *bte;
293  methoddesc *md;
294  fieldinfo *fi;
295  unresolved_field *uf;
296  s4 fieldtype;
297 
298  /* get required compiler data */
299 
300  m = jd->m;
301  cd = jd->cd;
302  rd = jd->rd;
303 
304  /* prevent compiler warnings */
305 
306  d = 0;
307  currentline = 0;
308  lm = NULL;
309  bte = NULL;
310 
311  /* determine stackframe size (in units of ptrint slots) */
312 
313  cd->stackframesize = m->maxlocals;
314 
315 #if defined(ENABLE_THREADS)
316  if (checksync && code_is_synchronized(code))
317  cd->stackframesize += 1;
318 #endif
319 
320  /* create method header */
321 
322  (void) dseg_add_unique_address(cd, jd->code);
323  (void) dseg_add_unique_s4(cd, cd->stackframesize * SIZEOF_VOID_P);
324 
325  code->synchronizedoffset = rd->memuse * 8;
326 
327  /* REMOVEME: We still need it for exception handling in assembler. */
328 
329  if (code_is_leafmethod(code))
330  (void) dseg_add_unique_s4(cd, 1);
331  else
332  (void) dseg_add_unique_s4(cd, 0);
333 
334  (void) dseg_add_unique_s4(cd, 0);
335  (void) dseg_add_unique_s4(cd, 0);
336 
337  dseg_addlinenumbertablesize(cd);
338 
339 #if 0
340  /* initialize mcode variables */
341 
342  cd->mcodeptr = cd->mcodebase;
343  cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
344 #endif
345 
346  gen_BBSTART;
347 
348 #if defined(ENABLE_THREADS)
349  if (checksync && code_is_synchronized(code)) {
350  if (m->flags & ACC_STATIC) {
351  gen_ACONST(cd, (java_objectheader *) m->clazz);
352  }
353  else {
354  gen_ALOAD(cd, 0);
355  gen_DUP(cd);
356  gen_ASTORE(cd, index2offset(m->maxlocals));
357  }
358 
359  gen_MONITORENTER(cd);
360  }
361 #endif
362 
363  if (opt_verbosecall)
364  gen_TRACECALL(cd, m);
365 
366  gen_BBEND;
367 
368  /* walk through all basic blocks */
369 
370  for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
371 
372  bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
373 
374  if (bptr->state != basicblock::DELETED) {
375 
376  /* walk through all instructions */
377 
378  len = bptr->icount;
379 
380  gen_BBSTART;
381 
382  for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
383  if (iptr->line != currentline) {
384  dseg_addlinenumber(cd, iptr->line);
385  currentline = iptr->line;
386  }
387 
388  MCODECHECK(64); /* an instruction usually needs < 64 words */
389 
390 switch_again:
391  switch (iptr->opc) {
392 
393  case ICMD_INLINE_START:
394  case ICMD_INLINE_END:
395  break;
396 
397  case ICMD_NOP: /* ... ==> ... */
398  break;
399 
400  case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
401 
402  gen_CHECKNULL(cd);
403  break;
404 
405  /* constant operations ************************************************/
406 
407  case ICMD_ICONST: /* ... ==> ..., constant */
408  /* op1 = 0, val.i = constant */
409 
410  /* optimize ICONST (2^x) .. IREM --> IREMPOW2 (const) */
411 
412  if (len >= 2 && iptr[1].opc == ICMD_IREM) {
413  switch (iptr[0].sx.val.i) {
414  case 0x00000001: case 0x00000002: case 0x00000004: case 0x00000008:
415  case 0x00000010: case 0x00000020: case 0x00000040: case 0x00000080:
416  case 0x00000100: case 0x00000200: case 0x00000400: case 0x00000800:
417  case 0x00001000: case 0x00002000: case 0x00004000: case 0x00008000:
418  case 0x00010000: case 0x00020000: case 0x00040000: case 0x00080000:
419  case 0x00100000: case 0x00200000: case 0x00400000: case 0x00800000:
420  case 0x01000000: case 0x02000000: case 0x04000000: case 0x08000000:
421  case 0x10000000: case 0x20000000: case 0x40000000: case 0x80000000:
422  iptr[0].opc = ICMD_IREMPOW2;
423  iptr[0].sx.val.i--;
424  iptr[1].opc = ICMD_NOP;
425  goto switch_again;
426  }
427  }
428 
429  /* optimize ICONST (2^x) .. IDIV --> IDIVPOW2 (const) */
430 
431  if (len >= 2 && iptr[1].opc == ICMD_IDIV) {
432  switch (iptr[0].sx.val.i) {
433  case 0x00000002: I( 1) case 0x00000004: I( 2) case 0x00000008: I( 3)
434  case 0x00000010: I( 4) case 0x00000020: I( 5) case 0x00000040: I( 6) case 0x00000080: I( 7)
435  case 0x00000100: I( 8) case 0x00000200: I( 9) case 0x00000400: I(10) case 0x00000800: I(11)
436  case 0x00001000: I(12) case 0x00002000: I(13) case 0x00004000: I(14) case 0x00008000: I(15)
437  case 0x00010000: I(16) case 0x00020000: I(17) case 0x00040000: I(18) case 0x00080000: I(19)
438  case 0x00100000: I(20) case 0x00200000: I(21) case 0x00400000: I(22) case 0x00800000: I(23)
439  case 0x01000000: I(24) case 0x02000000: I(25) case 0x04000000: I(26) case 0x08000000: I(27)
440  case 0x10000000: I(28) case 0x20000000: I(29) case 0x40000000: I(30) case 0x80000000: I(31)
441  default: goto dont_opt_IDIVPOW2;
442  }
443  iptr[0].opc = ICMD_IDIVPOW2;
444  iptr[1].opc = ICMD_NOP;
445  goto switch_again;
446  }
447 dont_opt_IDIVPOW2:
448 
449  /* optimize ICONST .. IF_ICMPxx --> IFxx (const) */
450 
451  if (len >= 2) {
452  switch (iptr[1].opc) {
453  case ICMD_IF_ICMPEQ: iptr[0].opc = ICMD_IFEQ; break;
454  case ICMD_IF_ICMPNE: iptr[0].opc = ICMD_IFNE; break;
455  case ICMD_IF_ICMPLT: iptr[0].opc = ICMD_IFLT; break;
456  case ICMD_IF_ICMPLE: iptr[0].opc = ICMD_IFLE; break;
457  case ICMD_IF_ICMPGT: iptr[0].opc = ICMD_IFGT; break;
458  case ICMD_IF_ICMPGE: iptr[0].opc = ICMD_IFGE; break;
459  default: goto dont_opt_IFxx;
460  }
461  iptr[0].dst.insindex = iptr[1].dst.insindex;
462  iptr[1].opc = ICMD_NOP;
463  goto switch_again;
464  }
465 dont_opt_IFxx:
466 
467  gen_ICONST(cd, iptr->sx.val.i);
468  break;
469 
470  case ICMD_LCONST: /* ... ==> ..., constant */
471  /* op1 = 0, val.l = constant */
472 
473  /* optimize LCONST (2^x) .. LREM --> LREMPOW2 (const) */
474 
475  if (len >= 2 && iptr[1].opc == ICMD_LREM) {
476  switch (iptr[0].sx.val.l) {
477  case 0x00000001: case 0x00000002: case 0x00000004: case 0x00000008:
478  case 0x00000010: case 0x00000020: case 0x00000040: case 0x00000080:
479  case 0x00000100: case 0x00000200: case 0x00000400: case 0x00000800:
480  case 0x00001000: case 0x00002000: case 0x00004000: case 0x00008000:
481  case 0x00010000: case 0x00020000: case 0x00040000: case 0x00080000:
482  case 0x00100000: case 0x00200000: case 0x00400000: case 0x00800000:
483  case 0x01000000: case 0x02000000: case 0x04000000: case 0x08000000:
484  case 0x10000000: case 0x20000000: case 0x40000000: case 0x80000000:
485  iptr[0].opc = ICMD_LREMPOW2;
486  iptr[0].sx.val.l--;
487  iptr[1].opc = ICMD_NOP;
488  goto switch_again;
489  }
490  }
491 
492  /* optimize LCONST (2^x) .. LDIV --> LDIVPOW2 (const) */
493 
494  if (len >= 2 && iptr[1].opc == ICMD_LDIV) {
495  switch (iptr[0].sx.val.l) {
496  case 0x00000002: I( 1) case 0x00000004: I( 2) case 0x00000008: I( 3)
497  case 0x00000010: I( 4) case 0x00000020: I( 5) case 0x00000040: I( 6) case 0x00000080: I( 7)
498  case 0x00000100: I( 8) case 0x00000200: I( 9) case 0x00000400: I(10) case 0x00000800: I(11)
499  case 0x00001000: I(12) case 0x00002000: I(13) case 0x00004000: I(14) case 0x00008000: I(15)
500  case 0x00010000: I(16) case 0x00020000: I(17) case 0x00040000: I(18) case 0x00080000: I(19)
501  case 0x00100000: I(20) case 0x00200000: I(21) case 0x00400000: I(22) case 0x00800000: I(23)
502  case 0x01000000: I(24) case 0x02000000: I(25) case 0x04000000: I(26) case 0x08000000: I(27)
503  case 0x10000000: I(28) case 0x20000000: I(29) case 0x40000000: I(30) case 0x80000000: I(31)
504  default: goto dont_opt_LDIVPOW2;
505  }
506  iptr[0].opc = ICMD_LDIVPOW2;
507  iptr[1].opc = ICMD_NOP;
508  goto switch_again;
509  }
510 dont_opt_LDIVPOW2:
511 
512  /* optimize LCONST .. LCMP .. IFxx (0) --> IF_Lxx */
513 
514  if (len >= 3 && iptr[1].opc == ICMD_LCMP && iptr[2].sx.val.i == 0) {
515  switch (iptr[2].opc) {
516  case ICMD_IFEQ: iptr[0].opc = ICMD_IF_LEQ; break;
517  case ICMD_IFNE: iptr[0].opc = ICMD_IF_LNE; break;
518  case ICMD_IFLT: iptr[0].opc = ICMD_IF_LLT; break;
519  case ICMD_IFLE: iptr[0].opc = ICMD_IF_LLE; break;
520  case ICMD_IFGT: iptr[0].opc = ICMD_IF_LGT; break;
521  case ICMD_IFGE: iptr[0].opc = ICMD_IF_LGE; break;
522  default: goto dont_opt_IF_Lxx;
523  }
524  iptr[0].dst.insindex = iptr[2].dst.insindex;
525  iptr[1].opc = ICMD_NOP;
526  iptr[2].opc = ICMD_NOP;
527  goto switch_again;
528  }
529 dont_opt_IF_Lxx:
530 
531  gen_LCONST(cd, iptr->sx.val.l);
532  break;
533 
534  case ICMD_FCONST: /* ... ==> ..., constant */
535  /* op1 = 0, val.f = constant */
536  {
537  ptrint fi;
538 
539  vm_f2Cell(iptr->sx.val.f, fi);
540  gen_ICONST(cd, fi);
541  }
542  break;
543 
544  case ICMD_DCONST: /* ... ==> ..., constant */
545  /* op1 = 0, val.d = constant */
546 
547  gen_LCONST(cd, *(s8 *)&(iptr->sx.val.d));
548  break;
549 
550  case ICMD_ACONST: /* ... ==> ..., constant */
551  /* op1 = 0, val.a = constant */
552 
553  if (INSTRUCTION_IS_UNRESOLVED(iptr))
554  gen_PATCHER_ACONST(cd, NULL, iptr->sx.val.c.ref);
555  else
556  gen_ACONST(cd, iptr->sx.val.anyptr);
557  break;
558 
559 
560  /* load/store operations **********************************************/
561 
562  case ICMD_ILOAD: /* ... ==> ..., content of local variable */
563  /* op1 = local variable */
564 
565  gen_ILOAD(cd, index2offset(iptr->s1.varindex));
566  break;
567 
568  case ICMD_LLOAD: /* ... ==> ..., content of local variable */
569  /* op1 = local variable */
570 
571  gen_LLOAD(cd, index2offset(iptr->s1.varindex));
572  break;
573 
574  case ICMD_ALOAD: /* ... ==> ..., content of local variable */
575  /* op1 = local variable */
576 
577  gen_ALOAD(cd, index2offset(iptr->s1.varindex));
578  break;
579 
580  case ICMD_FLOAD: /* ... ==> ..., content of local variable */
581  /* op1 = local variable */
582 
583  gen_ILOAD(cd, index2offset(iptr->s1.varindex));
584  break;
585 
586  case ICMD_DLOAD: /* ... ==> ..., content of local variable */
587  /* op1 = local variable */
588 
589  gen_LLOAD(cd, index2offset(iptr->s1.varindex));
590  break;
591 
592 
593  case ICMD_ISTORE: /* ..., value ==> ... */
594  /* op1 = local variable */
595 
596  gen_ISTORE(cd, index2offset(iptr->dst.varindex));
597  break;
598 
599  case ICMD_LSTORE: /* ..., value ==> ... */
600  /* op1 = local variable */
601 
602  gen_LSTORE(cd, index2offset(iptr->dst.varindex));
603  break;
604 
605  case ICMD_ASTORE: /* ..., value ==> ... */
606  /* op1 = local variable */
607 
608  gen_ASTORE(cd, index2offset(iptr->dst.varindex));
609  break;
610 
611 
612  case ICMD_FSTORE: /* ..., value ==> ... */
613  /* op1 = local variable */
614 
615  gen_ISTORE(cd, index2offset(iptr->dst.varindex));
616  break;
617 
618  case ICMD_DSTORE: /* ..., value ==> ... */
619  /* op1 = local variable */
620 
621  gen_LSTORE(cd, index2offset(iptr->dst.varindex));
622  break;
623 
624 
625  /* pop/dup/swap operations ********************************************/
626 
627  case ICMD_POP: /* ..., value ==> ... */
628 
629  gen_POP(cd);
630  break;
631 
632  case ICMD_POP2: /* ..., value, value ==> ... */
633 
634  gen_POP2(cd);
635  break;
636 
637  case ICMD_DUP: /* ..., a ==> ..., a, a */
638 
639  gen_DUP(cd);
640  break;
641 
642  case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
643 
644  gen_DUP_X1(cd);
645  break;
646 
647  case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
648 
649  gen_DUP_X2(cd);
650  break;
651 
652  case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
653 
654  gen_DUP2(cd);
655  break;
656 
657  case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
658 
659  gen_DUP2_X1(cd);
660  break;
661 
662  case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
663 
664  gen_DUP2_X2(cd);
665  break;
666 
667  case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
668 
669  gen_SWAP(cd);
670  break;
671 
672 
673  /* integer operations *************************************************/
674 
675  case ICMD_INEG: /* ..., value ==> ..., - value */
676 
677  gen_INEG(cd);
678  break;
679 
680  case ICMD_LNEG: /* ..., value ==> ..., - value */
681 
682  gen_LNEG(cd);
683  break;
684 
685  case ICMD_I2L: /* ..., value ==> ..., value */
686 
687  gen_I2L(cd);
688  break;
689 
690  case ICMD_L2I: /* ..., value ==> ..., value */
691 
692  gen_L2I(cd);
693  break;
694 
695  case ICMD_INT2BYTE: /* ..., value ==> ..., value */
696 
697  gen_INT2BYTE(cd);
698  break;
699 
700  case ICMD_INT2CHAR: /* ..., value ==> ..., value */
701 
702  gen_INT2CHAR(cd);
703  break;
704 
705  case ICMD_INT2SHORT: /* ..., value ==> ..., value */
706 
707  gen_INT2SHORT(cd);
708  break;
709 
710 
711  case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
712 
713  gen_IADD(cd);
714  break;
715 
716  case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
717 
718  gen_LADD(cd);
719  break;
720 
721  case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
722 
723  gen_ISUB(cd);
724  break;
725 
726  case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
727 
728  gen_LSUB(cd);
729  break;
730 
731  case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
732 
733  gen_IMUL(cd);
734  break;
735 
736  case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
737 
738  gen_LMUL(cd);
739  break;
740 
741  case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
742 
743  gen_IDIV(cd);
744  break;
745 
746  case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
747 
748  gen_IREM(cd);
749  break;
750 
751  case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
752 
753  gen_LDIV(cd);
754  break;
755 
756  case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
757 
758  gen_LREM(cd);
759  break;
760 
761  case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
762  /* val.i = constant */
763 
764  gen_IDIVPOW2(cd, iptr->sx.val.i);
765  break;
766 
767  case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
768  /* val.i = constant */
769 
770  gen_IREMPOW2(cd, iptr->sx.val.i);
771  break;
772 
773  case ICMD_LDIVPOW2: /* ..., value ==> ..., value << constant */
774  /* val.i = constant */
775 
776  gen_LDIVPOW2(cd, iptr->sx.val.i);
777  break;
778 
779  case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
780  /* val.l = constant */
781 
782  gen_LREMPOW2(cd, iptr->sx.val.i);
783  break;
784 
785  case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
786 
787  gen_ISHL(cd);
788  break;
789 
790  case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
791 
792  gen_ISHR(cd);
793  break;
794 
795  case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
796 
797  gen_IUSHR(cd);
798  break;
799 
800  case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
801 
802  gen_LSHL(cd);
803  break;
804 
805  case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
806 
807  gen_LSHR(cd);
808  break;
809 
810  case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
811 
812  gen_LUSHR(cd);
813  break;
814 
815  case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
816 
817  gen_IAND(cd);
818  break;
819 
820  case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
821 
822  gen_LAND(cd);
823  break;
824 
825  case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
826 
827  gen_IOR(cd);
828  break;
829 
830  case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
831 
832  gen_LOR(cd);
833  break;
834 
835  case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
836 
837  gen_IXOR(cd);
838  break;
839 
840  case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
841 
842  gen_LXOR(cd);
843  break;
844 
845 
846  case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
847 
848  /* optimize LCMP .. IFxx (0) --> IF_LCMPxx */
849 
850  if (len >= 2 && iptr[1].sx.val.i == 0) {
851  switch (iptr[1].opc) {
852  case ICMD_IFEQ: iptr[0].opc = ICMD_IF_LCMPEQ; break;
853  case ICMD_IFNE: iptr[0].opc = ICMD_IF_LCMPNE; break;
854  case ICMD_IFLT: iptr[0].opc = ICMD_IF_LCMPLT; break;
855  case ICMD_IFLE: iptr[0].opc = ICMD_IF_LCMPLE; break;
856  case ICMD_IFGT: iptr[0].opc = ICMD_IF_LCMPGT; break;
857  case ICMD_IFGE: iptr[0].opc = ICMD_IF_LCMPGE; break;
858  default: goto dont_opt_IF_LCMPxx;
859  }
860  iptr[0].dst.insindex = iptr[1].dst.insindex;
861  iptr[1].opc = ICMD_NOP;
862  goto switch_again;
863  }
864 dont_opt_IF_LCMPxx:
865 
866  gen_LCMP(cd);
867  break;
868 
869 
870  case ICMD_IINC: /* ..., value ==> ..., value + constant */
871  /* op1 = variable, val.i = constant */
872 
873  gen_IINC(cd, index2offset(iptr->s1.varindex), iptr->sx.val.i);
874  break;
875 
876 
877  /* floating operations ************************************************/
878 
879  case ICMD_FNEG: /* ..., value ==> ..., - value */
880 
881  gen_FNEG(cd);
882  break;
883 
884  case ICMD_DNEG: /* ..., value ==> ..., - value */
885 
886  gen_DNEG(cd);
887  break;
888 
889  case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
890 
891  gen_FADD(cd);
892  break;
893 
894  case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
895 
896  gen_DADD(cd);
897  break;
898 
899  case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
900 
901  gen_FSUB(cd);
902  break;
903 
904  case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
905 
906  gen_DSUB(cd);
907  break;
908 
909  case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
910 
911  gen_FMUL(cd);
912  break;
913 
914  case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
915 
916  gen_DMUL(cd);
917  break;
918 
919  case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
920 
921  gen_FDIV(cd);
922  break;
923 
924  case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
925 
926  gen_DDIV(cd);
927  break;
928 
929  case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
930 
931  gen_FREM(cd);
932  break;
933 
934  case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
935 
936  gen_DREM(cd);
937  break;
938 
939  case ICMD_I2F: /* ..., value ==> ..., (float) value */
940 
941  gen_I2F(cd);
942  break;
943 
944  case ICMD_L2F: /* ..., value ==> ..., (float) value */
945 
946  gen_L2F(cd);
947  break;
948 
949  case ICMD_I2D: /* ..., value ==> ..., (double) value */
950 
951  gen_I2D(cd);
952  break;
953 
954  case ICMD_L2D: /* ..., value ==> ..., (double) value */
955 
956  gen_L2D(cd);
957  break;
958 
959  case ICMD_F2I: /* ..., value ==> ..., (int) value */
960 
961  gen_F2I(cd);
962  break;
963 
964  case ICMD_D2I: /* ..., value ==> ..., (int) value */
965 
966  gen_D2I(cd);
967  break;
968 
969  case ICMD_F2L: /* ..., value ==> ..., (long) value */
970 
971  gen_F2L(cd);
972  break;
973 
974  case ICMD_D2L: /* ..., value ==> ..., (long) value */
975 
976  gen_D2L(cd);
977  break;
978 
979  case ICMD_F2D: /* ..., value ==> ..., (double) value */
980 
981  gen_F2D(cd);
982  break;
983 
984  case ICMD_D2F: /* ..., value ==> ..., (float) value */
985 
986  gen_D2F(cd);
987  break;
988 
989  case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
990 
991  gen_FCMPL(cd);
992  break;
993 
994  case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
995 
996  gen_DCMPL(cd);
997  break;
998 
999  case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1000 
1001  gen_FCMPG(cd);
1002  break;
1003 
1004  case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1005 
1006  gen_DCMPG(cd);
1007  break;
1008 
1009 
1010  /* memory operations **************************************************/
1011 
1012  case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1013 
1014  gen_ARRAYLENGTH(cd);
1015  break;
1016 
1017  case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1018 
1019  gen_BALOAD(cd);
1020  break;
1021 
1022  case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1023 
1024  gen_CALOAD(cd);
1025  break;
1026 
1027  case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1028 
1029  gen_SALOAD(cd);
1030  break;
1031 
1032  case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1033 
1034  gen_IALOAD(cd);
1035  break;
1036 
1037  case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1038 
1039  gen_FALOAD(cd);
1040  break;
1041 
1042  case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1043  case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1044 
1045  gen_LALOAD(cd);
1046  break;
1047 
1048  case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1049 
1050  gen_AALOAD(cd);
1051  break;
1052 
1053 
1054  case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1055 
1056  gen_BASTORE(cd);
1057  break;
1058 
1059  case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1060  case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1061 
1062  gen_CASTORE(cd);
1063  break;
1064 
1065  case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1066 
1067  gen_IASTORE(cd);
1068  break;
1069 
1070  case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1071 
1072  gen_FASTORE(cd);
1073  break;
1074 
1075  case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1076  case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1077 
1078  gen_LASTORE(cd);
1079  break;
1080 
1081  case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1082 
1083  gen_AASTORE(cd);
1084  break;
1085 
1086 
1087  case ICMD_GETSTATIC: /* ... ==> ..., value */
1088  /* op1 = type, val.a = field address */
1089 
1090  if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1091  fi = NULL;
1092  uf = iptr->sx.s23.s3.uf;
1093  fieldtype = uf->fieldref->parseddesc.fd->type;
1094  }
1095  else {
1096  fi = iptr->sx.s23.s3.fmiref->p.field;
1097  uf = NULL;
1098  fieldtype = fi->type;
1099  }
1100 
1101  switch (fieldtype) {
1102  case TYPE_INT:
1103  if (fi == NULL)
1104  gen_PATCHER_GETSTATIC_INT(cd, 0, uf);
1105  else if (!class_is_or_almost_initialized(fi->clazz))
1106  gen_PATCHER_GETSTATIC_CLINIT_INT(cd, 0, fi);
1107  else
1108  gen_GETSTATIC_INT(cd, (u1 *) &(fi->value.i), fi);
1109  break;
1110  case TYPE_FLT:
1111  if (fi == NULL)
1112  gen_PATCHER_GETSTATIC_FLOAT(cd, 0, uf);
1113  else if (!class_is_or_almost_initialized(fi->clazz))
1114  gen_PATCHER_GETSTATIC_CLINIT_FLOAT(cd, 0, fi);
1115  else
1116  gen_GETSTATIC_FLOAT(cd, (u1 *) &(fi->value.i), fi);
1117  break;
1118  case TYPE_LNG:
1119  case TYPE_DBL:
1120  if (fi == NULL)
1121  gen_PATCHER_GETSTATIC_LONG(cd, 0, uf);
1122  else if (!class_is_or_almost_initialized(fi->clazz))
1123  gen_PATCHER_GETSTATIC_CLINIT_LONG(cd, 0, fi);
1124  else
1125  gen_GETSTATIC_LONG(cd, (u1 *) &(fi->value.l), fi);
1126  break;
1127  case TYPE_ADR:
1128  if (fi == NULL)
1129  gen_PATCHER_GETSTATIC_CELL(cd, 0, uf);
1130  else if (!class_is_or_almost_initialized(fi->clazz))
1131  gen_PATCHER_GETSTATIC_CLINIT_CELL(cd, 0, fi);
1132  else
1133  gen_GETSTATIC_CELL(cd, (u1 *) &(fi->value.a), fi);
1134  break;
1135  }
1136  break;
1137 
1138  case ICMD_PUTSTATIC: /* ..., value ==> ... */
1139  /* op1 = type, val.a = field address */
1140 
1141  if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1142  fi = NULL;
1143  uf = iptr->sx.s23.s3.uf;
1144  fieldtype = uf->fieldref->parseddesc.fd->type;
1145  }
1146  else {
1147  fi = iptr->sx.s23.s3.fmiref->p.field;
1148  uf = NULL;
1149  fieldtype = fi->type;
1150  }
1151 
1152  switch (fieldtype) {
1153  case TYPE_INT:
1154  if (fi == NULL)
1155  gen_PATCHER_PUTSTATIC_INT(cd, 0, uf);
1156  else if (!class_is_or_almost_initialized(fi->clazz))
1157  gen_PATCHER_PUTSTATIC_CLINIT_INT(cd, 0, fi);
1158  else
1159  gen_PUTSTATIC_INT(cd, (u1 *) &(fi->value.i), fi);
1160  break;
1161  case TYPE_FLT:
1162  if (fi == NULL)
1163  gen_PATCHER_PUTSTATIC_FLOAT(cd, 0, uf);
1164  else if (!class_is_or_almost_initialized(fi->clazz))
1165  gen_PATCHER_PUTSTATIC_CLINIT_FLOAT(cd, 0, fi);
1166  else
1167  gen_PUTSTATIC_FLOAT(cd, (u1 *) &(fi->value.i), fi);
1168  break;
1169  case TYPE_LNG:
1170  case TYPE_DBL:
1171  if (fi == NULL)
1172  gen_PATCHER_PUTSTATIC_LONG(cd, 0, uf);
1173  else if (!class_is_or_almost_initialized(fi->clazz))
1174  gen_PATCHER_PUTSTATIC_CLINIT_LONG(cd, 0, fi);
1175  else
1176  gen_PUTSTATIC_LONG(cd, (u1 *) &(fi->value.l), fi);
1177  break;
1178  case TYPE_ADR:
1179  if (fi == NULL)
1180  gen_PATCHER_PUTSTATIC_CELL(cd, 0, uf);
1181  else if (!class_is_or_almost_initialized(fi->clazz))
1182  gen_PATCHER_PUTSTATIC_CLINIT_CELL(cd, 0, fi);
1183  else
1184  gen_PUTSTATIC_CELL(cd, (u1 *) &(fi->value.a), fi);
1185  break;
1186  }
1187  break;
1188 
1189 
1190  case ICMD_GETFIELD: /* ... ==> ..., value */
1191  /* op1 = type, val.a = field address */
1192 
1193  if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1194  fi = NULL;
1195  uf = iptr->sx.s23.s3.uf;
1196  fieldtype = uf->fieldref->parseddesc.fd->type;
1197  }
1198  else {
1199  fi = iptr->sx.s23.s3.fmiref->p.field;
1200  uf = NULL;
1201  fieldtype = fi->type;
1202  }
1203 
1204  switch (fieldtype) {
1205  case TYPE_INT:
1206  if (fi == NULL)
1207  gen_PATCHER_GETFIELD_INT(cd, 0, uf);
1208  else
1209  gen_GETFIELD_INT(cd, fi->offset, fi);
1210  break;
1211  case TYPE_FLT:
1212  if (fi == NULL)
1213  gen_PATCHER_GETFIELD_FLOAT(cd, 0, uf);
1214  else
1215  gen_GETFIELD_FLOAT(cd, fi->offset, fi);
1216  break;
1217  case TYPE_LNG:
1218  case TYPE_DBL:
1219  if (fi == NULL)
1220  gen_PATCHER_GETFIELD_LONG(cd, 0, uf);
1221  else
1222  gen_GETFIELD_LONG(cd, fi->offset, fi);
1223  break;
1224  case TYPE_ADR:
1225  if (fi == NULL)
1226  gen_PATCHER_GETFIELD_CELL(cd, 0, uf);
1227  else
1228  gen_GETFIELD_CELL(cd, fi->offset, fi);
1229  break;
1230  }
1231  break;
1232 
1233  case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
1234  /* op1 = type, val.a = field address */
1235 
1236  if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1237  fi = NULL;
1238  uf = iptr->sx.s23.s3.uf;
1239  fieldtype = uf->fieldref->parseddesc.fd->type;
1240  }
1241  else {
1242  fi = iptr->sx.s23.s3.fmiref->p.field;
1243  uf = NULL;
1244  fieldtype = fi->type;
1245  }
1246 
1247  switch (fieldtype) {
1248  case TYPE_INT:
1249  if (fi == NULL)
1250  gen_PATCHER_PUTFIELD_INT(cd, 0, uf);
1251  else
1252  gen_PUTFIELD_INT(cd, fi->offset, fi);
1253  break;
1254  case TYPE_FLT:
1255  if (fi == NULL)
1256  gen_PATCHER_PUTFIELD_FLOAT(cd, 0, uf);
1257  else
1258  gen_PUTFIELD_FLOAT(cd, fi->offset, fi);
1259  break;
1260  case TYPE_LNG:
1261  case TYPE_DBL:
1262  if (fi == NULL)
1263  gen_PATCHER_PUTFIELD_LONG(cd, 0, uf);
1264  else
1265  gen_PUTFIELD_LONG(cd, fi->offset, fi);
1266  break;
1267  case TYPE_ADR:
1268  if (fi == NULL)
1269  gen_PATCHER_PUTFIELD_CELL(cd, 0, uf);
1270  else
1271  gen_PUTFIELD_CELL(cd, fi->offset, fi);
1272  break;
1273  }
1274  break;
1275 
1276 
1277  /* branch operations **************************************************/
1278 
1279  case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
1280 
1281  gen_ATHROW(cd);
1282  break;
1283 
1284  case ICMD_GOTO: /* ... ==> ... */
1285  /* op1 = target JavaVM pc */
1286  gen_branch(GOTO);
1287  break;
1288 
1289  case ICMD_JSR: /* ... ==> ... */
1290  /* op1 = target JavaVM pc */
1291 
1292  gen_JSR(cd, NULL);
1293  codegen_addreference(cd, BLOCK_OF(iptr->sx.s23.s3.jsrtarget.insindex));
1294  break;
1295 
1296  case ICMD_RET: /* ... ==> ... */
1297  /* op1 = local variable */
1298 
1299  gen_RET(cd, index2offset(iptr->s1.varindex));
1300  break;
1301 
1302  case ICMD_IFNULL: /* ..., value ==> ... */
1303  /* op1 = target JavaVM pc */
1304 
1305  gen_branch(IFNULL);
1306  break;
1307 
1308  case ICMD_IFNONNULL: /* ..., value ==> ... */
1309  /* op1 = target JavaVM pc */
1310 
1311  gen_branch(IFNONNULL);
1312  break;
1313 
1314  case ICMD_IFEQ: /* ..., value ==> ... */
1315  /* op1 = target JavaVM pc, val.i = constant */
1316 
1317  if (iptr->sx.val.i == 0) {
1318  gen_branch(IFEQ);
1319  } else {
1320  gen_ICONST(cd, iptr->sx.val.i);
1321  gen_branch(IF_ICMPEQ);
1322  }
1323  break;
1324 
1325  case ICMD_IFLT: /* ..., value ==> ... */
1326  /* op1 = target JavaVM pc, val.i = constant */
1327 
1328  if (iptr->sx.val.i == 0) {
1329  gen_branch(IFLT);
1330  } else {
1331  gen_ICONST(cd, iptr->sx.val.i);
1332  gen_branch(IF_ICMPLT);
1333  }
1334  break;
1335 
1336  case ICMD_IFLE: /* ..., value ==> ... */
1337  /* op1 = target JavaVM pc, val.i = constant */
1338 
1339  if (iptr->sx.val.i == 0) {
1340  gen_branch(IFLE);
1341  } else {
1342  gen_ICONST(cd, iptr->sx.val.i);
1343  gen_branch(IF_ICMPLE);
1344  }
1345  break;
1346 
1347  case ICMD_IFNE: /* ..., value ==> ... */
1348  /* op1 = target JavaVM pc, val.i = constant */
1349 
1350  if (iptr->sx.val.i == 0) {
1351  gen_branch(IFNE);
1352  } else {
1353  gen_ICONST(cd, iptr->sx.val.i);
1354  gen_branch(IF_ICMPNE);
1355  }
1356  break;
1357 
1358  case ICMD_IFGT: /* ..., value ==> ... */
1359  /* op1 = target JavaVM pc, val.i = constant */
1360 
1361  if (iptr->sx.val.i == 0) {
1362  gen_branch(IFGT);
1363  } else {
1364  gen_ICONST(cd, iptr->sx.val.i);
1365  gen_branch(IF_ICMPGT);
1366  }
1367  break;
1368 
1369  case ICMD_IFGE: /* ..., value ==> ... */
1370  /* op1 = target JavaVM pc, val.i = constant */
1371 
1372  if (iptr->sx.val.i == 0) {
1373  gen_branch(IFGE);
1374  } else {
1375  gen_ICONST(cd, iptr->sx.val.i);
1376  gen_branch(IF_ICMPGE);
1377  }
1378  break;
1379 
1380 
1381  case ICMD_IF_LEQ: /* ..., value ==> ... */
1382  /* op1 = target JavaVM pc, val.l = constant */
1383 
1384  gen_LCONST(cd, iptr->sx.val.l);
1385  gen_branch(IF_LCMPEQ);
1386  break;
1387 
1388  case ICMD_IF_LLT: /* ..., value ==> ... */
1389  /* op1 = target JavaVM pc, val.l = constant */
1390 
1391  gen_LCONST(cd, iptr->sx.val.l);
1392  gen_branch(IF_LCMPLT);
1393  break;
1394 
1395  case ICMD_IF_LLE: /* ..., value ==> ... */
1396  /* op1 = target JavaVM pc, val.l = constant */
1397 
1398  gen_LCONST(cd, iptr->sx.val.l);
1399  gen_branch(IF_LCMPLE);
1400  break;
1401 
1402  case ICMD_IF_LNE: /* ..., value ==> ... */
1403  /* op1 = target JavaVM pc, val.l = constant */
1404 
1405  gen_LCONST(cd, iptr->sx.val.l);
1406  gen_branch(IF_LCMPNE);
1407  break;
1408 
1409  case ICMD_IF_LGT: /* ..., value ==> ... */
1410  /* op1 = target JavaVM pc, val.l = constant */
1411 
1412  gen_LCONST(cd, iptr->sx.val.l);
1413  gen_branch(IF_LCMPGT);
1414  break;
1415 
1416  case ICMD_IF_LGE: /* ..., value ==> ... */
1417  /* op1 = target JavaVM pc, val.l = constant */
1418 
1419  gen_LCONST(cd, iptr->sx.val.l);
1420  gen_branch(IF_LCMPGE);
1421  break;
1422 
1423  case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
1424  /* op1 = target JavaVM pc */
1425 
1426  gen_branch(IF_LCMPEQ);
1427  break;
1428 
1429  case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
1430  /* op1 = target JavaVM pc */
1431 
1432  gen_branch(IF_LCMPNE);
1433  break;
1434 
1435  case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
1436  /* op1 = target JavaVM pc */
1437 
1438  gen_branch(IF_LCMPLT);
1439  break;
1440 
1441  case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
1442  /* op1 = target JavaVM pc */
1443 
1444  gen_branch(IF_LCMPGT);
1445  break;
1446 
1447  case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
1448  /* op1 = target JavaVM pc */
1449 
1450  gen_branch(IF_LCMPLE);
1451  break;
1452 
1453  case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
1454  /* op1 = target JavaVM pc */
1455 
1456  gen_branch(IF_LCMPGE);
1457  break;
1458 
1459 
1460  case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
1461  /* op1 = target JavaVM pc */
1462 
1463  gen_branch(IF_ICMPEQ);
1464  break;
1465 
1466  case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
1467  /* op1 = target JavaVM pc */
1468 
1469  gen_branch(IF_ACMPEQ);
1470  break;
1471 
1472  case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
1473  /* op1 = target JavaVM pc */
1474 
1475  gen_branch(IF_ICMPNE);
1476  break;
1477 
1478  case ICMD_IF_ACMPNE: /* ..., value, value ==> ... */
1479  /* op1 = target JavaVM pc */
1480 
1481  gen_branch(IF_ACMPNE);
1482  break;
1483 
1484  case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
1485  /* op1 = target JavaVM pc */
1486 
1487  gen_branch(IF_ICMPLT);
1488  break;
1489 
1490  case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
1491  /* op1 = target JavaVM pc */
1492 
1493  gen_branch(IF_ICMPGT);
1494  break;
1495 
1496  case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
1497  /* op1 = target JavaVM pc */
1498 
1499  gen_branch(IF_ICMPLE);
1500  break;
1501 
1502  case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
1503  /* op1 = target JavaVM pc */
1504 
1505  gen_branch(IF_ICMPGE);
1506  break;
1507 
1508 
1509  case ICMD_ARETURN: /* ..., retvalue ==> ... */
1510  case ICMD_IRETURN: /* ..., retvalue ==> ... */
1511  case ICMD_FRETURN: /* ..., retvalue ==> ... */
1512 
1513 #if defined(ENABLE_THREADS)
1514  if (checksync && code_is_synchronized(code)) {
1515  if (m->flags & ACC_STATIC) {
1516  gen_ACONST(cd, (java_objectheader *) m->clazz);
1517  } else {
1518  gen_ALOAD(cd, index2offset(m->maxlocals));
1519  }
1520  gen_MONITOREXIT(cd);
1521  }
1522 #endif
1523  if (opt_verbosecall)
1524  gen_TRACERETURN(cd, m);
1525 
1526  gen_IRETURN(cd, index2offset(cd->stackframesize));
1527  break;
1528 
1529  case ICMD_LRETURN: /* ..., retvalue ==> ... */
1530  case ICMD_DRETURN: /* ..., retvalue ==> ... */
1531 
1532 #if defined(ENABLE_THREADS)
1533  if (checksync && code_is_synchronized(code)) {
1534  if (m->flags & ACC_STATIC) {
1535  gen_ACONST(cd, (java_objectheader *) m->clazz);
1536  } else {
1537  gen_ALOAD(cd, index2offset(m->maxlocals));
1538  }
1539  gen_MONITOREXIT(cd);
1540  }
1541 #endif
1542  if (opt_verbosecall)
1543  gen_TRACELRETURN(cd, m);
1544 
1545  gen_LRETURN(cd, index2offset(cd->stackframesize));
1546  break;
1547 
1548  case ICMD_RETURN: /* ... ==> ... */
1549 
1550 #if defined(ENABLE_THREADS)
1551  if (checksync && code_is_synchronized(code)) {
1552  if (m->flags & ACC_STATIC) {
1553  gen_ACONST(cd, (java_objectheader *) m->clazz);
1554  } else {
1555  gen_ALOAD(cd, index2offset(m->maxlocals));
1556  }
1557  gen_MONITOREXIT(cd);
1558  }
1559 #endif
1560  if (opt_verbosecall)
1561  gen_TRACERETURN(cd, m);
1562 
1563  gen_RETURN(cd, index2offset(cd->stackframesize));
1564  break;
1565 
1566 
1567  case ICMD_TABLESWITCH: /* ..., index ==> ... */
1568  {
1569  s4 i, l;
1570  branch_target_t *table;
1571 
1572  table = iptr->dst.table;
1573 
1574  l = iptr->sx.s23.s2.tablelow;
1575  i = iptr->sx.s23.s3.tablehigh;
1576 
1577  i = i - l + 1;
1578 
1579  /* arguments: low, range, datasegment address, table
1580  offset in datasegment, default target */
1581 
1582  gen_TABLESWITCH(cd, l, i, NULL, 0, NULL);
1583 
1584  /* actually -3 cells offset */
1585 
1586  cd->mcodeptr = (u1 *) cd->mcodeptr - 2 * sizeof(Inst);
1587  dseg_adddata(cd);
1588  cd->mcodeptr = (u1 *) cd->mcodeptr + 2 * sizeof(Inst);
1589 
1590  codegen_addreference(cd, BLOCK_OF(table[0].insindex));
1591 
1592  /* build jump table top down and use address of lowest entry */
1593 
1594  table += i;
1595 
1596  while (--i >= 0) {
1597  dseg_add_target(cd, BLOCK_OF(table->insindex));
1598  --table;
1599  }
1600  }
1601 
1602  /* length of dataseg after last dseg_add_target is used by load */
1603  ((ptrint *)(cd->mcodeptr))[-2] = (ptrint) -(cd->dseglen);
1604  break;
1605 
1606 
1607  case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
1608  {
1609  s4 i;
1610  lookup_target_t *lookup;
1611 
1612  lookup = iptr->dst.lookup;
1613 
1614  i = iptr->sx.s23.s2.lookupcount;
1615 
1616  /* arguments: count, datasegment address, table offset in */
1617  /* datasegment, default target */
1618  gen_LOOKUPSWITCH(cd, i, NULL, 0, NULL);
1619 
1620  /* actually -3 cells offset */
1621 
1622  cd->mcodeptr = (u1 *) cd->mcodeptr - 2 * sizeof(Inst);
1623  dseg_adddata(cd);
1624  cd->mcodeptr = (u1 *) cd->mcodeptr + 2 * sizeof(Inst);
1625 
1626  /* build jump table top down and use address of lowest entry */
1627 
1628  while (--i >= 0) {
1629  dseg_add_target(cd, BLOCK_OF(lookup->target.insindex));
1630  dseg_add_unique_address(cd, lookup->value);
1631  lookup++;
1632  }
1633 
1634  codegen_addreference(cd, BLOCK_OF(iptr->sx.s23.s3.lookupdefault.insindex));
1635  }
1636 
1637  /* length of dataseg after last dseg_add_target is used by load */
1638  ((ptrint *)(cd->mcodeptr))[-2] = (ptrint) -(cd->dseglen);
1639  break;
1640 
1641 
1642  case ICMD_BUILTIN: /* ..., arg1, arg2, arg3 ==> ... */
1643  /* op1 = arg count val.a = builtintable entry */
1644  bte = iptr->sx.s23.s3.bte;
1645 
1646  for (i = 0; i < sizeof(builtin_gen_table)/sizeof(builtin_gen); i++) {
1647  builtin_gen *bg = &builtin_gen_table[i];
1648  if (bg->builtin == bte->fp) {
1649  (bg->gen)(cd);
1650  goto gen_builtin_end;
1651  }
1652  }
1653 
1654  vm_abort(0);
1655 
1656  gen_builtin_end:
1657  break;
1658 
1659  case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
1660  /* op1 = arg count, val.a = method pointer */
1661 
1662  if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1663  um = iptr->sx.s23.s3.um;
1664  md = um->methodref->parseddesc.md;
1665  gen_PATCHER_INVOKESTATIC(cd, 0, md->paramslots, um);
1666  }
1667  else {
1668  lm = iptr->sx.s23.s3.fmiref->p.method;
1669  md = lm->parseddesc;
1670  gen_INVOKESTATIC(cd, (Inst **) lm->stubroutine, md->paramslots, lm);
1671  }
1672  break;
1673 
1674  case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
1675 
1676  if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1677  um = iptr->sx.s23.s3.um;
1678  md = um->methodref->parseddesc.md;
1679  gen_PATCHER_INVOKESPECIAL(cd, 0, md->paramslots, um);
1680  }
1681  else {
1682  lm = iptr->sx.s23.s3.fmiref->p.method;
1683  md = lm->parseddesc;
1684  gen_INVOKESPECIAL(cd, (Inst **) lm->stubroutine, md->paramslots, lm);
1685  }
1686  break;
1687 
1688  case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
1689 
1690  if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1691  um = iptr->sx.s23.s3.um;
1692  md = um->methodref->parseddesc.md;
1693  gen_PATCHER_INVOKEVIRTUAL(cd, 0, md->paramslots, um);
1694  }
1695  else {
1696  lm = iptr->sx.s23.s3.fmiref->p.method;
1697  md = lm->parseddesc;
1698 
1699  s1 = OFFSET(vftbl_t, table[0]) +
1700  sizeof(methodptr) * lm->vftblindex;
1701 
1702  gen_INVOKEVIRTUAL(cd, s1, md->paramslots, lm);
1703  }
1704  break;
1705 
1706  case ICMD_INVOKEINTERFACE:/* op1 = arg count, val.a = method pointer */
1707 
1708  if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1709  um = iptr->sx.s23.s3.um;
1710  md = um->methodref->parseddesc.md;
1711  gen_PATCHER_INVOKEINTERFACE(cd, 0, 0, md->paramslots, um);
1712  }
1713  else {
1714  lm = iptr->sx.s23.s3.fmiref->p.method;
1715  md = lm->parseddesc;
1716 
1717  s1 = OFFSET(vftbl_t, interfacetable[0]) -
1718  sizeof(methodptr*) * lm->clazz->index;
1719 
1720  s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
1721 
1722  gen_INVOKEINTERFACE(cd, s1, s2, md->paramslots, lm);
1723  }
1724  break;
1725 
1726 
1727  case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
1728  /* op1: 0 == array, 1 == class */
1729  /* val.a: (classinfo *) superclass */
1730 
1731  if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
1732  if (INSTRUCTION_IS_UNRESOLVED(iptr))
1733  gen_PATCHER_CHECKCAST(cd, NULL, iptr->sx.s23.s3.c.ref);
1734  else
1735  gen_CHECKCAST(cd, iptr->sx.s23.s3.c.cls, NULL);
1736  }
1737  else {
1738  if (INSTRUCTION_IS_UNRESOLVED(iptr))
1739  gen_PATCHER_ARRAYCHECKCAST(cd, NULL, iptr->sx.s23.s3.c.ref);
1740  else
1741  gen_ARRAYCHECKCAST(cd, iptr->sx.s23.s3.c.cls, NULL);
1742  }
1743  break;
1744 
1745  case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
1746  /* op1: 0 == array, 1 == class */
1747  /* val.a: (classinfo *) superclass */
1748 
1749  if (INSTRUCTION_IS_UNRESOLVED(iptr))
1750  gen_PATCHER_INSTANCEOF(cd, NULL, iptr->sx.s23.s3.c.ref);
1751  else
1752  gen_INSTANCEOF(cd, iptr->sx.s23.s3.c.cls, iptr->sx.s23.s3.c.ref);
1753  break;
1754 
1755  case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
1756  /* op1 = dimension, val.a = class */
1757 
1758  if (INSTRUCTION_IS_UNRESOLVED(iptr))
1759  gen_PATCHER_MULTIANEWARRAY(cd, NULL, iptr->s1.argcount, iptr->sx.s23.s3.c.ref);
1760  else
1761  gen_MULTIANEWARRAY(cd, iptr->sx.s23.s3.c.cls, iptr->s1.argcount, NULL);
1762  break;
1763 
1764  default:
1765  exceptions_throw_internalerror("Unknown ICMD %d during code generation",
1766  iptr->opc);
1767  return false;
1768  } /* switch */
1769 
1770  } /* for instruction */
1771 
1772  gen_BBEND;
1773 
1774  } /* if (bptr->state != basicblock::DELETED) */
1775  } /* for basic block */
1776 
1777  dseg_createlinenumbertable(cd);
1778 
1779  codegen_finish(jd);
1780 
1781 #ifdef VM_PROFILING
1782  vm_block_insert(jd->code->mcode + jd->code->mcodelength);
1783 #endif
1784 
1785  /* branch resolving (walk through all basic blocks) */
1786 
1787  for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
1788  branchref *brefs;
1789 
1790  for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
1791  gen_resolveanybranch(((u1*) jd->code->entrypoint) + brefs->branchpos,
1792  ((u1 *)jd->code->entrypoint) + bptr->mpc);
1793  }
1794  }
1795 
1796  /* everything's ok */
1797 
1798  return true;
1799 }
1800 
1801 
1802 /* createcompilerstub **********************************************************
1803 
1804  Creates a stub routine which calls the compiler.
1805 
1806  A stub consists of:
1807 
1808  +-------------+
1809  | codeinfo * |
1810  +-------------+ <-- stub
1811  | codeptr |
1812  +-------------+
1813  | framesize | (in ptrint units, does not include return address)
1814  +-------------+
1815  | TRANSLATE |
1816  +-------------+
1817  | methodinfo |
1818  +-------------+
1819 
1820  codeptr points either to TRANSLATE or to the translated threaded code
1821 
1822  all methods are called indirectly through methodptr
1823 
1824 *******************************************************************************/
1825 
1826 #define COMPILERSTUB_DATASIZE 2
1827 #define COMPILERSTUB_CODESIZE 4
1828 
1829 #define COMPILERSTUB_SIZE COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
1830 
1831 
1833 {
1834  Inst *s;
1835  Inst *d;
1836  codegendata *cd;
1837  s4 stackframesize;
1838  int32_t dumpmarker;
1839 
1840  s = CNEW(Inst, COMPILERSTUB_SIZE);
1841 
1842  /* set data pointer and code pointer */
1843 
1844  d = s;
1845  s = s + COMPILERSTUB_DATASIZE;
1846 
1847  /* The codeinfo pointer is actually a pointer to the
1848  methodinfo. This fakes a codeinfo structure. */
1849 
1850  d[0] = (Inst *) m;
1851  d[1] = (Inst *) &d[0]; /* fake code->m */
1852 
1853  /* mark start of dump memory area */
1854 
1855  DMARKER;
1856 
1857  cd = DNEW(codegendata);
1858  cd->mcodeptr = (u1 *) s;
1859  cd->lastinstwithoutdispatch = ~0;
1860  cd->superstarts = NULL;
1861 
1862  genarg_ainst(cd, s + 2);
1863 
1864  if (m->flags & ACC_NATIVE) {
1865  stackframesize = m->parseddesc->paramslots;
1866  }
1867  else {
1868  stackframesize = m->maxlocals;
1869 
1870 #if defined(ENABLE_THREADS)
1871  if (checksync && code_is_synchronized(code))
1872  stackframesize += 1;
1873 #endif
1874  }
1875 
1876  genarg_i(cd, stackframesize);
1877 
1878  gen_BBSTART;
1879  gen_TRANSLATE(cd, m);
1880  gen_BBEND;
1881 
1882 #ifdef VM_PROFILING
1884 #endif
1885 
1886 #if defined(ENABLE_STATISTICS)
1887  if (opt_stat)
1888  #warning port to new statistics framework
1889  count_cstub_len += COMPILERSTUB_SIZE;
1890 #endif
1891 
1892  /* release dump area */
1893 
1894  DRELEASE;
1895 
1896  return (u1 *) s;
1897 }
1898 
1899 
1900 #if defined(WITH_FFI)
1901 static ffi_type *cacaotype2ffitype(s4 cacaotype)
1902 {
1903  switch (cacaotype) {
1904  case TYPE_INT:
1905 #if SIZEOF_VOID_P == 8
1906  return &ffi_type_sint64;
1907 #else
1908  return &ffi_type_sint32;
1909 #endif
1910  case TYPE_LNG:
1911  return &ffi_type_sint64;
1912  case TYPE_FLT:
1913  return &ffi_type_float;
1914  case TYPE_DBL:
1915  return &ffi_type_double;
1916  case TYPE_ADR:
1917  return &ffi_type_pointer;
1918  case TYPE_VOID:
1919  return &ffi_type_void;
1920  default:
1921  assert(false);
1922  }
1923 }
1924 #endif
1925 
1926 
1927 /* native stub:
1928 +---------+
1929 |NATIVECALL|
1930 +---------+
1931 |methodinf|
1932 +---------+
1933 |function |
1934 +---------+
1935 |cif |
1936 +---------+
1937 */
1938 
1939 #if defined(WITH_FFI)
1940 static ffi_cif *createnativecif(methodinfo *m, methoddesc *nmd)
1941 {
1942  methoddesc *md = m->parseddesc;
1943  ffi_cif *pcif = NEW(ffi_cif);
1944  ffi_type **types = MNEW(ffi_type *, nmd->paramcount);
1945  ffi_type **ptypes = types;
1946  s4 i;
1947 
1948  /* pass env pointer */
1949 
1950  *ptypes++ = &ffi_type_pointer;
1951 
1952  /* for static methods, pass class pointer */
1953 
1954  if (m->flags & ACC_STATIC)
1955  *ptypes++ = &ffi_type_pointer;
1956 
1957  /* pass parameter to native function */
1958 
1959  for (i = 0; i < md->paramcount; i++)
1960  *ptypes++ = cacaotype2ffitype(md->paramtypes[i].type);
1961 
1962  assert(ptypes - types == nmd->paramcount);
1963 
1964  if (ffi_prep_cif(pcif, FFI_DEFAULT_ABI, nmd->paramcount, cacaotype2ffitype(md->returntype.type), types) != FFI_OK)
1965  assert(0);
1966 
1967  return pcif;
1968 }
1969 #endif
1970 
1971 
1973 {
1974  methodinfo *m;
1975  codeinfo *code;
1976  codegendata *cd;
1977  registerdata *rd;
1978 #if defined(WITH_FFI)
1979  ffi_cif *cif;
1980 #else
1981  u1 *cif;
1982 #endif
1983  s4 stackframesize;
1984 
1985  /* get required compiler data */
1986 
1987  m = jd->m;
1988  code = jd->code;
1989  cd = jd->cd;
1990  rd = jd->rd;
1991 
1992  /* determine stackframe size (in units of ptrint) */
1993 
1994  stackframesize = nmd->paramslots;
1995 
1996  /* create method header */
1997 
1998  (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
1999  (void) dseg_add_unique_s4(cd, stackframesize * SIZEOF_VOID_P); /*FrameSize*/
2000  (void) dseg_add_unique_s4(cd, 0); /* IsSync */
2001  (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
2002  (void) dseg_add_unique_s4(cd, 0); /* IntSave */
2003  (void) dseg_add_unique_s4(cd, 0); /* FltSave */
2004  dseg_addlinenumbertablesize(cd);
2005  (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
2006 
2007 #if defined(WITH_FFI)
2008  /* prepare ffi cif structure */
2009 
2010  cif = createnativecif(m, nmd);
2011 #else
2012  cif = NULL;
2013 #endif
2014 
2015  gen_BBSTART;
2016 
2017  if (opt_verbosecall)
2018  gen_TRACECALL(cd, m);
2019 
2020  if (f == NULL) {
2021  gen_PATCHER_NATIVECALL(cd, m, f, (u1 *)cif);
2022  } else {
2023  if (opt_verbosecall)
2024  gen_TRACENATIVECALL(cd, m, f, (u1 *)cif);
2025  else
2026  gen_NATIVECALL(cd, m, f, (u1 *)cif);
2027  }
2028 
2029  gen_BBEND;
2030 
2031  codegen_finish(jd);
2032 
2033 #ifdef VM_PROFILING
2034  vm_block_insert(jd->code->mcode + jd->code->mcodelength);
2035 #endif
2036 
2037  return jd->code->entrypoint;
2038 }
2039 
2040 
2041 /* call jni function */
2043 {
2044 #if defined(WITH_FFCALL)
2045  av_alist alist;
2046  methoddesc *md;
2047  Cell *p;
2048  Cell *endsp;
2049  s4 i;
2050 
2051  struct {
2052  stackframeinfo sfi;
2053  localref_table lrt;
2054  } s;
2055 
2056  md = m->parseddesc;
2057 
2058  switch (md->returntype.type) {
2059  case TYPE_INT:
2060  endsp = sp - 1 + md->paramslots;
2061  av_start_long(alist, f, endsp);
2062  break;
2063  case TYPE_LNG:
2064  endsp = sp - 2 + md->paramslots;
2065  av_start_longlong(alist, f, endsp);
2066  break;
2067  case TYPE_FLT:
2068  endsp = sp - 1 + md->paramslots;
2069  av_start_float(alist, f, endsp);
2070  break;
2071  case TYPE_DBL:
2072  endsp = sp - 2 + md->paramslots;
2073  av_start_double(alist, f, endsp);
2074  break;
2075  case TYPE_ADR:
2076  endsp = sp - 1 + md->paramslots;
2077  av_start_ptr(alist, f, void *, endsp);
2078  break;
2079  case TYPE_VOID:
2080  endsp = sp + md->paramslots;
2081  av_start_void(alist, f);
2082  break;
2083  default:
2084  assert(false);
2085  }
2086 
2087  av_ptr(alist, _Jv_JNIEnv *, VM_get_jnienv());
2088 
2089  if (m->flags & ACC_STATIC)
2090  av_ptr(alist, classinfo *, m->clazz);
2091 
2092  for (i = 0, p = sp + md->paramslots; i < md->paramcount; i++) {
2093  switch (md->paramtypes[i].type) {
2094  case TYPE_INT:
2095  p -= 1;
2096  av_long(alist, *p);
2097  break;
2098  case TYPE_LNG:
2099  p -= 2;
2100  av_longlong(alist, *(s8 *)p);
2101  break;
2102  case TYPE_FLT:
2103  p -= 1;
2104  av_float(alist, *((float *) p));
2105  break;
2106  case TYPE_DBL:
2107  p -= 2;
2108  av_double(alist, *(double *) p);
2109  break;
2110  case TYPE_ADR:
2111  p -= 1;
2112  av_ptr(alist, void *, *(void **) p);
2113  break;
2114  default:
2115  assert(false);
2116  }
2117  }
2118 
2119  global_sp = sp;
2120 
2121  /* create stackframe info structure */
2122 
2123  codegen_start_native_call(((u1 *) &s) + sizeof(s), m->code->entrypoint,
2124  (u1 *) fp, (u1 *) ra);
2125 
2126  av_call(alist);
2127 
2128  *exceptionptr = codegen_finish_native_call(((u1 *) &s) + sizeof(s));
2129 
2131 
2132  return endsp;
2133 #elif defined(WITH_FFI)
2134  methoddesc *md = m->parseddesc;
2135  ffi_cif *pcif;
2136  void *values[md->paramcount + 2];
2137  void **pvalues = values;
2138  Cell *p;
2139  Cell *endsp;
2140  s4 i;
2141  _Jv_JNIEnv *penv;
2142 
2143  struct {
2144  stackframeinfo sfi;
2145  localref_table lrt;
2146  } s;
2147 
2148  pcif = (ffi_cif *) addrcif;
2149 
2150  /* pass env pointer */
2151 
2152  penv = (_Jv_JNIEnv *) VM_get_jnienv();
2153  *pvalues++ = &penv;
2154 
2155  /* for static methods, pass class pointer */
2156 
2157  if (m->flags & ACC_STATIC)
2158  *pvalues++ = &m->clazz;
2159 
2160  /* pass parameter to native function */
2161 
2162  for (i = 0, p = sp + md->paramslots; i < md->paramcount; i++) {
2163  if (IS_2_WORD_TYPE(md->paramtypes[i].type))
2164  p -= 2;
2165  else
2166  p--;
2167 
2168  *pvalues++ = p;
2169  }
2170 
2171  /* calculate position of return value */
2172 
2173  if (md->returntype.type == TYPE_VOID)
2174  endsp = sp + md->paramslots;
2175  else
2176  endsp = sp - (IS_2_WORD_TYPE(md->returntype.type) ? 2 : 1) + md->paramslots;
2177 
2178  global_sp = sp;
2179 
2180  /* create stackframe info structure */
2181 
2182  codegen_start_native_call(((u1 *) &s) + sizeof(s), m->code->entrypoint,
2183  (u1 *) fp, (u1 *) ra);
2184 
2185  ffi_call(pcif, FFI_FN(f), endsp, values);
2186 
2187  *exceptionptr = codegen_finish_native_call(((u1 *) &s) + sizeof(s));
2188 
2190 
2191  return endsp;
2192 #endif
2193 }
2194 
2195 
2197 {
2198  methodinfo *tmpm;
2199  u1 *entrypoint;
2200  jitdata *jd;
2201  codegendata *cd;
2202  registerdata *rd;
2203  methoddesc *md;
2204  int32_t dumpmarker;
2205 
2206  /* mark dump memory */
2207 
2208  DMARKER;
2209 
2210  /* allocate memory */
2211 
2212  jd = DNEW(jitdata);
2213 
2214  tmpm = DNEW(methodinfo);
2215  cd = DNEW(codegendata);
2216  rd = DNEW(registerdata);
2217 
2218  jd->m = tmpm;
2219  jd->flags = 0;
2220  jd->cd = cd;
2221  jd->rd = rd;
2222 
2223  /* Allocate codeinfo memory from the heap as we need to keep them. */
2224 
2225  jd->code = code_codeinfo_new(tmpm); /* XXX check allocation */
2226 
2227  /* setup code generation stuff */
2228 
2229  MSET(tmpm, 0, u1, sizeof(methodinfo));
2230 
2231  codegen_setup(jd);
2232 
2233  md = m->parseddesc;
2234 
2235  /* create method header */
2236 
2237  (void) dseg_add_unique_address(cd, NULL); /* CodeinfoPointer */
2238  (void) dseg_add_unique_s4(cd, md->paramslots * SIZEOF_VOID_P);/* FrameSize*/
2239  (void) dseg_add_unique_s4(cd, 0); /* IsSync */
2240  (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
2241  (void) dseg_add_unique_s4(cd, 0); /* IntSave */
2242  (void) dseg_add_unique_s4(cd, 0); /* FltSave */
2243  dseg_addlinenumbertablesize(cd);
2244  (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
2245 
2246 
2247  /* generate code */
2248 
2249  gen_BBSTART;
2250  gen_INVOKESTATIC(cd, (Inst **)m->stubroutine, md->paramslots, 0);
2251  gen_END(cd);
2252 
2253  gen_BBEND;
2254 
2255  codegen_finish(jd);
2256 
2257 #ifdef VM_PROFILING
2258  vm_block_insert(jd->code->mcode + jd->code->mcodelength);
2259 #endif
2260  entrypoint = jd->code->entrypoint;
2261 
2262  /* release memory */
2263 
2264  DRELEASE;
2265 
2266  return entrypoint;
2267 }
2268 
2269 
2270 /*
2271  * These are local overrides for various environment variables in Emacs.
2272  * Please do not remove this and leave it at the end of the file, where
2273  * Emacs will automagically detect them.
2274  * ---------------------------------------------------------------------
2275  * Local variables:
2276  * mode: c
2277  * indent-tabs-mode: t
2278  * c-basic-offset: 4
2279  * tab-width: 4
2280  * End:
2281  * vim:noexpandtab:sw=4:ts=4:
2282  */
val_operand_t val
#define BUILTIN_f2l
Definition: builtin.hpp:303
#define BUILTIN_d2i
Definition: builtin.hpp:311
basicblock * basicblocks
Definition: jit.hpp:141
Definition: jit.hpp:126
#define ra
Definition: md-asm.hpp:62
Cell * nativecall(functionptr f, methodinfo *m, Cell *sp, Inst *ra, Cell *fp, u1 *addrcif)
Definition: codegen.c:2042
void genarg_aRef(codegendata *cd1, java_objectheader *a)
Definition: codegen.c:110
#define MSET(ptr, byte, type, num)
Definition: memory.hpp:104
s4 dseg_add_unique_address(codegendata *cd, void *value)
Definition: dseg.cpp:525
methodinfo * methods
Definition: class.hpp:113
#define NEW(type)
Definition: memory.hpp:93
struct builtin_gen builtin_gen_table[]
Definition: codegen.c:224
s8 Cell
Definition: intrp.h:42
#define BUILTIN_newarray_float
Definition: builtin.hpp:186
#define CLEAR_global_sp
Definition: intrp.h:120
State state
Definition: jit.hpp:313
genfunctionptr gen
Definition: codegen.c:221
void * a
Definition: global.hpp:58
basicblock * next
Definition: jit.hpp:337
void genarg_aum(codegendata *cd1, unresolved_method *a)
Definition: codegen.c:194
void genarg_avftbl(codegendata *cd1, vftbl_t *a)
Definition: codegen.c:201
codeinfo * code
Definition: jit.hpp:128
int32_t argcount
Definition: instruction.hpp:64
s4 mpc
Definition: jit.hpp:345
codegendata * cd
Definition: jit.hpp:129
int32_t varindex
Definition: instruction.hpp:63
u4 flags
Definition: jit.hpp:138
#define gen_resolveanybranch(ip, target)
Definition: codegen.h:69
void genarg_i(codegendata *cd1, s4 i)
Definition: codegen.c:83
typedef void(JNICALL *jvmtiEventSingleStep)(jvmtiEnv *jvmti_env
#define BUILTIN_newarray_long
Definition: builtin.hpp:196
methoddesc * md
Definition: references.hpp:75
JNIEnv * VM_get_jnienv()
Definition: vm.cpp:2584
void genarg_acr(codegendata *cd1, constant_classref *a)
Definition: codegen.c:138
void genarg_ainst(codegendata *cd1, Inst *a)
Definition: codegen.c:180
constant_classref * ref
Definition: references.hpp:62
uint8_t u1
Definition: types.hpp:40
void dseg_add_target(codegendata *cd, basicblock *target)
Definition: dseg.cpp:565
void(* genfunctionptr)(codegendata *)
Definition: codegen.c:215
u1 * methodptr
Definition: global.hpp:40
#define BUILTIN_newarray_char
Definition: builtin.hpp:184
s4 mcodelength
Definition: code.hpp:85
java_object_t * codegen_finish_native_call(u1 *sp, u1 *pv)
branchref * branchrefs
Definition: jit.hpp:335
bool opt_verbosecall
Definition: options.cpp:76
int64_t s8
Definition: types.hpp:48
lookup_target_t * lookup
instruction * iinstr
Definition: jit.hpp:319
s4 icount
Definition: jit.hpp:318
static int code_is_leafmethod(codeinfo *code)
Definition: code.hpp:151
u1 * intrp_createcompilerstub(methodinfo *m)
Definition: codegen.c:1832
#define BUILTIN_newarray_byte
Definition: builtin.hpp:190
u1 * intrp_createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
Definition: codegen.c:1972
void genarg_aClass(codegendata *cd1, classinfo *a)
Definition: codegen.c:131
block_count * vm_block_insert(Inst *ip)
Definition: profile.c:60
#define DNEW(type)
Definition: dumpmemory.hpp:370
void vm_abort(const char *text,...)
Definition: vm.cpp:2586
void(* functionptr)(void)
Definition: global.hpp:39
void genarg_am(codegendata *cd1, methodinfo *a)
Definition: codegen.c:166
typedesc paramtypes[1]
Definition: descriptor.hpp:167
#define BUILTIN_frem
Definition: builtin.hpp:270
codeinfo * code_codeinfo_new(methodinfo *m)
Definition: code.cpp:72
void genarg_addr(codegendata *cd1, u1 *a)
Definition: codegen.c:145
java_handle_t * codegen_start_native_call(u1 *sp, u1 *pv)
#define IS_2_WORD_TYPE(a)
Definition: global.hpp:132
u1 * mcode
Definition: code.hpp:83
int32_t insindex
classref_or_classinfo c
u1 * stubroutine
Definition: method.hpp:102
s4 vftblindex
Definition: method.hpp:81
#define global_sp
Definition: intrp.h:108
branch_target_t target
Definition: instruction.hpp:57
dst_operand_t dst
functionptr builtin
Definition: codegen.c:220
flags_operand_t flags
void * Inst
Definition: intrp.h:58
void genarg_v(codegendata *cd1, Cell v)
Definition: codegen.c:76
uint16_t u2
Definition: types.hpp:43
#define BUILTIN_drem
Definition: builtin.hpp:287
#define LOCK_monitor_enter
Definition: builtin.hpp:124
constant_FMIref * fieldref
Definition: resolve.hpp:88
int32_t offset
Definition: field.hpp:66
classinfo * clazz
Definition: method.hpp:80
#define COMPILERSTUB_DATASIZE
Definition: codegen.c:1826
bool checksync
Definition: options.cpp:90
#define BUILTIN_newarray_boolean
Definition: builtin.hpp:182
imm_union * value
Definition: field.hpp:67
void exceptions_throw_internalerror(const char *message,...)
Definition: exceptions.cpp:805
void genarg_afi(codegendata *cd1, fieldinfo *a)
Definition: codegen.c:159
#define gen_branch(_inst)
Definition: codegen.c:67
#define BUILTIN_new
Definition: builtin.hpp:163
typedesc * fd
Definition: references.hpp:74
void genarg_acell(codegendata *cd1, Cell *a)
Definition: codegen.c:173
MIIterator i
typedesc returntype
Definition: descriptor.hpp:166
int32_t s4
Definition: types.hpp:45
s4 dseg_add_unique_s4(codegendata *cd, s4 value)
Definition: dseg.cpp:229
classinfo * clazz
Definition: field.hpp:55
#define BUILTIN_newarray
Definition: builtin.hpp:179
#define gen_BBEND
Definition: intrp.h:177
registerdata * rd
Definition: jit.hpp:130
#define COMPILERSTUB_SIZE
Definition: codegen.c:1829
s4 maxlocals
Definition: method.hpp:84
void genarg_aArray(codegendata *cd1, java_arrayheader *a)
Definition: codegen.c:117
s4 index
Definition: class.hpp:116
union instruction::@12 sx
#define BUILTIN_arrayinstanceof
Definition: builtin.hpp:146
#define BUILTIN_newarray_int
Definition: builtin.hpp:194
codeinfo * code
Definition: method.hpp:103
#define LOCK_monitor_exit
Definition: builtin.hpp:132
int32_t varindex
void genarg_aaTarget(codegendata *cd1, Inst **a)
Definition: codegen.c:124
s1_operand_t s1
void codegen_setup(jitdata *jd)
#define gen_BBSTART
Definition: intrp.h:176
#define BUILTIN_newarray_double
Definition: builtin.hpp:188
constant_FMIref * methodref
Definition: resolve.hpp:97
void genarg_auf(codegendata *cd1, unresolved_field *a)
Definition: codegen.c:187
#define BUILTIN_ldiv
Definition: builtin.hpp:234
methoddesc * parseddesc
Definition: method.hpp:78
#define sp
Definition: md-asm.hpp:81
#define I(value)
Definition: codegen.c:279
int memuse
Definition: reg.hpp:84
void genarg_af(codegendata *cd1, functionptr a)
Definition: codegen.c:152
void genarg_l(codegendata *cd1, s8 l)
Definition: codegen.c:103
Definition: builtin.hpp:60
#define MNEW(type, num)
Definition: memory.hpp:96
methodinfo * m
Definition: jit.hpp:127
#define BUILTIN_idiv
Definition: builtin.hpp:222
s4 type
Definition: field.hpp:60
#define BUILTIN_irem
Definition: builtin.hpp:224
#define BUILTIN_newarray_short
Definition: builtin.hpp:192
int8_t s1
Definition: types.hpp:39
static bool class_is_or_almost_initialized(classinfo *c)
Definition: class.hpp:433
void genarg_f(codegendata *cd1, float f)
Definition: codegen.c:95
u1 * createcalljavafunction(methodinfo *m)
Definition: codegen.c:2196
static int code_is_synchronized(codeinfo *code)
Definition: code.hpp:173
int16_t s2
Definition: types.hpp:42
#define INSTRUCTION_IS_UNRESOLVED(iptr)
#define vm_f2Cell(x1, x2)
Definition: intrp.h:198
struct instruction::@12::@13 s23
void genarg_b(codegendata *cd1, s4 i)
Definition: codegen.c:90
#define index2offset(_i)
Definition: codegen.c:72
const parseddesc_t parseddesc
Definition: references.hpp:105
#define MCODECHECK(icnt)
Definition: codegen.hpp:40
branchref * next
functionptr fp
Definition: builtin.hpp:63
bool intrp_codegen(jitdata *jd)
Definition: codegen.c:281
#define vm_l2twoCell(d_, hi, lo)
Definition: intrp.h:126
s4 flags
Definition: method.hpp:70
uintptr_t ptrint
Definition: types.hpp:54
#define fp
Definition: md-asm.hpp:79
#define OFFSET(s, el)
Definition: memory.hpp:90
branch_target_t * table
#define BUILTIN_d2l
Definition: builtin.hpp:315
u1 * entrypoint
Definition: code.hpp:84
void codegen_finish(jitdata *jd)
#define BUILTIN_f2i
Definition: builtin.hpp:299
#define CNEW(type, num)
Definition: codememory.hpp:34
#define BUILTIN_lrem
Definition: builtin.hpp:236