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