CACAO
emit.cpp
Go to the documentation of this file.
1 /* src/vm/jit/aarch64/emit.cpp - Aarch64 code emitter functions
2 
3  Copyright (C) 1996-2014
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 #include "vm/types.hpp"
28 
29 #include <cassert>
30 #include <stdint.h>
31 
32 #include "md-abi.hpp"
33 
35 
36 #include "mm/memory.hpp"
37 
38 #include "threads/lock.hpp"
39 
40 #include "vm/descriptor.hpp" // for typedesc, methoddesc, etc
41 #include "vm/options.hpp"
42 
43 #include "vm/jit/abi.hpp"
44 #include "vm/jit/abi-asm.hpp"
45 #include "vm/jit/asmpart.hpp"
46 #include "vm/jit/builtin.hpp"
47 #include "vm/jit/code.hpp"
49 #include "vm/jit/dseg.hpp"
50 #include "vm/jit/emit-common.hpp"
51 #include "vm/jit/jit.hpp"
53 #include "vm/jit/replace.hpp"
54 #include "vm/jit/trace.hpp"
55 #include "vm/jit/trap.hpp"
56 
58 
59 
60 /* emit_load *******************************************************************
61 
62  Emits a possible load of an operand.
63 
64 *******************************************************************************/
65 
66 s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
67 {
68  AsmEmitter asme(jd->cd);
69  s4 disp;
70  s4 reg;
71 
72  if (IS_INMEMORY(src->flags)) {
74 
75  disp = src->vv.regoff;
76 
77  switch (src->type) {
78  case TYPE_INT:
79  asme.ild(tempreg, REG_SP, disp);
80  break;
81  case TYPE_LNG:
82  asme.lld(tempreg, REG_SP, disp);
83  break;
84  case TYPE_ADR:
85  asme.ald(tempreg, REG_SP, disp);
86  break;
87  case TYPE_FLT:
88  asme.fld(tempreg, REG_SP, disp);
89  break;
90  case TYPE_DBL:
91  asme.dld(tempreg, REG_SP, disp);
92  break;
93  default:
94  vm_abort("emit_load: unknown type %d", src->type);
95  break;
96  }
97 
98  reg = tempreg;
99  }
100  else
101  reg = src->vv.regoff;
102 
103  return reg;
104 }
105 
106 
107 /* emit_store ******************************************************************
108 
109  Emit a possible store for the given variable.
110 
111 *******************************************************************************/
112 
113 void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
114 {
115  AsmEmitter asme(jd->cd);
116  s4 disp;
117 
118  if (IS_INMEMORY(dst->flags)) {
119  COUNT_SPILLS;
120 
121  disp = dst->vv.regoff;
122 
123  switch (dst->type) {
124  case TYPE_INT:
125  asme.ist(d, REG_SP, disp);
126  break;
127  case TYPE_LNG:
128  asme.lst(d, REG_SP, disp);
129  break;
130  case TYPE_ADR:
131  asme.ast(d, REG_SP, disp);
132  break;
133  case TYPE_FLT:
134  asme.fst(d, REG_SP, disp);
135  break;
136  case TYPE_DBL:
137  asme.dst(d, REG_SP, disp);
138  break;
139  default:
140  vm_abort("emit_store: unknown type %d", dst->type);
141  break;
142  }
143  }
144 }
145 
146 
147 /* emit_copy *******************************************************************
148 
149  Generates a register/memory to register/memory copy.
150 
151 *******************************************************************************/
152 
153 void emit_copy(jitdata *jd, instruction *iptr)
154 {
155  codegendata *cd;
156  varinfo *src;
157  varinfo *dst;
158  s4 s1, d;
159 
160  /* get required compiler data */
161 
162  cd = jd->cd;
163 
164  /* get source and destination variables */
165 
166  src = VAROP(iptr->s1);
167  dst = VAROP(iptr->dst);
168 
169  if ((src->vv.regoff != dst->vv.regoff) ||
170  ((src->flags ^ dst->flags) & INMEMORY)) {
171 
172  if ((src->type == TYPE_RET) || (dst->type == TYPE_RET)) {
173  /* emit nothing, as the value won't be used anyway */
174  return;
175  }
176 
177  /* If one of the variables resides in memory, we can eliminate
178  the register move from/to the temporary register with the
179  order of getting the destination register and the load. */
180 
181  if (IS_INMEMORY(src->flags)) {
182  d = codegen_reg_of_var(iptr->opc, dst, REG_IFTMP);
183  s1 = emit_load(jd, iptr, src, d);
184  }
185  else {
186  s1 = emit_load(jd, iptr, src, REG_IFTMP);
187  d = codegen_reg_of_var(iptr->opc, dst, s1);
188  }
189 
190  if (s1 != d) {
191  switch (src->type) {
192  case TYPE_INT:
193  case TYPE_LNG:
194  case TYPE_ADR:
195  M_MOV(s1, d);
196  break;
197  case TYPE_FLT:
198  M_FMOV(s1, d);
199  break;
200  case TYPE_DBL:
201  M_DMOV(s1, d);
202  break;
203  default:
204  vm_abort("emit_copy: unknown type %d", src->type);
205  break;
206  }
207  }
208 
209  emit_store(jd, iptr, dst, d);
210  }
211 }
212 
213 
214 /* emit_iconst *****************************************************************
215 
216  XXX
217 
218 *******************************************************************************/
219 
220 void emit_iconst(codegendata *cd, s4 d, s4 value)
221 {
222  AsmEmitter asme(cd);
223  asme.iconst(d, value);
224 }
225 
226 
227 /* emit_lconst *****************************************************************
228 
229  XXX
230 
231 *******************************************************************************/
232 
233 void emit_lconst(codegendata *cd, s4 d, s8 value)
234 {
235  AsmEmitter asme(cd);
236  asme.lconst(d, value);
237 }
238 
239 
240 /**
241  * Emits code comparing a single register
242  */
243 void emit_icmp_imm(codegendata* cd, int reg, int32_t value) {
244  AsmEmitter asme(cd);
245 
246  if (value >= 0 && value <= 4095) {
247  asme.icmp_imm(reg, value);
248  } else if ((-value) >= 0 && (-value) <= 4095) {
249  asme.icmn_imm(reg, -value);
250  } else {
251  asme.iconst(REG_ITMP2, value);
252  asme.icmp(reg, REG_ITMP2);
253  }
254 }
255 
256 
257 /* emit_branch *****************************************************************
258 
259  Emits the code for conditional and unconditional branchs.
260 
261 *******************************************************************************/
262 
263 void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 opt)
264 {
265  s4 checkdisp;
266  s4 branchdisp;
267  AsmEmitter asme(cd);
268 
269  /* calculate the different displacements */
270 
271  checkdisp = disp;
272  branchdisp = disp >> 2;
273 
274  /* check which branch to generate */
275 
276  if (condition == BRANCH_UNCONDITIONAL) {
277  /* check displacement for overflow */
278 
279  if ((checkdisp < (s4) 0xffe00000) || (checkdisp > (s4) 0x001fffff)) {
280  /* if the long-branches flag isn't set yet, do it */
281 
283  log_println("setting error");
284  cd->flags |= (CODEGENDATA_FLAG_ERROR |
286  }
287 
288  vm_abort("emit_branch: emit unconditional long-branch code");
289  }
290  else {
291  asme.b(branchdisp);
292  }
293  }
294  else {
295  /* and displacement for overflow */
296 
297  if ((checkdisp < (s4) 0xffe00000) || (checkdisp > (s4) 0x001fffff)) {
298  /* if the long-branches flag isn't set yet, do it */
299 
301  log_println("setting error");
302  cd->flags |= (CODEGENDATA_FLAG_ERROR |
304  }
305 
306  vm_abort("emit_branch: emit conditional long-branch code");
307  }
308  else {
309  switch (condition) {
310  case BRANCH_EQ:
311  asme.b_eq(branchdisp);
312  break;
313  case BRANCH_NE:
314  asme.b_ne(branchdisp);
315  break;
316  case BRANCH_LT:
317  asme.b_lt(branchdisp);
318  break;
319  case BRANCH_GE:
320  asme.b_ge(branchdisp);
321  break;
322  case BRANCH_GT:
323  asme.b_gt(branchdisp);
324  break;
325  case BRANCH_LE:
326  asme.b_le(branchdisp);
327  break;
328  case BRANCH_UGT:
329  asme.b_hi(branchdisp);
330  break;
331  default:
332  vm_abort("emit_branch: unknown condition %d", condition);
333  break;
334  }
335  }
336  }
337 }
338 
339 
340 /* emit_arithmetic_check *******************************************************
341 
342  Emit an ArithmeticException check.
343 
344 *******************************************************************************/
345 
347 {
348  if (INSTRUCTION_MUST_CHECK(iptr)) {
349  AsmEmitter asme(cd);
350  asme.cbnz(reg, 2);
352  }
353 }
354 
355 
356 /* emit_arrayindexoutofbounds_check ********************************************
357 
358  Emit an ArrayIndexOutOfBoundsException check.
359 
360 *******************************************************************************/
361 
363 {
364  if (INSTRUCTION_MUST_CHECK(iptr)) {
365  AsmEmitter asme(cd);
366  asme.ild(REG_ITMP3, s1, OFFSET(java_array_t, size));
367  asme.icmp(s2, REG_ITMP3);
368  asme.b_cc(2);
370  }
371 }
372 
373 
374 /* emit_arraystore_check *******************************************************
375 
376  Emit an ArrayStoreException check.
377 
378 *******************************************************************************/
379 
381 {
382  if (INSTRUCTION_MUST_CHECK(iptr)) {
383  AsmEmitter asme(cd);
384  asme.cbnz(REG_RESULT, 2);
386  }
387 }
388 
389 
390 /* emit_classcast_check ********************************************************
391 
392  Emit a ClassCastException check.
393 
394 *******************************************************************************/
395 
396 void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1)
397 {
398  if (INSTRUCTION_MUST_CHECK(iptr)) {
399  AsmEmitter asme(cd);
400  switch (condition) {
401  case BRANCH_EQ:
402  asme.b_ne(2);
403  break;
404  case BRANCH_LE:
405  asme.b_gt(2);
406  break;
407  case BRANCH_NE:
408  asme.b_eq(2);
409  break;
410  case BRANCH_GT:
411  asme.b_le(2);
412  break;
413  case BRANCH_LT:
414  asme.b_ge(2);
415  break;
416  default:
417  vm_abort("emit_classcast_check: unknown condition %d", condition);
418  break;
419  }
421  }
422 }
423 
424 
425 /* emit_nullpointer_check ******************************************************
426 
427  Emit a NullPointerException check.
428 
429 *******************************************************************************/
430 
432 {
433  if (INSTRUCTION_MUST_CHECK(iptr)) {
434  AsmEmitter asme(cd);
435  asme.cbnz(reg, 2);
437  }
438 }
439 
440 
441 /* emit_exception_check ********************************************************
442 
443  Emit an Exception check.
444 
445 *******************************************************************************/
446 
448 {
449  if (INSTRUCTION_MUST_CHECK(iptr)) {
450  AsmEmitter asme(cd);
451  asme.cbnz(REG_RESULT, 2);
453  }
454 }
455 
456 
457 /* emit_trap_compiler **********************************************************
458 
459  Emit a trap instruction which calls the JIT compiler.
460 
461 *******************************************************************************/
462 
464 {
466 }
467 
469 {
471 }
472 
473 
474 /* emit_trap *******************************************************************
475 
476  Emit a trap instruction and return the original machine code.
477 
478 *******************************************************************************/
479 
480 uint32_t emit_trap(codegendata *cd)
481 {
482  /* Get machine code which is patched back in later. The
483  trap is 1 instruction word long. */
484  uint32_t mcode = *((uint32_t*) cd->mcodeptr);
485 
486  emit_trap(cd, 0, TRAP_PATCHER);
487 
488  return mcode;
489 }
490 
491 
492 /**
493  * Emit code to recompute the procedure vector.
494  */
496 {
497  int32_t disp = (int32_t) (cd->mcodeptr - cd->mcodebase);
498 
499  AsmEmitter asme(cd);
500  asme.lda(REG_PV, REG_RA, -disp);
501 }
502 
503 
504 /**
505  * Generates synchronization code to enter a monitor.
506  */
507 void emit_monitor_enter(jitdata* jd, int32_t syncslot_offset)
508 {
509  int32_t p;
510  int32_t disp;
511 
512  // Get required compiler data.
513  methodinfo* m = jd->m;
514  codegendata* cd = jd->cd;
515  AsmEmitter asme(cd);
516 
517 #if !defined(NDEBUG)
519  asme.lda(REG_SP, REG_SP, -(INT_ARG_CNT + FLT_ARG_CNT) * 8);
520 
521  for (p = 0; p < INT_ARG_CNT; p++)
522  asme.lst(abi_registers_integer_argument[p], REG_SP, p * 8);
523 
524  for (p = 0; p < FLT_ARG_CNT; p++)
525  asme.dst(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
526 
527  syncslot_offset += (INT_ARG_CNT + FLT_ARG_CNT) * 8;
528  }
529 #endif /* !defined(NDEBUG) */
530 
531  /* decide which monitor enter function to call */
532 
533  if (m->flags & ACC_STATIC) {
534  disp = dseg_add_address(cd, &m->clazz->object.header);
535  asme.lld(REG_A0, REG_PV, disp);
536  }
537  else {
538  asme.cbnz(REG_A0, 2);
540  }
541 
542  asme.lst(REG_A0, REG_SP, syncslot_offset);
544  asme.lld(REG_PV, REG_PV, disp);
545  asme.blr(REG_PV);
546  emit_recompute_pv(cd);
547 
548 #if !defined(NDEBUG)
550  for (p = 0; p < INT_ARG_CNT; p++)
551  asme.lld(abi_registers_integer_argument[p], REG_SP, p * 8);
552 
553  for (p = 0; p < FLT_ARG_CNT; p++)
554  asme.dld(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
555 
556  asme.lda(REG_SP, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT) * 8);
557  }
558 #endif
559 }
560 
561 
562 /**
563  * Generates synchronization code to leave a monitor.
564  */
565 void emit_monitor_exit(jitdata* jd, int32_t syncslot_offset)
566 {
567  int32_t disp;
568 
569  // Get required compiler data.
570  methodinfo* m = jd->m;
571  codegendata* cd = jd->cd;
572  AsmEmitter asme(cd);
573 
574  methoddesc* md = m->parseddesc;
575 
576  switch (md->returntype.type) {
577  case TYPE_INT:
578  case TYPE_LNG:
579  case TYPE_ADR:
580  asme.lst(REG_RESULT, REG_SP, syncslot_offset + 8);
581  break;
582  case TYPE_FLT:
583  case TYPE_DBL:
584  asme.dst(REG_FRESULT, REG_SP, syncslot_offset + 8);
585  break;
586  case TYPE_VOID:
587  break;
588  default:
589  assert(false);
590  break;
591  }
592 
593  asme.lld(REG_A0, REG_SP, syncslot_offset);
595  asme.lld(REG_PV, REG_PV, disp);
596  asme.blr(REG_PV);
597  emit_recompute_pv(cd);
598 
599  switch (md->returntype.type) {
600  case TYPE_INT:
601  case TYPE_LNG:
602  case TYPE_ADR:
603  asme.lld(REG_RESULT, REG_SP, syncslot_offset + 8);
604  break;
605  case TYPE_FLT:
606  case TYPE_DBL:
607  asme.dld(REG_FRESULT, REG_SP, syncslot_offset + 8);
608  break;
609  case TYPE_VOID:
610  break;
611  default:
612  assert(false);
613  break;
614  }
615 }
616 
617 
618 /* emit_verbosecall_enter ******************************************************
619 
620  Generates the code for the call trace.
621 
622 *******************************************************************************/
623 
624 #if !defined(NDEBUG)
626 {
627  methodinfo *m;
628  codeinfo *code;
629  codegendata *cd;
630  registerdata *rd;
631  methoddesc *md;
632  int32_t stackframesize;
633  s4 disp;
634  s4 i, j, s;
635 
636  /* get required compiler data */
637 
638  m = jd->m;
639  code = jd->code;
640  cd = jd->cd;
641  rd = jd->rd;
642 
643  md = m->parseddesc;
644  AsmEmitter asme(cd);
645 
646  /* mark trace code */
647 
648  asme.nop();
649 
650  stackframesize = ARG_CNT + TMP_CNT + md->paramcount + 1;
651  stackframesize += stackframesize % 2;
652 
653  asme.lda(REG_SP, REG_SP, -(stackframesize * 8));
654  asme.ast(REG_RA, REG_SP, 0 * 8);
655 
656  /* save all argument and temporary registers for leaf methods */
657 
658  if (code_is_leafmethod(code)) {
659  j = 1 + md->paramcount;
660 
661  for (i = 0; i < INT_ARG_CNT; i++, j++)
662  asme.lst(abi_registers_integer_argument[i], REG_SP, j * 8);
663 
664  for (i = 0; i < FLT_ARG_CNT; i++, j++)
665  asme.dst(abi_registers_float_argument[i], REG_SP, j * 8);
666 
667  for (i = 0; i < INT_TMP_CNT; i++, j++)
668  asme.lst(rd->tmpintregs[i], REG_SP, j * 8);
669 
670  for (i = 0; i < FLT_TMP_CNT; i++, j++)
671  asme.dst(rd->tmpfltregs[i], REG_SP, j * 8);
672  }
673 
674  /* save argument registers */
675 
676  for (i = 0; i < md->paramcount; i++) {
677  if (!md->params[i].inmemory) {
678  s = md->params[i].regoff;
679 
680  switch (md->paramtypes[i].type) {
681  case TYPE_ADR:
682  case TYPE_INT:
683  case TYPE_LNG:
684  asme.lst(s, REG_SP, (1 + i) * 8);
685  break;
686  case TYPE_FLT:
687  case TYPE_DBL:
688  asme.dst(s, REG_SP, (1 + i) * 8);
689  break;
690  default:
691  assert(false);
692  break;
693  }
694  }
695  }
696 
697  disp = dseg_add_address(cd, m);
698  asme.lld(REG_A0, REG_PV, disp);
699  asme.ladd_imm(REG_A1, REG_SP, 1 * 8);
700  asme.lda(REG_A2, REG_SP, stackframesize * 8 + cd->stackframesize * 8);
701 
703  asme.lld(REG_PV, REG_PV, disp);
704  asme.blr(REG_PV);
705  disp = (s4) (cd->mcodeptr - cd->mcodebase);
706  asme.lda(REG_PV, REG_RA, -disp);
707  asme.lld(REG_RA, REG_SP, 0 * 8);
708 
709  /* restore argument registers */
710 
711  for (i = 0; i < md->paramcount; i++) {
712  if (!md->params[i].inmemory) {
713  s = md->params[i].regoff;
714 
715  switch (md->paramtypes[i].type) {
716  case TYPE_ADR:
717  case TYPE_INT:
718  case TYPE_LNG:
719  asme.lld(s, REG_SP, (1 + i) * 8);
720  break;
721  case TYPE_FLT:
722  case TYPE_DBL:
723  asme.dld(s, REG_SP, (1 + i) * 8);
724  break;
725  default:
726  assert(false);
727  break;
728  }
729  }
730  }
731 
732  /* restore all argument and temporary registers for leaf methods */
733 
734  if (code_is_leafmethod(code)) {
735  j = 1 + md->paramcount;
736 
737  for (i = 0; i < INT_ARG_CNT; i++, j++)
738  asme.lld(abi_registers_integer_argument[i], REG_SP, j * 8);
739 
740  for (i = 0; i < FLT_ARG_CNT; i++, j++)
741  asme.dld(abi_registers_float_argument[i], REG_SP, j * 8);
742 
743  for (i = 0; i < INT_TMP_CNT; i++, j++)
744  asme.lld(rd->tmpintregs[i], REG_SP, j * 8);
745 
746  for (i = 0; i < FLT_TMP_CNT; i++, j++)
747  asme.dld(rd->tmpfltregs[i], REG_SP, j * 8);
748  }
749 
750  asme.lda(REG_SP, REG_SP, stackframesize * 8);
751 
752  /* mark trace code */
753 
754  asme.nop();
755 }
756 #endif /* !defined(NDEBUG) */
757 
758 
759 /* emit_verbosecall_exit *******************************************************
760 
761  Generates the code for the call trace.
762 
763 *******************************************************************************/
764 
765 #if !defined(NDEBUG)
767 {
768  methodinfo *m;
769  codegendata *cd;
770  methoddesc *md;
771  s4 disp;
772 
773  /* get required compiler data */
774 
775  m = jd->m;
776  cd = jd->cd;
777 
778  md = m->parseddesc;
779  AsmEmitter asme(cd);
780 
781  /* mark trace code */
782 
783  asme.nop();
784 
785  asme.lsub_imm(REG_SP, REG_SP, 2 * 8);
786  asme.lst(REG_RA, REG_SP, 0 * 8);
787 
788  /* save return value */
789 
790  switch (md->returntype.type) {
791  case TYPE_ADR:
792  case TYPE_INT:
793  case TYPE_LNG:
794  asme.lst(REG_RESULT, REG_SP, 1 * 8);
795  break;
796  case TYPE_FLT:
797  case TYPE_DBL:
798  asme.dst(REG_FRESULT, REG_SP, 1 * 8);
799  break;
800  case TYPE_VOID:
801  break;
802  default:
803  assert(false);
804  break;
805  }
806 
807  disp = dseg_add_address(cd, m);
808  asme.lld(REG_A0, REG_PV, disp);
809  asme.ladd_imm(REG_A1, REG_SP, 1 * 8);
810 
812  asme.lld(REG_PV, REG_PV, disp);
813  asme.blr(REG_PV);
814  disp = (cd->mcodeptr - cd->mcodebase);
815  asme.lda(REG_PV, REG_RA, -disp);
816 
817  /* restore return value */
818 
819  switch (md->returntype.type) {
820  case TYPE_ADR:
821  case TYPE_INT:
822  case TYPE_LNG:
823  asme.lld(REG_RESULT, REG_SP, 1 * 8);
824  break;
825  case TYPE_FLT:
826  case TYPE_DBL:
827  asme.dld(REG_FRESULT, REG_SP, 1 * 8);
828  break;
829  case TYPE_VOID:
830  break;
831  default:
832  assert(false);
833  break;
834  }
835 
836  asme.lld(REG_RA, REG_SP, 0 * 8);
837  asme.ladd_imm(REG_SP, REG_SP, 2 * 8);
838 
839  /* mark trace code */
840 
841  asme.nop();
842 }
843 #endif /* !defined(NDEBUG) */
844 
845 
846 /*
847  * These are local overrides for various environment variables in Emacs.
848  * Please do not remove this and leave it at the end of the file, where
849  * Emacs will automagically detect them.
850  * ---------------------------------------------------------------------
851  * Local variables:
852  * mode: c++
853  * indent-tabs-mode: t
854  * c-basic-offset: 4
855  * tab-width: 4
856  * End:
857  * vim:noexpandtab:sw=4:ts=4:
858  */
void ald(u1 xt, u1 xn, s2 imm)
Definition: codegen.hpp:109
const s4 abi_registers_float_argument[]
Definition: md-abi.cpp:107
#define REG_SP
Definition: md-abi.hpp:53
#define CODEGENDATA_FLAG_ERROR
java_object_t header
Definition: class.hpp:73
union varinfo::@19 vv
#define REG_PV
Definition: md-abi.hpp:42
dummy_java_lang_Class object
Definition: class.hpp:88
void icmp(u1 wn, u1 wm)
Definition: codegen.hpp:100
#define REG_A1
Definition: md-abi.hpp:36
Definition: jit.hpp:126
void emit_monitor_exit(jitdata *jd, int32_t syncslot_offset)
Generates synchronization code to leave a monitor.
Definition: emit.cpp:565
#define REG_A0
Definition: md-abi.hpp:35
paramdesc * params
Definition: descriptor.hpp:164
#define BRANCH_LE
#define JITDATA_HAS_FLAG_VERBOSECALL(jd)
Definition: jit.hpp:227
#define BRANCH_NE
#define BRANCH_GT
void emit_monitor_enter(jitdata *jd, int32_t syncslot_offset)
Generates synchronization code to enter a monitor.
Definition: emit.cpp:507
#define BRANCH_EQ
const s4 abi_registers_integer_argument[]
Definition: md-abi.cpp:64
s4 dseg_add_address(codegendata *cd, void *value)
Definition: dseg.cpp:542
codeinfo * code
Definition: jit.hpp:128
void dst(u1 xt, u1 xn, s2 imm)
Definition: codegen.hpp:125
#define REG_FRESULT
Definition: md-abi.hpp:59
s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
#define BRANCH_UNCONDITIONAL
void lconst(u1 xt, s8 value)
Definition: codegen.hpp:146
#define dseg_add_functionptr(cd, value)
Definition: dseg.hpp:39
codegendata * cd
Definition: jit.hpp:129
#define REG_A2
Definition: md-abi.hpp:37
void b(s4 imm)
Definition: codegen.hpp:177
void icmp_imm(u1 wd, u2 imm)
Definition: codegen.hpp:95
int * tmpfltregs
Definition: reg.hpp:72
void b_eq(s4 imm)
Definition: codegen.hpp:178
void emit_arraystore_check(codegendata *cd, instruction *iptr)
Definition: emit.cpp:380
#define COUNT_SPILLS
Definition: jit.hpp:108
void cbnz(u1 xn, s4 imm)
Definition: codegen.hpp:197
void trace_java_call_exit(methodinfo *m, uint64_t *return_regs)
Definition: trace.cpp:240
Type type
Definition: reg.hpp:44
void fst(u1 xt, u1 xn, s2 imm)
Definition: codegen.hpp:124
void blr(u1 xn)
Definition: codegen.hpp:193
#define CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)
int64_t s8
Definition: types.hpp:48
void b_ne(s4 imm)
Definition: codegen.hpp:179
void log_println(const char *text,...)
Definition: logging.cpp:193
#define CODEGENDATA_FLAG_LONGBRANCHES
void b_gt(s4 imm)
Definition: codegen.hpp:190
JNIEnv jthread jobject jclass jlong size
Definition: jvmti.h:387
Definition: reg.hpp:43
void emit_recompute_pv(codegendata *cd)
Emit code to recompute the procedure vector.
Definition: emit.cpp:495
void emit_abstractmethoderror_trap(codegendata *cd)
Definition: emit.cpp:468
void ist(u1 xt, u1 xn, s2 imm)
Definition: codegen.hpp:120
static int code_is_leafmethod(codeinfo *code)
Definition: code.hpp:151
#define M_FMOV(b, c)
Definition: codegen.hpp:341
#define REG_IFTMP
Definition: md-abi.hpp:69
void vm_abort(const char *text,...)
Definition: vm.cpp:2586
s4 regoff
Definition: reg.hpp:47
void b_lt(s4 imm)
Definition: codegen.hpp:189
void emit_verbosecall_enter(jitdata *jd)
Definition: emit.cpp:625
typedesc paramtypes[1]
Definition: descriptor.hpp:167
void ild(u1 xt, u1 xn, s2 imm)
Definition: codegen.hpp:107
void emit_exception_check(codegendata *cd, instruction *iptr)
Definition: emit.cpp:447
void ast(u1 xt, u1 xn, s2 imm)
Definition: codegen.hpp:122
void trace_java_call_enter(methodinfo *m, uint64_t *arg_regs, uint64_t *stack)
Definition: trace.cpp:149
void ladd_imm(u1 xd, u1 xn, u4 imm)
Definition: codegen.hpp:201
#define FLT_TMP_CNT
Definition: md-abi.hpp:82
void emit_lconst(codegendata *cd, s4 d, s8 value)
Definition: emit.cpp:233
dst_operand_t dst
#define LOCK_monitor_enter
Definition: builtin.hpp:124
classinfo * clazz
Definition: method.hpp:80
#define ARG_CNT
Definition: abi-asm.hpp:41
#define BRANCH_GE
void b_ge(s4 imm)
Definition: codegen.hpp:188
void b_le(s4 imm)
Definition: codegen.hpp:191
#define INT_ARG_CNT
Definition: md-abi.hpp:74
void emit_trap_compiler(codegendata *cd)
Definition: emit.cpp:463
void lst(u1 xt, u1 xn, s2 imm)
Definition: codegen.hpp:121
void lsub_imm(u1 xd, u1 xn, u4 imm)
Definition: codegen.hpp:212
void emit_trap(codegendata *cd, u1 Xd, int type)
Definition: emit-asm.hpp:563
MIIterator i
s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
Definition: emit.cpp:66
#define BRANCH_UGT
typedesc returntype
Definition: descriptor.hpp:166
int32_t s4
Definition: types.hpp:45
void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
Definition: emit.cpp:113
void b_cc(s4 imm)
Definition: codegen.hpp:181
registerdata * rd
Definition: jit.hpp:130
void dld(u1 xt, u1 xn, s2 imm)
Definition: codegen.hpp:112
#define REG_RA
Definition: md-abi.hpp:41
void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg)
Definition: emit.cpp:346
#define LOCK_monitor_exit
Definition: builtin.hpp:132
#define M_MOV(a, b)
Definition: codegen.hpp:340
bool inmemory
Definition: descriptor.hpp:151
#define REG_ITMP2
Definition: md-abi.hpp:47
void emit_icmp_imm(codegendata *cd, int reg, int32_t value)
Emits code comparing a single register.
Definition: emit.cpp:243
void emit_copy(jitdata *jd, instruction *iptr)
Definition: emit.cpp:153
s1_operand_t s1
#define TMP_CNT
Definition: abi-asm.hpp:42
void lld(u1 xt, u1 xn, s2 imm)
Definition: codegen.hpp:108
uint32_t u4
Definition: types.hpp:46
#define BRANCH_LT
#define INT_TMP_CNT
Definition: md-abi.hpp:75
void b_hi(s4 imm)
Definition: codegen.hpp:186
void lda(u1 xd, u1 xn, s4 imm)
Definition: codegen.hpp:172
methoddesc * parseddesc
Definition: method.hpp:78
void icmn_imm(u1 wd, u2 imm)
Definition: codegen.hpp:97
#define VAROP(v)
Definition: jit.hpp:251
int * tmpintregs
Definition: reg.hpp:70
methodinfo * m
Definition: jit.hpp:127
static bool IS_INMEMORY(s4 flags)
Definition: stack.hpp:51
void nop()
Definition: codegen.hpp:104
#define FLT_ARG_CNT
Definition: md-abi.hpp:81
s4 flags
Definition: reg.hpp:45
void iconst(u1 xt, s4 value)
Definition: codegen.hpp:130
void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1)
Definition: emit.cpp:396
#define REG_METHODPTR
Definition: md-abi.hpp:43
void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 opt)
Definition: emit.cpp:263
int8_t s1
Definition: types.hpp:39
int16_t s2
Definition: types.hpp:42
#define REG_ZERO
Definition: md-abi.hpp:54
void emit_iconst(codegendata *cd, s4 d, s4 value)
Definition: emit.cpp:220
#define REG_ITMP3
Definition: md-abi.hpp:48
s4 flags
Definition: method.hpp:70
void fld(u1 xt, u1 xn, s2 imm)
Definition: codegen.hpp:111
void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2)
Definition: emit.cpp:362
void emit_verbosecall_exit(jitdata *jd)
Definition: emit.cpp:766
uint32_t regoff
Definition: descriptor.hpp:153
#define OFFSET(s, el)
Definition: memory.hpp:90
#define INSTRUCTION_MUST_CHECK(iptr)
#define REG_RESULT
Definition: md-abi.hpp:33
void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
Definition: emit.cpp:431
#define M_DMOV(b, c)
Definition: codegen.hpp:342