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