LCOV - code coverage report
Current view: top level - vm/jit - stubs.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 53 60 88.3 %
Date: 2015-06-10 18:10:59 Functions: 3 5 60.0 %

          Line data    Source code
       1             : /* src/vm/jit/stubs.cpp - JIT stubs
       2             : 
       3             :    Copyright (C) 1996-2013
       4             :    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
       5             :    Copyright (C) 2008 Theobroma Systems Ltd.
       6             : 
       7             :    This file is part of CACAO.
       8             : 
       9             :    This program is free software; you can redistribute it and/or
      10             :    modify it under the terms of the GNU General Public License as
      11             :    published by the Free Software Foundation; either version 2, or (at
      12             :    your option) any later version.
      13             : 
      14             :    This program is distributed in the hope that it will be useful, but
      15             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      17             :    General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program; if not, write to the Free Software
      21             :    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
      22             :    02110-1301, USA.
      23             : 
      24             : */
      25             : 
      26             : #include "vm/jit/stubs.hpp"
      27             : #include <stdint.h>                     // for uint8_t
      28             : #include "arch.hpp"                     // for JIT_COMPILER_VIA_SIGNAL
      29             : #include "config.h"                     // for ENABLE_JIT
      30             : #include "md-stubs.hpp"                 // for CompilerStub::get_code_size
      31             : #include "md.hpp"                       // for md_cacheflush
      32             : #include "mm/codememory.hpp"
      33             : #include "mm/dumpmemory.hpp"            // for DumpMemory, DumpMemoryArea
      34             : #include "vm/descriptor.hpp"            // for methoddesc, typedesc, etc
      35             : #include "vm/jit/abi.hpp"               // for md_param_alloc_native
      36             : #include "vm/jit/builtin.hpp"           // for builtintable_entry
      37             : #include "vm/jit/code.hpp"              // for code_unflag_leafmethod, etc
      38             : #include "vm/jit/codegen-common.hpp"    // for codegen_emit_stub_native, etc
      39             : #include "vm/jit/disass.hpp"
      40             : #include "vm/jit/dseg.hpp"
      41             : #include "vm/jit/emit-common.hpp"       // for emit_trap_compiler
      42             : #include "vm/jit/jit.hpp"               // for jitdata, jit_jitdata_new
      43             : #include "vm/jit/reg.hpp"               // for reg_setup
      44             : #include "vm/jit/show.hpp"
      45             : #include "vm/method.hpp"                // for methodinfo
      46             : #include "vm/options.hpp"               // for opt_verbosecall
      47             : #include "vm/statistics.hpp"            // for StatVar
      48             : #include "vm/types.hpp"                 // for ptrint, u1
      49             : 
      50             : STAT_DECLARE_VAR(int,count_cstub_len,0)
      51             : STAT_DECLARE_VAR(int,size_stub_native,0)
      52             : 
      53             : /**
      54             :  * Wrapper for codegen_emit_stub_compiler.
      55             :  *
      56             :  * @param m Method object.
      57             :  *
      58             :  * @return Pointer to the compiler stub code.
      59             :  */
      60      422722 : void* CompilerStub::generate(methodinfo *m)
      61             : {
      62             :         jitdata     *jd;
      63             :         codegendata *cd;
      64             :         ptrint      *d;                     /* pointer to data memory             */
      65             :         u1          *c;                     /* pointer to code memory             */
      66             : 
      67             :         // Create new dump memory area.
      68      422722 :         DumpMemoryArea dma;
      69             : 
      70             :         /* allocate required data structures */
      71             : 
      72      422722 :         jd = (jitdata*) DumpMemory::allocate(sizeof(jitdata));
      73             : 
      74      422722 :         jd->m     = m;
      75      422722 :         jd->cd    = (codegendata*) DumpMemory::allocate(sizeof(codegendata));
      76      422722 :         jd->flags = 0;
      77             : 
      78             :         /* get required compiler data */
      79             : 
      80      422722 :         cd = jd->cd;
      81             : 
      82             : #if !defined(JIT_COMPILER_VIA_SIGNAL)
      83             :         /* allocate code memory */
      84             : 
      85             :         c = CNEW(u1, 3 * SIZEOF_VOID_P + get_code_size());
      86             : 
      87             :         /* set pointers correctly */
      88             : 
      89             :         d = (ptrint *) c;
      90             : 
      91             :         cd->mcodebase = c;
      92             : 
      93             :         c = c + 3 * SIZEOF_VOID_P;
      94             :         cd->mcodeptr = c;
      95             : 
      96             :         /* NOTE: The codeinfo pointer is actually a pointer to the
      97             :            methodinfo (this fakes a codeinfo structure). */
      98             : 
      99             :         d[0] = (ptrint) asm_call_jit_compiler;
     100             :         d[1] = (ptrint) m;
     101             :         d[2] = (ptrint) &d[1];                                    /* fake code->m */
     102             : 
     103             :         /* call the emit function */
     104             : 
     105             :         codegen_emit_stub_compiler(jd);
     106             : 
     107             :         STATISTICS(count_cstub_len += 3 * SIZEOF_VOID_P + get_code_size());
     108             : 
     109             :         /* flush caches */
     110             : 
     111             :         md_cacheflush(cd->mcodebase, 3 * SIZEOF_VOID_P + get_code_size());
     112             : #else
     113             :         /* Allocate code memory. */
     114             : 
     115      422722 :         c = CNEW(uint8_t, 2 * SIZEOF_VOID_P + get_code_size());
     116             : 
     117             :         /* Set pointers correctly. */
     118             : 
     119      422722 :         d = (ptrint *) c;
     120             : 
     121      422722 :         cd->mcodebase = c;
     122             : 
     123      422722 :         c = c + 2 * SIZEOF_VOID_P;
     124      422722 :         cd->mcodeptr = c;
     125             : 
     126             :         /* NOTE: The codeinfo pointer is actually a pointer to the
     127             :            methodinfo (this fakes a codeinfo structure). */
     128             : 
     129      422722 :         d[0] = (ptrint) m;
     130      422722 :         d[1] = (ptrint) &d[0];                                    /* fake code->m */
     131             : 
     132             :         /* Emit the trap instruction. */
     133             : 
     134      422722 :         emit_trap_compiler(cd);
     135             : 
     136             :         STATISTICS(count_cstub_len += 2 * SIZEOF_VOID_P + get_code_size());
     137             : 
     138             :         /* Flush caches. */
     139             : 
     140      422722 :         md_cacheflush(cd->mcodebase, 2 * SIZEOF_VOID_P + get_code_size());
     141             : #endif
     142             : 
     143             :         /* return native stub code */
     144             : 
     145      422722 :         return c;
     146             : }
     147             : 
     148             : 
     149             : /**
     150             :  * Free a compiler stub from memory.
     151             :  *
     152             :  * @param 
     153             :  */
     154           0 : void CompilerStub::remove(void* stub)
     155             : {
     156             :         // Pass size 1 to keep the intern function happy.
     157           0 :         CFREE(stub, 1);
     158           0 : }
     159             : 
     160             : 
     161             : /* codegen_disassemble_nativestub **********************************************
     162             : 
     163             :    Disassembles the generated builtin or native stub.
     164             : 
     165             : *******************************************************************************/
     166             : 
     167             : #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
     168             : static void codegen_disassemble_stub(methodinfo *m, u1 *start, u1 *end)
     169             : {
     170             :         printf("Stub code: ");
     171             :         if (m->clazz != NULL)
     172             :                 utf_fprint_printable_ascii_classname(stdout, m->clazz->name);
     173             :         else
     174             :                 printf("NULL");
     175             :         printf(".");
     176             :         utf_fprint_printable_ascii(stdout, m->name);
     177             :         utf_fprint_printable_ascii(stdout, m->descriptor);
     178             :         printf("\nLength: %d\n\n", (s4) (end - start));
     179             : 
     180             :         DISASSEMBLE(start, end);
     181             : }
     182             : #endif
     183             : 
     184             : 
     185             : /**
     186             :  * Wrapper for codegen_emit_stub_native.
     187             :  *
     188             :  * @param m   Method object.
     189             :  * @param bte Builtin function structure.
     190             :  */
     191        2282 : void BuiltinStub::generate(methodinfo* m, builtintable_entry* bte)
     192             : {
     193             :         jitdata  *jd;
     194             :         codeinfo *code;
     195             :         int       skipparams;
     196             : 
     197             :         // Create new dump memory area.
     198        2282 :         DumpMemoryArea dma;
     199             : 
     200             :         /* Create JIT data structure. */
     201             : 
     202        2282 :         jd = jit_jitdata_new(m);
     203             : 
     204             :         /* Get required compiler data. */
     205             : 
     206        2282 :         code = jd->code;
     207             : 
     208             :         /* Stubs are non-leaf methods. */
     209             : 
     210        2282 :         code_unflag_leafmethod(code);
     211             : 
     212             :         /* setup code generation stuff */
     213             : 
     214        2282 :         codegen_setup(jd);
     215             : 
     216             :         /* Set the number of native arguments we need to skip. */
     217             : 
     218        2282 :         skipparams = 0;
     219             : 
     220             :         /* generate the code */
     221             : 
     222             : #if defined(ENABLE_JIT)
     223             : # if defined(ENABLE_INTRP)
     224             :         if (!opt_intrp) {
     225             : # endif
     226        2282 :                 assert(bte->fp != NULL);
     227        2282 :                 codegen_emit_stub_native(jd, bte->md, bte->fp, skipparams);
     228             : # if defined(ENABLE_INTRP)
     229             :         }
     230             : # endif
     231             : #endif
     232             : 
     233             :         /* reallocate the memory and finish the code generation */
     234             : 
     235        2282 :         codegen_finish(jd);
     236             : 
     237             :         /* set the stub entry point in the builtin table */
     238             : 
     239        2282 :         bte->stub = code->entrypoint;
     240             : 
     241        2282 :         STATISTICS(size_stub_native += code->mcodelength);
     242             : 
     243             : #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
     244             :         /* disassemble native stub */
     245             : 
     246             :         if (opt_DisassembleStubs) {
     247             :                 codegen_disassemble_stub(m,
     248             :                                                                  (u1 *) (ptrint) code->entrypoint,
     249             :                                                                  (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
     250             : 
     251             :                 /* show data segment */
     252             : 
     253             :                 if (opt_showddatasegment)
     254             :                         dseg_display(jd);
     255             :         }
     256             : #endif /* !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER) */
     257        2282 : }
     258             : 
     259             : 
     260             : /**
     261             :  * Wrapper for codegen_emit_stub_native.
     262             :  *
     263             :  * @param m Method object of the native function.
     264             :  * @param f Native function pointer.
     265             :  *
     266             :  * @return The codeinfo representing the stub code.
     267             :  */
     268       10775 : codeinfo* NativeStub::generate(methodinfo* m, functionptr f)
     269             : {
     270             :         jitdata     *jd;
     271             :         codeinfo    *code;
     272             :         methoddesc  *md;
     273             :         methoddesc  *nmd;       
     274             :         int          skipparams;
     275             : 
     276             :         // Create new dump memory area.
     277       10775 :         DumpMemoryArea dma;
     278             : 
     279             :         /* Create JIT data structure. */
     280             : 
     281       10775 :         jd = jit_jitdata_new(m);
     282             : 
     283             :         /* Get required compiler data. */
     284             : 
     285       10775 :         code = jd->code;
     286             : 
     287             :         /* Stubs are non-leaf methods. */
     288             : 
     289       10775 :         code_unflag_leafmethod(code);
     290             : 
     291             :         /* set the flags for the current JIT run */
     292             : 
     293             : #if defined(ENABLE_PROFILING)
     294             :         if (opt_prof)
     295             :                 jd->flags |= JITDATA_FLAG_INSTRUMENT;
     296             : #endif
     297             : 
     298       10775 :         if (opt_verbosecall)
     299           0 :                 jd->flags |= JITDATA_FLAG_VERBOSECALL;
     300             : 
     301             :         /* setup code generation stuff */
     302             : 
     303             : #if defined(ENABLE_JIT)
     304             : # if defined(ENABLE_INTRP)
     305             :         if (!opt_intrp)
     306             : # endif
     307       10775 :                 reg_setup(jd);
     308             : #endif
     309             : 
     310       10775 :         codegen_setup(jd);
     311             : 
     312             :         /* create new method descriptor with additional native parameters */
     313             : 
     314       10775 :         md = m->parseddesc;
     315             : 
     316             :         /* Set the number of native arguments we need to skip. */
     317             : 
     318       10775 :         if (m->flags & ACC_STATIC)
     319        5157 :                 skipparams = 2;
     320             :         else
     321        5618 :                 skipparams = 1;
     322             :         
     323             :         nmd = (methoddesc*) DumpMemory::allocate(sizeof(methoddesc) - sizeof(typedesc) +
     324             :                                                                                          md->paramcount * sizeof(typedesc) +
     325       10775 :                                                                                          skipparams * sizeof(typedesc));
     326             : 
     327       10775 :         nmd->paramcount = md->paramcount + skipparams;
     328             : 
     329       10775 :         nmd->params = (paramdesc*) DumpMemory::allocate(sizeof(paramdesc) * nmd->paramcount);
     330             : 
     331       10775 :         nmd->paramtypes[0].type = TYPE_ADR; /* add environment pointer            */
     332             : 
     333       10775 :         if (m->flags & ACC_STATIC)
     334        5157 :                 nmd->paramtypes[1].type = TYPE_ADR; /* add class pointer              */
     335             : 
     336             :         MCOPY(nmd->paramtypes + skipparams, md->paramtypes, typedesc,
     337       10775 :                   md->paramcount);
     338             : 
     339             : #if defined(ENABLE_JIT)
     340             : # if defined(ENABLE_INTRP)
     341             :         if (!opt_intrp)
     342             : # endif
     343             :                 /* pre-allocate the arguments for the native ABI */
     344             : 
     345       10775 :                 md_param_alloc_native(nmd);
     346             : #endif
     347             : 
     348             :         /* generate the code */
     349             : 
     350             : #if defined(ENABLE_JIT)
     351             : # if defined(ENABLE_INTRP)
     352             :         if (opt_intrp)
     353             :                 intrp_createnativestub(f, jd, nmd);
     354             :         else
     355             : # endif
     356       10775 :                 codegen_emit_stub_native(jd, nmd, f, skipparams);
     357             : #else
     358             :         intrp_createnativestub(f, jd, nmd);
     359             : #endif
     360             : 
     361             :         /* reallocate the memory and finish the code generation */
     362             : 
     363       10775 :         codegen_finish(jd);
     364             : 
     365             :         /* must be done after codegen_finish() */
     366             :         STATISTICS(size_stub_native += code->mcodelength);
     367             : 
     368             : #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
     369             :         /* disassemble native stub */
     370             : 
     371             :         if (opt_DisassembleStubs) {
     372             : # if defined(ENABLE_DEBUG_FILTER)
     373             :                 if (m->filtermatches & SHOW_FILTER_FLAG_SHOW_METHOD)
     374             : # endif
     375             :                 {
     376             :                         codegen_disassemble_stub(m,
     377             :                                                                          (u1 *) (ptrint) code->entrypoint,
     378             :                                                                          (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
     379             : 
     380             :                         /* show data segment */
     381             : 
     382             :                         if (opt_showddatasegment)
     383             :                                 dseg_display(jd);
     384             :                 }
     385             :         }
     386             : #endif /* !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER) */
     387             : 
     388             :         /* return native stub code */
     389             : 
     390       10775 :         return code;
     391             : }
     392             : 
     393             : 
     394             : /**
     395             :  * Free a native stub from memory.
     396             :  *
     397             :  * @param stub Pointer to stub memory.
     398             :  */    
     399           0 : void NativeStub::remove(void* stub)
     400             : {
     401             :         // Pass size 1 to keep the intern function happy.
     402           0 :         CFREE(stub, 1);
     403           0 : }
     404             : 
     405             : 
     406             : /*
     407             :  * These are local overrides for various environment variables in Emacs.
     408             :  * Please do not remove this and leave it at the end of the file, where
     409             :  * Emacs will automagically detect them.
     410             :  * ---------------------------------------------------------------------
     411             :  * Local variables:
     412             :  * mode: c++
     413             :  * indent-tabs-mode: t
     414             :  * c-basic-offset: 4
     415             :  * tab-width: 4
     416             :  * End:
     417             :  * vim:noexpandtab:sw=4:ts=4:
     418             :  */

Generated by: LCOV version 1.11