CACAO
jit.cpp
Go to the documentation of this file.
1 /* src/vm/jit/jit.cpp - Just-In-Time compiler
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 #include <cassert> // for assert
26 #include <stdint.h> // for uintptr_t
27 #include "config.h" // for ENABLE_JIT, etc
28 #include "md.hpp" // for md_cacheflush
29 #include "mm/dumpmemory.hpp" // for DumpMemory, DumpMemoryArea
30 #include "native/native.hpp" // for NativeMethods
31 #include "threads/mutex.hpp" // for Mutex
32 #include "toolbox/logging.hpp" // for log_message_method, etc
33 #include "vm/class.hpp" // for classinfo
34 #include "vm/global.hpp" // for functionptr
35 #include "vm/globals.hpp"
36 #include "vm/hook.hpp" // for jit_generated
37 #include "vm/initialize.hpp" // for initialize_class
38 #include "vm/jit/jit.hpp"
39 #include "vm/jit/allocator/simplereg.hpp" // for regalloc, etc
40 #include "vm/jit/cfg.hpp" // for cfg_build
41 #include "vm/jit/code.hpp" // for codeinfo, etc
42 #include "vm/jit/codegen-common.hpp" // for codegen_setup, etc
43 #include "vm/jit/disass.hpp"
44 #include "vm/jit/dseg.hpp" // for dseg_display
45 #include "vm/jit/ir/bytecode.hpp"
46 #include "vm/jit/ir/icmd.hpp" // for ::ICMD_IFNONNULL, etc
47 #include "vm/jit/optimizing/ifconv.hpp" // for ifconv_static
49 #include "vm/jit/parse.hpp" // for parse
50 #include "vm/jit/reg.hpp" // for reg_setup, registerdata
51 #include "vm/jit/replace.hpp" // for replace_activate_replacement_points
52 #include "vm/jit/show.hpp" // for show_filters_apply, etc
53 #include "vm/jit/stack.hpp" // for stack_analyse, stack_init
54 #include "vm/jit/stubs.hpp" // for NativeStub
55 #include "vm/jit/verify/typecheck.hpp" // for typecheck
56 #include "vm/method.hpp" // for methodinfo, method_print
57 #include "vm/options.hpp" // for compileverbose, etc
58 #include "vm/rt-timing.hpp"
59 #include "vm/statistics.hpp" // for StatSumGroup, StatVar, etc
60 #include "vm/types.hpp" // for u1, s4, ptrint
61 #include "vm/vm.hpp" // for VM, vm_abort
62 
63 #if defined(ENABLE_LSRA) && !defined(ENABLE_SSA)
64 # include "vm/jit/allocator/lsra.hpp"
65 #endif
66 
67 #if defined(ENABLE_SSA)
69 # include "vm/jit/optimizing/ssa.hpp"
70 #endif
71 
72 #if defined(ENABLE_INLINING)
73 # include "vm/jit/inline/inline.hpp"
74 #endif
75 
76 #if defined(ENABLE_IFCONV)
78 #endif
79 
80 #if defined(ENABLE_LOOP)
81 # include "vm/jit/loop/loop.hpp"
82 #endif
83 
84 #if defined(ENABLE_COMPILER2)
88 #endif
89 
90 /* debug macros ***************************************************************/
91 
92 #if !defined(NDEBUG)
93 #define DEBUG_JIT_COMPILEVERBOSE(x) \
94  do { \
95  if (compileverbose) { \
96  log_message_method(x, m); \
97  } \
98  } while (0)
99 #else
100 #define DEBUG_JIT_COMPILEVERBOSE(x) /* nothing */
101 #endif
102 
103 #if !defined(NDEBUG)
104 # define TRACECOMPILERCALLS() \
105  do { \
106  if (opt_TraceCompilerCalls) { \
107  log_start(); \
108  log_print("[JIT compiler started: method="); \
109  method_print(m); \
110  log_print("]"); \
111  log_finish(); \
112  } \
113  } while (0)
114 #else
115 # define TRACECOMPILERCALLS()
116 #endif
117 
118 STAT_REGISTER_VAR(int,count_jit_calls,0,"jit calls","Number of JIT compiler calls")
119 STAT_REGISTER_VAR(int,count_methods,0,"compiled methods","Number of compiled methods")
120 // TODO regression: old framework also printed (count_javacodesize - count_methods * 18)
121 STAT_REGISTER_VAR(int,count_javacodesize,0,"java code size","Size of compiled JavaVM instructions")
122 STAT_REGISTER_VAR(int,count_javaexcsize,0,"java exc.tbl. size","Size of compiled Exception Tables")
123 STAT_REGISTER_VAR(int,count_tryblocks,0,"try blocks","Number of Try-Blocks")
124 STAT_REGISTER_VAR(int,count_methods_allocated_by_lsra,0,"meth. alloc. lsra","Methods allocated by LSRA")
125 
126 STAT_REGISTER_VAR_EXTERN(int,count_interface_size,0,"interface size","Number of interface slots")
127 STAT_REGISTER_VAR_EXTERN(int,count_locals_conflicts,0,"locals conflicts","Conflicts between local Variables")
128 STAT_REGISTER_VAR_EXTERN(int,count_locals_spilled,0,"locals spilled","Local Variables held in Memory")
129 STAT_REGISTER_VAR_EXTERN(int,count_locals_register,0,"locals register","Local Variables held in Registers")
130 STAT_REGISTER_VAR_EXTERN(int,count_ss_spilled,0,"ss spilled","Stackslots held in Memory")
131 STAT_REGISTER_VAR_EXTERN(int,count_ss_register,0,"ss register","Stackslots held in Registers")
132 STAT_REGISTER_VAR_EXTERN(int,count_argument_reg_ss,0,"argument reg ss","Number of Argument stack slots in register")
133 STAT_REGISTER_VAR_EXTERN(int,count_argument_mem_ss,0,"argument mem ss","Number of Argument stack slots in memory")
134 
135 STAT_REGISTER_SUM_GROUP(spill_write_stat,"spills write","Number of Spills (write to memory)")
136 STAT_REGISTER_GROUP_VAR_EXTERN(int,count_spills_write_ila,0,"spill write i/l/a","Int, Long, Array Spills (write to memory)",spill_write_stat)
137 STAT_REGISTER_GROUP_VAR_EXTERN(int,count_spills_write_flt,0,"spill write float","Float Spills (write to memory)",spill_write_stat)
138 STAT_REGISTER_GROUP_VAR_EXTERN(int,count_spills_write_dbl,0,"spill write double","Double Spills (write to memory)",spill_write_stat)
139 
140 STAT_REGISTER_SUM_GROUP(spill_read_stat,"spills read","Number of Spills (read from memory)")
141 STAT_REGISTER_GROUP_VAR_EXTERN(int,count_spills_read_ila,0,"spill read i/l/a","Int, Long, Array Spills (read from memory)",spill_read_stat)
142 STAT_REGISTER_GROUP_VAR_EXTERN(int,count_spills_read_flt,0,"spill read float","Float Spills (read from memory)",spill_read_stat)
143 STAT_REGISTER_GROUP_VAR_EXTERN(int,count_spills_read_dbl,0,"spill read double","Double Spills (read from memory)",spill_read_stat)
144 
145 /* jit_init ********************************************************************
146 
147  Initializes the JIT subsystem.
148 
149 *******************************************************************************/
150 
151 void jit_init(void)
152 {
153  TRACESUBSYSTEMINITIALIZATION("jit_init");
154 
155 #if defined(ENABLE_JIT)
156  /* initialize stack analysis subsystem */
157 
158  (void) stack_init();
159 #endif
160 
161  /* initialize show subsystem */
162 
163 #if !defined(NDEBUG)
164  (void) show_init();
165 #endif
166 
167  /* initialize codegen subsystem */
168 
169  codegen_init();
170 
171  /* initialize code subsystem */
172 
173  (void) code_init();
174 
175  /* Machine dependent initialization. */
176 
177 #if defined(ENABLE_JIT)
178 # if defined(ENABLE_INTRP)
179  if (opt_intrp)
180  intrp_md_init();
181  else
182 # endif
183  md_init();
184 #else
185  intrp_md_init();
186 #endif
187 }
188 
189 #define DEBUG_NAME "jit"
190 
191 /* jit_close *******************************************************************
192 
193  Close the JIT subsystem.
194 
195 *******************************************************************************/
196 
197 void jit_close(void)
198 {
199  /* nop */
200 }
201 
202 
203 /* dummy function, used when there is no JavaVM code available */
204 
205 static u1 *do_nothing_function(void)
206 {
207  return NULL;
208 }
209 
210 
211 /* jit_jitdata_new *************************************************************
212 
213  Allocates and initalizes a new jitdata structure.
214 
215 *******************************************************************************/
216 
218 {
219  jitdata *jd;
220  codeinfo *code;
221 
222  /* allocate jitdata structure and fill it */
223 
224  jd = (jitdata*) DumpMemory::allocate(sizeof(jitdata));
225 
226  jd->m = m;
229 #if defined(ENABLE_LOOP)
230  if (opt_loops)
231  jd->ld = new MethodLoopData;
232 #endif
233 
234  /* Allocate codeinfo memory from the heap as we need to keep them. */
235 
236  code = code_codeinfo_new(m);
237 
238  /* Set codeinfo flags. */
239 
240  if (checksync && (m->flags & ACC_SYNCHRONIZED))
242 
243  if (checksync && (m->flags & ACC_SYNCHRONIZED))
245  else
246  code_flag_leafmethod(code);
247 
248  /* initialize variables */
249 
250  jd->code = code;
251  jd->flags = 0;
252  jd->exceptiontable = NULL;
253  jd->exceptiontablelength = 0;
254  jd->returncount = 0;
255  jd->branchtoentry = false;
256  jd->branchtoend = false;
257  jd->returncount = 0;
258  jd->returnblock = NULL;
259  jd->maxlocals = m->maxlocals;
260 
261  return jd;
262 }
263 
264 STAT_REGISTER_VAR_EXTERN(std::size_t, compiler_last_codesize, 0, "last-code-size", "code size of the last compiled method")
265 
266 /* jit_compile *****************************************************************
267 
268  Translates one method to machine code.
269 
270 *******************************************************************************/
271 
272 static u1 *jit_compile_intern(jitdata *jd);
273 
275 {
276  u1 *r;
277  jitdata *jd;
278 
279  STATISTICS(count_jit_calls++);
280 
281  /* Initialize the static function's class. */
282 
283  /* ATTENTION: This MUST be done before the method lock is aquired,
284  otherwise we could run into a deadlock with <clinit>'s that
285  call static methods of it's own class. */
286 
287  if ((m->flags & ACC_STATIC) && !(m->clazz->state & CLASS_INITIALIZED)) {
288 #if !defined(NDEBUG)
289  if (initverbose)
290  log_message_class("Initialize class ", m->clazz);
291 #endif
292 
293  if (!initialize_class(m->clazz))
294  return NULL;
295 
296  /* check if the method has been compiled during initialization */
297 
298  if ((m->code != NULL) && (m->code->entrypoint != NULL))
299  return m->code->entrypoint;
300  }
301 
302  /* enter a monitor on the method */
303 
304  m->mutex->lock();
305 
306  /* if method has been already compiled return immediately */
307 
308  if (m->code != NULL) {
309  m->mutex->unlock();
310 
311  assert(m->code->entrypoint);
312  return m->code->entrypoint;
313  }
314 
316 
317  STATISTICS(count_methods++);
318 
319 #if defined(ENABLE_STATISTICS)
320  /* measure time */
321 
322  if (opt_getcompilingtime)
324 #endif
325 
326  // Create new dump memory area.
327  DumpMemoryArea dma;
328 
329  /* create jitdata structure */
330 
331  jd = jit_jitdata_new(m);
332 
333  /* set the flags for the current JIT run */
334 
336 
337 #if defined(ENABLE_VERIFIER)
338  if (opt_verify)
339  jd->flags |= JITDATA_FLAG_VERIFY;
340 #endif
341 
342 #if defined(ENABLE_PROFILING)
343  if (opt_prof)
345 #endif
346 
347 #if defined(ENABLE_IFCONV)
348  if (opt_ifconv)
349  jd->flags |= JITDATA_FLAG_IFCONV;
350 #endif
351 
352 #if defined(ENABLE_INLINING) && defined(ENABLE_INLINING_DEBUG)
353  if (opt_Inline && opt_InlineAll)
354  jd->flags |= JITDATA_FLAG_INLINE;
355 #endif
356 
359 
362 
363  if (opt_verbosecall)
365 
366 #if defined(ENABLE_REPLACEMENT) && defined(ENABLE_INLINING) && defined(ENABLE_INLINING_DEBUG) && !defined(NDEBUG)
367  if (opt_Inline && (jd->m->hitcountdown > 0) && (jd->code->optlevel == 0)) {
368  if (!opt_InlineMethod) {
370  } else {
371  if (!opt_InlineMethodUtf) {
372  opt_InlineMethodUtf = Utf8String::from_utf8(opt_InlineMethod);
373  }
374  LOG2("name: " << jd->m->name << " hash: " << jd->m->name.hash() << cacao::nl);
375  LOG2(/*"name: " << opt_InlineMethodUtf << " "*/"hash: " << opt_InlineMethodUtf.hash() << cacao::nl);
376  if ( jd->m->name.hash() == opt_InlineMethodUtf.hash() ) {
378  }
379  }
380  }
381 #endif
382 
383 #if defined(ENABLE_JIT)
384 # if defined(ENABLE_INTRP)
385  if (!opt_intrp)
386 # endif
387  /* initialize the register allocator */
388  {
389  reg_setup(jd);
390  }
391 #endif
392 
393  /* setup the codegendata memory */
394 
395  codegen_setup(jd);
396 
397  /* now call internal compile function */
398 
399  r = jit_compile_intern(jd);
400 #if defined(ENABLE_COMPILER2)
402  using namespace cacao::jit::compiler2;
403  JITData JD(jd);
405  pass.initialize();
406  pass.run(JD);
407  pass.finalize();
408  }
409 #endif
410 
411  if (r == NULL) {
412  /* We had an exception! Finish stuff here if necessary. */
413 
414  /* release codeinfo */
415 
417  }
418  else {
419  DEBUG_JIT_COMPILEVERBOSE("Running: ");
420  }
421 
422 #if defined(ENABLE_STATISTICS)
423  /* measure time */
424 
425  if (opt_getcompilingtime)
427 #endif
428 
429  // Hook point just after code was generated.
430  Hook::jit_generated(m, m->code);
431 
432  /* leave the monitor */
433 
434  m->mutex->unlock();
435 
436 #if defined(ENABLE_STATISTICS)
437  if (m && m->code)
438  compiler_last_codesize = m->code->mcodelength;
439 #endif
440 
441  /* return pointer to the methods entry point */
442 
443  return r;
444 }
445 
446 
447 /* jit_recompile ***************************************************************
448 
449  Recompiles a Java method.
450 
451 *******************************************************************************/
452 
454 {
455  u1 *r;
456  jitdata *jd;
457  u1 optlevel;
458 
459  /* check for max. optimization level */
460 
461  optlevel = (m->code) ? m->code->optlevel : 0;
462 
463 #if 0
464  if (optlevel == 1) {
465 /* log_message_method("not recompiling: ", m); */
466  return NULL;
467  }
468 #endif
469 
470  DEBUG_JIT_COMPILEVERBOSE("Recompiling start: ");
471 
472 
473 #if defined(ENABLE_STATISTICS)
474  /* measure time */
475 
476  if (opt_getcompilingtime)
478 #endif
479 
480  // Create new dump memory area.
481  DumpMemoryArea dma;
482 
483  /* create jitdata structure */
484 
485  jd = jit_jitdata_new(m);
486 
487  /* set the current optimization level to the previous one plus 1 */
488 
489  jd->code->optlevel = optlevel + 1;
490 
491  /* get the optimization flags for the current JIT run */
492 
493 #if defined(ENABLE_VERIFIER)
494  jd->flags |= JITDATA_FLAG_VERIFY;
495 #endif
496 
497  /* jd->flags |= JITDATA_FLAG_REORDER; */
502  if (opt_verbosecall)
504 
505 #if defined(ENABLE_INLINING)
506  // XXX #warning Inlining currently disabled (broken)
507 #if 0
508  if (opt_Inline)
509  jd->flags |= JITDATA_FLAG_INLINE;
510 #endif
511 #endif
512 
513 #if defined(ENABLE_JIT)
514 # if defined(ENABLE_INTRP)
515  if (!opt_intrp)
516 # endif
517  /* initialize the register allocator */
518 
519  reg_setup(jd);
520 #endif
521 
522  /* setup the codegendata memory */
523 
524  codegen_setup(jd);
525 
526  /* now call internal compile function */
527 
528  r = jit_compile_intern(jd);
529 
530  if (r == NULL) {
531  /* We had an exception! Finish stuff here if necessary. */
532 
533  /* release codeinfo */
534 
536  }
537 
538 #if defined(ENABLE_STATISTICS)
539  /* measure time */
540 
541  if (opt_getcompilingtime)
543 #endif
544 
545  // Hook point just after code was generated.
546  Hook::jit_generated(m, m->code);
547 
548  DEBUG_JIT_COMPILEVERBOSE("Recompiling done: ");
549 
550  /* return pointer to the methods entry point */
551 
552  return r;
553 }
554 
555 #if defined(ENABLE_PM_HACKS)
556 #include "vm/jit/jit_pm_1.inc"
557 #endif
558 
559 // register compiler real-time group
560 RT_REGISTER_GROUP(compiler_group,"compiler","baseline compiler")
561 
562 // register real-time timers
563 RT_REGISTER_GROUP_TIMER(checks_timer, "compiler","checks at beginning", compiler_group)
564 RT_REGISTER_GROUP_TIMER(parse_timer, "compiler","parse", compiler_group)
565 RT_REGISTER_GROUP_TIMER(stack_timer, "compiler","analyse_stack", compiler_group)
566 RT_REGISTER_GROUP_TIMER(typechecker_timer, "compiler","typecheck", compiler_group)
567 RT_REGISTER_GROUP_TIMER(loop_timer, "compiler","loop", compiler_group)
568 RT_REGISTER_GROUP_TIMER(ifconversion_timer, "compiler","if conversion", compiler_group)
569 RT_REGISTER_GROUP_TIMER(ra_timer, "compiler","register allocation", compiler_group)
570 RT_REGISTER_GROUP_TIMER(codegen_timer, "compiler","codegen", compiler_group)
571 
572 /* jit_compile_intern **********************************************************
573 
574  Static internal function which does the actual compilation.
575 
576 *******************************************************************************/
577 
579 {
580  methodinfo *m;
581  //codegendata *cd;
582  codeinfo *code;
583 
584  RT_TIMER_START(checks_timer);
585 
586  /* get required compiler data */
587 
588 #if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
589  jd->ls = NULL;
590 #endif
591  m = jd->m;
592  code = jd->code;
593  //cd = jd->cd;
594 
595 #if defined(ENABLE_DEBUG_FILTER)
596  show_filters_apply(jd->m);
597 #endif
598 
599  // Handle native methods and create a native stub.
600  if (m->flags & ACC_NATIVE) {
602  void* f = nm.resolve_method(m);
603 
604  if (f == NULL)
605  return NULL;
606 
607  // XXX reinterpret_cast is used to prevend a compiler warning
608  // The Native* framework requires a rework to make it type safer
609  // and to get rid of this hack
610  code = NativeStub::generate(m, *reinterpret_cast<functionptr*>(&f));
611 
612  /* Native methods are never recompiled. */
613 
614  assert(!m->code);
615 
616  m->code = code;
617 
618  return code->entrypoint;
619  }
620 
621  /* if there is no javacode, print error message and return empty method */
622 
623  if (m->jcode == NULL) {
624  DEBUG_JIT_COMPILEVERBOSE("No code given for: ");
625 
626  code->entrypoint = (u1 *) (ptrint) do_nothing_function;
627  m->code = code;
628 
629  return code->entrypoint; /* return empty method */
630  }
631 
632  STATISTICS(count_javacodesize += m->jcodelength + 18);
633  STATISTICS(count_tryblocks += jd->exceptiontablelength);
634  STATISTICS(count_javaexcsize += jd->exceptiontablelength * SIZEOF_VOID_P);
635 
636  RT_TIMER_STOPSTART(checks_timer,parse_timer);
637 
638 #if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
639  /* Code for Sun's OpenJDK (see
640  hotspot/src/share/vm/classfile/verifier.cpp
641  (Verifier::is_eligible_for_verification)): Don't verify
642  dynamically-generated bytecodes. */
643 
644 # if defined(ENABLE_VERIFIER)
645  if (class_issubclass(m->clazz, class_sun_reflect_MagicAccessorImpl))
646  jd->flags &= ~JITDATA_FLAG_VERIFY;
647 # endif
648 #endif
649 
650  /* call the compiler passes ***********************************************/
651 
652  DEBUG_JIT_COMPILEVERBOSE("Parsing: ");
653 
654  /* call parse pass */
655 
656  if (!parse(jd)) {
657  DEBUG_JIT_COMPILEVERBOSE("Exception while parsing: ");
658 
659  return NULL;
660  }
661  RT_TIMER_STOP(parse_timer);
662 
663  DEBUG_JIT_COMPILEVERBOSE("Parsing done: ");
664 
665 #if defined(ENABLE_JIT)
666 # if defined(ENABLE_INTRP)
667  if (!opt_intrp) {
668 # endif
669  RT_TIMER_START(stack_timer);
670  DEBUG_JIT_COMPILEVERBOSE("Analysing: ");
671 
672  /* call stack analysis pass */
673 
674  if (!stack_analyse(jd)) {
675  DEBUG_JIT_COMPILEVERBOSE("Exception while analysing: ");
676 
677  return NULL;
678  }
679  RT_TIMER_STOPSTART(stack_timer,typechecker_timer);
680 
681  DEBUG_JIT_COMPILEVERBOSE("Analysing done: ");
682 
683 #ifdef ENABLE_VERIFIER
684  if (JITDATA_HAS_FLAG_VERIFY(jd)) {
685  DEBUG_JIT_COMPILEVERBOSE("Typechecking: ");
686 
687  /* call typecheck pass */
688  if (!typecheck(jd)) {
689  DEBUG_JIT_COMPILEVERBOSE("Exception while typechecking: ");
690 
691  return NULL;
692  }
693 
694  DEBUG_JIT_COMPILEVERBOSE("Typechecking done: ");
695  }
696 #endif
697  RT_TIMER_STOPSTART(typechecker_timer,loop_timer);
698 
699 #if defined(ENABLE_IFCONV)
700  if (JITDATA_HAS_FLAG_IFCONV(jd)) {
701  if (!ifconv_static(jd))
702  return NULL;
704  }
705 #endif
706  RT_TIMER_STOPSTART(ifconversion_timer,ra_timer);
707 
708  /* inlining */
709 
710 #if defined(ENABLE_INLINING) && (!defined(ENABLE_ESCAPE) || 1)
711  if (JITDATA_HAS_FLAG_INLINE(jd)) {
712  if (!inline_inline(jd))
713  return NULL;
714  }
715 #endif
716 
717 #if defined(ENABLE_SSA)
718  if (opt_lsra) {
720  }
721 #endif
722 
723  /* Build the CFG. This has to be done after stack_analyse, as
724  there happens the JSR elimination. */
725 
726  if (!cfg_build(jd))
727  return NULL;
728 
729 #if defined(ENABLE_LOOP)
730  if (opt_loops)
731  {
734 
735  cfg_clear(jd);
736  if (!cfg_build(jd))
737  return NULL;
738  }
739 #endif
740  RT_TIMER_STOPSTART(ra_timer,loop_timer);
741 
742 #if defined(ENABLE_PROFILING)
743  /* Basic block reordering. I think this should be done after
744  if-conversion, as we could lose the ability to do the
745  if-conversion. */
746 
747  if (JITDATA_HAS_FLAG_REORDER(jd)) {
748  if (!reorder(jd))
749  return NULL;
751  }
752 #endif
753 
754 #if defined(ENABLE_PM_HACKS)
755 #include "vm/jit/jit_pm_2.inc"
756 #endif
757  DEBUG_JIT_COMPILEVERBOSE("Allocating registers: ");
758 
759 #if defined(ENABLE_LSRA) && !defined(ENABLE_SSA)
760  /* allocate registers */
761  if (opt_lsra) {
762  if (!lsra(jd))
763  return NULL;
764 
765  STATISTICS(count_methods_allocated_by_lsra++);
766 
767  } else
768 # endif /* defined(ENABLE_LSRA) && !defined(ENABLE_SSA) */
769 #if defined(ENABLE_SSA)
770  /* allocate registers */
771  if (
772  (opt_lsra &&
773  jd->code->optlevel > 0)
774  /* strncmp(UTF_TEXT(jd->m->name), "hottie", 6) == 0*/
775  /*&& jd->exceptiontablelength == 0*/
776  ) {
777  /*printf("=== %s ===\n", UTF_TEXT(jd->m->name));*/
778  jd->ls = (lsradata*) DumpMemory::allocate(sizeof(lsradata));
779  jd->ls = NULL;
780  ssa(jd);
781  /*lsra(jd);*/ regalloc(jd);
782  /*eliminate_subbasicblocks(jd);*/
783  STATISTICS(count_methods_allocated_by_lsra++);
784 
785  } else
786 # endif /* defined(ENABLE_SSA) */
787  {
788  STATISTICS(count_locals_conflicts += (jd->maxlocals - 1) * (jd->maxlocals));
789 
790  regalloc(jd);
791  }
792 
793  STATISTICS(simplereg_make_statistics(jd));
794 
795  RT_TIMER_STOP(ra_timer);
796  DEBUG_JIT_COMPILEVERBOSE("Allocating registers done: ");
797 # if defined(ENABLE_INTRP)
798  }
799 # endif
800 #endif /* defined(ENABLE_JIT) */
801  RT_TIMER_START(codegen_timer);
802 
803 #if defined(ENABLE_PROFILING)
804  /* Allocate memory for basic block profiling information. This
805  _must_ be done after loop optimization and register allocation,
806  since they can change the basic block count. */
807 
808  if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
809  code->basicblockcount = jd->basicblockcount;
810  code->bbfrequency = MNEW(u4, jd->basicblockcount);
811  }
812 #endif
813 
814  DEBUG_JIT_COMPILEVERBOSE("Generating code: ");
815 
816  /* now generate the machine code */
817 
818 #if defined(ENABLE_JIT)
819 # if defined(ENABLE_INTRP)
820  if (opt_intrp) {
821 #if defined(ENABLE_VERIFIER)
822  if (opt_verify) {
823  DEBUG_JIT_COMPILEVERBOSE("Typechecking (stackbased): ");
824 
825  if (!typecheck_stackbased(jd)) {
826  DEBUG_JIT_COMPILEVERBOSE("Exception while typechecking (stackbased): ");
827  return NULL;
828  }
829  }
830 #endif
831  if (!intrp_codegen(jd)) {
832  DEBUG_JIT_COMPILEVERBOSE("Exception while generating code: ");
833 
834  return NULL;
835  }
836  } else
837 # endif
838  {
839  if (!codegen_generate(jd)) {
840  DEBUG_JIT_COMPILEVERBOSE("Exception while generating code: ");
841 
842  return NULL;
843  }
844  }
845 #else
846  if (!intrp_codegen(jd)) {
847  DEBUG_JIT_COMPILEVERBOSE("Exception while generating code: ");
848 
849  return NULL;
850  }
851 #endif
852  RT_TIMER_STOP(codegen_timer);
853 
854  DEBUG_JIT_COMPILEVERBOSE("Generating code done: ");
855 
856 #if !defined(NDEBUG) && defined(ENABLE_REPLACEMENT)
857  /* activate replacement points inside newly created code */
858 
859  if (opt_TestReplacement)
861 #endif
862 
863 #if !defined(NDEBUG)
864 #if defined(ENABLE_DEBUG_FILTER)
865  if (jd->m->filtermatches & SHOW_FILTER_FLAG_SHOW_METHOD)
866 #endif
867  {
868  /* intermediate and assembly code listings */
869 
871  show_method(jd, SHOW_CODE);
872  }
873  else if (JITDATA_HAS_FLAG_SHOWDISASSEMBLE(jd)) {
874 # if defined(ENABLE_DISASSEMBLER)
875  DISASSEMBLE(code->entrypoint,
876  code->entrypoint + (code->mcodelength - jd->cd->dseglen));
877 # endif
878  }
879 
881  dseg_display(jd);
882  }
883 #endif
884 
885  /* switch to the newly generated code */
886 
887  assert(code);
888  assert(code->entrypoint);
889 
890  /* add the current compile version to the methodinfo */
891 
892  code->prev = m->code;
893  m->code = code;
894 
895  /* return pointer to the methods entry point */
896 
897  return code->entrypoint;
898 }
899 
900 
901 /* jit_invalidate_code *********************************************************
902 
903  Mark the compiled code of the given method as invalid and take care that
904  it is replaced if necessary.
905 
906  XXX Not fully implemented, yet.
907 
908 *******************************************************************************/
909 
911 {
912  codeinfo *code;
913 
914  code = m->code;
915 
916  if (code == NULL || code_is_invalid(code))
917  return;
918 
919  code_flag_invalid(code);
920 
921  /* activate mappable replacement points */
922 
923 #if defined(ENABLE_REPLACEMENT)
925 #else
926  vm_abort("invalidating code only works with ENABLE_REPLACEMENT");
927 #endif
928 }
929 
930 
931 /* jit_request_optimization ****************************************************
932 
933  Request optimization of the given method. If the code of the method is
934  unoptimized, it will be invalidated, so the next jit_get_current_code(m)
935  triggers an optimized recompilation.
936  If the method is already optimized, this function does nothing.
937 
938  IN:
939  m................the method
940 
941 *******************************************************************************/
942 
944 {
945  codeinfo *code;
946 
947  code = m->code;
948 
949  if (code && code->optlevel == 0)
951 }
952 
953 
954 /* jit_get_current_code ********************************************************
955 
956  Get the currently valid code for the given method. If there is no valid
957  code, (re)compile the method.
958 
959  IN:
960  m................the method
961 
962  RETURN VALUE:
963  the codeinfo* for the current code, or
964  NULL if an exception has been thrown during recompilation.
965 
966 *******************************************************************************/
967 
969 {
970  assert(m);
971 
972  /* if we have valid code, return it */
973 
974  if (m->code && !code_is_invalid(m->code))
975  return m->code;
976 
977  /* otherwise: recompile */
978 
979 #if defined(ENABLE_COMPILER2)
981  return NULL;
982 #else
983  if (!jit_recompile(m))
984  return NULL;
985 #endif
986 
987  assert(m->code);
988 
989  return m->code;
990 }
991 
992 
993 /* jit_asm_compile *************************************************************
994 
995  This method is called from asm_vm_call_method and does:
996 
997  - create stackframe info for exceptions
998  - compile the method
999  - patch the entrypoint of the method into the calculated address in
1000  the JIT code
1001  - flushes the instruction cache.
1002 
1003 *******************************************************************************/
1004 
1005 #if defined(ENABLE_JIT)
1006 #if !defined(JIT_COMPILER_VIA_SIGNAL)
1007 extern "C" {
1008 void* jit_asm_compile(methodinfo *m, void* mptr, void* sp, void* ra)
1009 {
1010  stackframeinfo_t sfi;
1011  void *entrypoint;
1012  void *pa;
1013  uintptr_t *p;
1014 
1015  /* create the stackframeinfo (subtract 1 from RA as it points to the */
1016  /* instruction after the call) */
1017 
1018  stacktrace_stackframeinfo_add(&sfi, NULL, sp, ra, ((uint8_t*) ra) - 1);
1019 
1020  /* actually compile the method */
1021 
1022  entrypoint = jit_compile(m);
1023 
1024  /* remove the stackframeinfo */
1025 
1027 
1028  /* there was a problem during compilation */
1029 
1030  if (entrypoint == NULL)
1031  return NULL;
1032 
1033  /* get the method patch address */
1034 
1035  pa = md_jit_method_patch_address(sfi.pv, (void *) ra, mptr);
1036 
1037  /* patch the method entry point */
1038 
1039  p = (uintptr_t*) pa;
1040 
1041  *p = (uintptr_t) entrypoint;
1042 
1043  /* flush the instruction cache */
1044 
1045  md_icacheflush(pa, SIZEOF_VOID_P);
1046 
1047  return entrypoint;
1048 }
1049 }
1050 #endif
1051 
1052 /* jit_compile_handle **********************************************************
1053 
1054  This method is called from the appropriate signal handler which
1055  handles compiler-traps and does the following:
1056 
1057  - compile the method
1058  - patch the entrypoint of the method into the calculated address in
1059  the JIT code
1060  - flush the instruction cache
1061 
1062 *******************************************************************************/
1063 
1064 void *jit_compile_handle(methodinfo *m, void *pv, void *ra, void *mptr)
1065 {
1066  void *newpv; /* new compiled method PV */
1067  void *pa; /* patch address */
1068  uintptr_t *p; /* convenience pointer */
1069 
1070  /* Compile the method. */
1071 
1072  newpv = jit_compile(m);
1073 
1074  /* There was a problem during compilation. */
1075 
1076  if (newpv == NULL)
1077  return NULL;
1078 
1079  /* Get the method patch address. */
1080 
1081  pa = md_jit_method_patch_address(pv, ra, mptr);
1082 
1083  /* Patch the method entry point. */
1084 
1085  p = (uintptr_t *) pa;
1086 
1087  *p = (uintptr_t) newpv;
1088 
1089  /* Flush both caches. */
1090 
1091  md_cacheflush(pa, SIZEOF_VOID_P);
1092 
1093  return newpv;
1094 }
1095 #endif /* defined(ENABLE_JIT) */
1096 
1097 
1098 /* jit_complement_condition ****************************************************
1099 
1100  Returns the complement of the passed conditional instruction.
1101 
1102  We use the order of the different conditions, e.g.:
1103 
1104  ICMD_IFEQ 153
1105  ICMD_IFNE 154
1106 
1107  If the passed opcode is odd, we simply add 1 to get the complement.
1108  If the opcode is even, we subtract 1.
1109 
1110  Exception:
1111 
1112  ICMD_IFNULL 198
1113  ICMD_IFNONNULL 199
1114 
1115 *******************************************************************************/
1116 
1118 {
1119  switch (opcode) {
1120  case ICMD_IFNULL:
1121  return ICMD_IFNONNULL;
1122 
1123  case ICMD_IFNONNULL:
1124  return ICMD_IFNULL;
1125 
1126  default:
1127  /* check if opcode is odd */
1128 
1129  if (opcode & 0x1)
1130  return ICMD(opcode + 1);
1131  else
1132  return ICMD(opcode - 1);
1133  }
1134 }
1135 
1136 
1137 /* jit_renumber_basicblocks ****************************************************
1138 
1139  Set the ->nr of all blocks so it increases when traversing ->next.
1140 
1141  IN:
1142  jitdata..........the current jitdata
1143 
1144 *******************************************************************************/
1145 
1147 {
1148  s4 nr;
1149  basicblock *bptr;
1150 
1151  nr = 0;
1152  for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
1153  bptr->nr = nr++;
1154  }
1155 
1156  /* we have one block more than jd->basicblockcount (the end marker) */
1157 
1158  assert(nr == jd->basicblockcount + 1);
1159 }
1160 
1161 
1162 /* jit_check_basicblock_numbers ************************************************
1163 
1164  Assert that the ->nr of the first block is zero and increases by 1 each
1165  time ->next is traversed.
1166  This function should be called before any analysis that relies on
1167  the basicblock numbers.
1168 
1169  IN:
1170  jitdata..........the current jitdata
1171 
1172  NOTE: Aborts with an assertion if the condition is not met!
1173 
1174 *******************************************************************************/
1175 
1176 #if !defined(NDEBUG)
1178 {
1179  s4 nr;
1180  basicblock *bptr;
1181 
1182  nr = 0;
1183  for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
1184  assert(bptr->nr == nr);
1185  nr++;
1186  }
1187 
1188  /* we have one block more than jd->basicblockcount (the end marker) */
1189 
1190  assert(nr == jd->basicblockcount + 1);
1191 }
1192 #endif /* !defined(NDEBUG) */
1193 
1194 
1195 /*
1196  * These are local overrides for various environment variables in Emacs.
1197  * Please do not remove this and leave it at the end of the file, where
1198  * Emacs will automagically detect them.
1199  * ---------------------------------------------------------------------
1200  * Local variables:
1201  * mode: c++
1202  * indent-tabs-mode: t
1203  * c-basic-offset: 4
1204  * tab-width: 4
1205  * End:
1206  * vim:noexpandtab:sw=4:ts=4:
1207  */
#define SHOW_CODE
Definition: show.hpp:44
#define JITDATA_FLAG_IFCONV
Definition: jit.hpp:189
Utf8String name
Definition: method.hpp:71
#define JITDATA_HAS_FLAG_SHOWDISASSEMBLE(jd)
Definition: jit.hpp:224
bool cfg_build(jitdata *jd)
Definition: cfg.cpp:124
#define JITDATA_HAS_FLAG_INLINE(jd)
Definition: jit.hpp:215
#define pv
Definition: md-asm.hpp:65
bool opt_showdisassemble
Definition: options.cpp:85
#define mptr
Definition: md-asm.hpp:66
s4 exceptiontablelength
Definition: jit.hpp:167
codeinfo * jit_get_current_code(methodinfo *m)
Definition: jit.cpp:968
#define STATISTICS(x)
Wrapper for statistics only code.
Definition: statistics.hpp:975
void code_codeinfo_free(codeinfo *code)
Definition: code.cpp:213
basicblock * basicblocks
Definition: jit.hpp:141
Definition: jit.hpp:126
#define ra
Definition: md-asm.hpp:62
Table containing all native methods registered with the VM.
Definition: native.hpp:132
NativeMethods & get_nativemethods()
Definition: vm.hpp:128
#define JITDATA_HAS_FLAG_REORDER(jd)
Definition: jit.hpp:212
s4 jcodelength
Definition: method.hpp:85
#define RT_TIMER_STOP(var)
Stop the timer var.
Definition: rt-timing.hpp:695
basicblock * returnblock
Definition: jit.hpp:170
void replace_activate_replacement_points(codeinfo *code, bool mappable)
Definition: replace.cpp:759
exception_entry * exceptiontable
Definition: jit.hpp:168
void * jit_compile_handle(methodinfo *m, void *pv, void *ra, void *mptr)
Definition: jit.cpp:1064
void cfg_clear(jitdata *jd)
Definition: cfg.cpp:515
void code_init(void)
Definition: code.cpp:46
argument_type from
bool inline_inline(jitdata *jd)
Definition: inline.cpp:3198
s4 maxlocals
Definition: jit.hpp:162
static int code_is_invalid(codeinfo *code)
Definition: code.hpp:129
basicblock * next
Definition: jit.hpp:337
#define JITDATA_FLAG_VERBOSECALL
Definition: jit.hpp:197
bool stack_init(void)
Definition: stack.cpp:666
codeinfo * code
Definition: jit.hpp:128
u1 optlevel
Definition: code.hpp:80
bool reorder(jitdata *jd)
Definition: reorder.cpp:84
MachineLoop * loop
bool typecheck(jitdata *jd)
Definition: typecheck.cpp:684
bool typecheck_stackbased(jitdata *jd)
#define show_method(...)
Definition: ssa2.cpp:41
bool opt_intrp
Definition: options.cpp:55
#define JITDATA_FLAG_INSTRUMENT
Definition: jit.hpp:187
codegendata * cd
Definition: jit.hpp:129
#define JITDATA_HAS_FLAG_INSTRUMENT(jd)
Definition: jit.hpp:206
u4 flags
Definition: jit.hpp:138
typedef void(JNICALL *jvmtiEventSingleStep)(jvmtiEnv *jvmti_env
_Jv_JavaVM JavaVM
Definition: jni.hpp:114
#define JITDATA_FLAG_VERIFY
Definition: jit.hpp:185
bool initverbose
Definition: options.cpp:71
static void code_flag_invalid(codeinfo *code)
Definition: code.hpp:134
u1 * jit_compile(methodinfo *m)
Definition: jit.cpp:274
bool show_init(void)
Definition: show.cpp:91
#define RT_TIMER_START(var)
Start the timer var.
Definition: rt-timing.hpp:694
MachineCode * compile(methodinfo *m)
Definition: Compiler.cpp:123
static void code_flag_synchronized(codeinfo *code)
Definition: code.hpp:178
void codegen_init(void)
#define DEBUG_JIT_COMPILEVERBOSE(x)
Definition: jit.cpp:93
uint8_t u1
Definition: types.hpp:40
static void code_unflag_leafmethod(codeinfo *code)
Definition: code.hpp:161
size_t hash() const
Definition: utf8.hpp:137
s4 mcodelength
Definition: code.hpp:85
bool opt_verbosecall
Definition: options.cpp:76
char * opt_CompileMethod
Definition: options.cpp:166
Second stage compiler class.
static u1 * do_nothing_function(void)
Definition: jit.cpp:205
JNIEnv jthread jobject jclass jlong size
Definition: jvmti.h:387
void dseg_display(jitdata *jd)
Definition: dseg.cpp:633
void jit_request_optimization(methodinfo *m)
Definition: jit.cpp:943
#define TRACESUBSYSTEMINITIALIZATION(text)
Definition: options.hpp:258
bool opt_ifconv
Definition: options.cpp:118
void md_cacheflush(u1 *addr, s4 nbytes)
Definition: md.c:49
#define JITDATA_FLAG_PARSE
Definition: jit.hpp:184
void vm_abort(const char *text,...)
Definition: vm.cpp:2586
#define RT_REGISTER_GROUP(var, name, description)
Register a new (toplevel) group.
Definition: rt-timing.hpp:683
void intrp_md_init(void)
Definition: md.c:58
codeinfo * code_codeinfo_new(methodinfo *m)
Definition: code.cpp:72
#define JITDATA_FLAG_SHOWINTERMEDIATE
Definition: jit.hpp:195
void jit_renumber_basicblocks(jitdata *jd)
Definition: jit.cpp:1146
void jit_invalidate_code(methodinfo *m)
Definition: jit.cpp:910
static u1 * jit_compile_intern(jitdata *jd)
Definition: jit.cpp:578
#define RT_REGISTER_GROUP_TIMER(var, name, description, group)
Register a new timer.
Definition: rt-timing.hpp:682
bool opt_showddatasegment
Definition: options.cpp:86
ObjectFileWriterPass TODO: more info.
struct MethodLoopData MethodLoopData
Definition: loop.hpp:29
Dump memory area.
Definition: dumpmemory.hpp:90
jitdata * jit_jitdata_new(methodinfo *m)
Definition: jit.cpp:217
bool stack_analyse(jitdata *jd)
Definition: stack.cpp:2144
classinfo * clazz
Definition: method.hpp:80
static JNINativeMethod methods[]
alloc::list< PassInfo::IDTy >::type & stack
This file contains the statistics framework.
#define SHOW_FILTER_FLAG_SHOW_METHOD
Definition: show.hpp:70
bool checksync
Definition: options.cpp:90
s4 returncount
Definition: jit.hpp:172
#define JITDATA_HAS_FLAG_VERIFY(jd)
Definition: jit.hpp:203
void reg_setup(jitdata *jd)
Definition: reg.cpp:42
bool lsra(jitdata *jd)
Definition: lsra.cpp:101
#define STAT_REGISTER_SUM_GROUP(var, name, description)
Register a statistics summary group.
Definition: statistics.hpp:972
bool method_matches(methodinfo *m, const char *name)
Definition: method.cpp:1271
u1 * jit_recompile(methodinfo *m)
Definition: jit.cpp:453
static void Exception(jvmtiEnv *jvmti_env, JNIEnv *jni_env, jthread thread, jmethodID method, jlocation location, jobject exception, jmethodID catch_method, jlocation catch_location)
Definition: VMjdwp.cpp:127
#define JITDATA_HAS_FLAG_IFCONV(jd)
Definition: jit.hpp:209
#define JITDATA_HAS_FLAG_SHOWINTERMEDIATE(jd)
Definition: jit.hpp:221
void jit_init(void)
Definition: jit.cpp:151
static Utf8String from_utf8(const char *, size_t)
Definition: utf8.cpp:335
u1 * jcode
Definition: method.hpp:86
void jit_close(void)
Definition: jit.cpp:197
MIIterator i
void jit_generated(methodinfo *m, codeinfo *code)
Hook point just after code was generated.
Definition: hook.hpp:102
bool branchtoentry
Definition: jit.hpp:173
static void code_flag_leafmethod(codeinfo *code)
Definition: code.hpp:156
#define LOG2(STMT)
Definition: logging.hpp:93
int32_t s4
Definition: types.hpp:45
void stacktrace_stackframeinfo_add(stackframeinfo_t *sfi, void *pv, void *sp, void *ra, void *xpc)
Definition: stacktrace.cpp:84
ICMD
Definition: icmd.hpp:37
registerdata * rd
Definition: jit.hpp:130
s4 maxlocals
Definition: method.hpp:84
bool initialize_class(classinfo *c)
Definition: initialize.cpp:110
codeinfo * code
Definition: method.hpp:103
bool class_issubclass(classinfo *sub, classinfo *super)
Definition: class.cpp:1404
codeinfo * prev
Definition: code.hpp:76
bool opt_verify
Definition: options.cpp:103
This file contains the real-time timing utilities.
void * resolve_method(methodinfo *m)
Resolves a native method, maybe from a dynamic library.
Definition: native.cpp:271
void compilingtime_start(void)
Definition: statistics.cpp:81
void * md_jit_method_patch_address(void *pv, void *ra, void *mptr)
Definition: md.cpp:83
bool regalloc(jitdata *jd)
Definition: simplereg.cpp:262
uint32_t u4
Definition: types.hpp:46
void codegen_setup(jitdata *jd)
This is a generic accessor class for Java arrays (of unspecified type), which can be used to safely o...
Definition: array.hpp:87
#define sp
Definition: md-asm.hpp:81
STAT_REGISTER_GROUP_VAR_EXTERN(int, size_classinfo, 0,"size classinfo","classinfo", info_struct_stat) STAT_REGISTER_GROUP_VAR(int
bool opt_showintermediate
Definition: options.cpp:87
void removeArrayBoundChecks(jitdata *jd)
Definition: loop.cpp:404
#define JITDATA_FLAG_INLINE
Definition: jit.hpp:191
#define MNEW(type, num)
Definition: memory.hpp:96
methodinfo * m
Definition: jit.hpp:127
void stacktrace_stackframeinfo_remove(stackframeinfo_t *sfi)
Definition: stacktrace.cpp:204
void show_filters_apply(methodinfo *m)
Definition: show.cpp:1525
bool parse(jitdata *jd)
Definition: parse.cpp:604
static void * allocate(size_t size)
Definition: dumpmemory.hpp:251
s4 nr
Definition: jit.hpp:312
s4 basicblockcount
Definition: jit.hpp:144
#define JITDATA_FLAG_COUNTDOWN
Definition: jit.hpp:193
bool branchtoend
Definition: jit.hpp:174
#define RT_TIMER_STOPSTART(var1, var2)
Stop the timer var1 and start the timer var2.
Definition: rt-timing.hpp:696
#define TRACECOMPILERCALLS()
Definition: jit.cpp:104
void ssa(jitdata *jd)
Definition: ssa.cpp:105
void jit_check_basicblock_numbers(jitdata *jd)
Definition: jit.cpp:1177
void fix_exception_handlers(jitdata *jd)
Definition: ssa3.cpp:989
#define JITDATA_FLAG_SHOWDISASSEMBLE
Definition: jit.hpp:196
#define jit_asm_compile
Definition: md-asm.hpp:103
ICMD jit_complement_condition(ICMD opcode)
Definition: jit.cpp:1117
bool codegen_generate(jitdata *jd)
bool intrp_codegen(jitdata *jd)
Definition: codegen.c:281
s4 flags
Definition: method.hpp:70
block_count * blocks[HASH_SIZE]
Definition: profile.c:48
void md_init(void)
Definition: md.cpp:48
uintptr_t ptrint
Definition: types.hpp:54
static void md_icacheflush(void *addr, int nbytes)
Definition: md.hpp:151
static codeinfo * generate(methodinfo *m, functionptr f)
Wrapper for codegen_emit_stub_native.
Definition: stubs.cpp:282
#define STAT_REGISTER_VAR_EXTERN(type, var, init, name, description)
Register an external statistics variable.
Definition: statistics.hpp:964
Nl nl
Definition: OStream.cpp:56
#define STAT_REGISTER_VAR(type, var, init, name, description)
Register an external statistics variable.
Definition: statistics.hpp:966
bool ifconv_static(jitdata *jd)
Definition: ifconv.cpp:123
virtual void initialize()
Initialize the Pass.
Definition: Pass.hpp:98
void log_message_class(const char *msg, classinfo *c)
Definition: logging.cpp:237
void compilingtime_stop(void)
Definition: statistics.cpp:96
static VM * get_current()
Definition: vm.hpp:99
u1 * entrypoint
Definition: code.hpp:84