LCOV - code coverage report
Current view: top level - vm/jit - stubs.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 60 67 89.6 %
Date: 2017-07-14 10:03:36 Functions: 4 6 66.7 %

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

Generated by: LCOV version 1.11