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