LCOV - code coverage report
Current view: top level - vm/jit - linenumbertable.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 22 39 56.4 %
Date: 2015-06-10 18:10:59 Functions: 4 7 57.1 %

          Line data    Source code
       1             : /* src/vm/jit/linenumbertable.cpp - linenumber handling stuff
       2             : 
       3             :    Copyright (C) 2007-2013
       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             : #include "vm/jit/linenumbertable.hpp"
      26             : #include <assert.h>                     // for assert
      27             : #include <stdint.h>                     // for int32_t, uintptr_t
      28             : #include <algorithm>                    // for find_if, for_each
      29             : #include <list>                         // for _List_iterator
      30             : #include "config.h"                     // for ENABLE_STATISTICS
      31             : #include "toolbox/list.hpp"             // for DumpList
      32             : #include "vm/jit/code.hpp"              // for codeinfo
      33             : #include "vm/jit/codegen-common.hpp"    // for codegendata
      34             : #include "vm/jit/ir/instruction.hpp"    // for insinfo_inline, instruction, etc
      35             : #include "vm/jit/jit.hpp"               // for jitdata
      36             : #include "vm/os.hpp"                    // for os
      37             : #include "vm/statistics.hpp"            // for StatVar
      38             : 
      39             : #if defined(__S390__)
      40             : #  define ADDR_MASK(type, x) ((type)((uintptr_t)(x) & 0x7FFFFFFF))
      41             : #else
      42             : #  define ADDR_MASK(type, x) (x)
      43             : #endif
      44             : 
      45             : STAT_DECLARE_VAR(int,count_linenumbertable,0)
      46             : STAT_DECLARE_VAR(int,size_linenumbertable,0)
      47             : 
      48             : /**
      49             :  * Resolve the linenumber.
      50             :  *
      51             :  * If the entry contains an mcode pointer (normal case), resolve it
      52             :  * (see doc/inlining_stacktrace.txt for details).
      53             :  *
      54             :  * @param code Code structure.
      55             :  */
      56      828758 : void Linenumber::resolve(const codeinfo* code)
      57             : {
      58      828758 :         void* pv = ADDR_MASK(void*, code->entrypoint);
      59             : 
      60             :         // TODO Use constant.
      61      828758 :         if (_linenumber >= -2)
      62      828758 :                 _pc = (void*) ((uintptr_t) pv + (uintptr_t) _pc);
      63      828758 : }
      64             : 
      65             : 
      66             : /**
      67             :  * Creates a linenumber table.
      68             :  *
      69             :  * We allocate an array and store the linenumber entry in
      70             :  * reverse-order, so we can search the correct linenumber more easily.
      71             :  *
      72             :  * @param jd JIT data.
      73             :  */
      74       99456 : LinenumberTable::LinenumberTable(jitdata* jd) : _linenumbers(jd->cd->linenumbers->begin(), jd->cd->linenumbers->end())
      75             : {
      76             :         // Get required compiler data.
      77       99456 :         codeinfo* code = jd->code;
      78             : 
      79             :         STATISTICS(count_linenumbertable++);
      80             :         STATISTICS(size_linenumbertable +=
      81             :                 sizeof(LinenumberTable) +
      82             :                 sizeof(Linenumber) * _linenumbers.size());
      83             : 
      84             :         // Resolve all linenumbers in the vector.
      85       99456 :         (void) for_each(_linenumbers.begin(), _linenumbers.end(), std::bind2nd(LinenumberResolver(), code));
      86           0 : }
      87             : 
      88             : 
      89             : /**
      90             :  * Search the the line number table for the line corresponding to a
      91             :  * given program counter.
      92             :  *
      93             :  * @param pc Program counter.
      94             :  *
      95             :  * @return Line number.
      96             :  */
      97         118 : int32_t LinenumberTable::find(methodinfo **pm, void* pc)
      98             : {
      99         118 :         void* maskpc = ADDR_MASK(void*, pc);
     100             : 
     101         118 :         std::vector<Linenumber>::iterator it = find_if(_linenumbers.begin(), _linenumbers.end(), std::bind2nd(comparator(), maskpc));
     102             : 
     103             :         // No matching entry found.
     104         118 :         if (it == _linenumbers.end())
     105           8 :                 return 0;
     106             : 
     107         110 :         Linenumber& ln = *it;
     108         110 :         int32_t linenumber = ln.get_linenumber();
     109             : 
     110             :         // Check for linenumber entry type.
     111         110 :         if (linenumber < 0) {
     112           0 :                 os::abort("FIX ME!");
     113             : 
     114             : #if 0
     115             :                 // We found a special inline entry (see
     116             :                 // doc/inlining_stacktrace.txt for details).
     117             :                 switch (linenumber) {
     118             :                 case -1:
     119             :                         // Begin of an inlined method (ie. INLINE_END instruction.
     120             :                         lntinline = --lnte;            /* get entry with methodinfo * */
     121             :                         lnte--;                        /* skip the special entry      */
     122             : 
     123             :                         /* search inside the inlined method */
     124             : 
     125             :                         if (linenumbertable_linenumber_for_pc_intern(pm, lnte, lntsize, pc)) {
     126             :                                 /* the inlined method contained the pc */
     127             : 
     128             :                                 *pm = (methodinfo *) lntinline->pc;
     129             : 
     130             :                                 assert(lntinline->linenumber <= -3);
     131             : 
     132             :                                 return (-3) - lntinline->linenumber;
     133             :                         }
     134             : 
     135             :                         /* pc was not in inlined method, continue search.
     136             :                            Entries inside the inlined method will be skipped
     137             :                            because their lntentry->pc is higher than pc.  */
     138             :                         break;
     139             : 
     140             :                 case -2: 
     141             :                         /* end of inlined method */
     142             : 
     143             :                         return 0;
     144             : 
     145             :                         /* default: is only reached for an -3-line entry after
     146             :                            a skipped -2 entry. We can safely ignore it and
     147             :                            continue searching.  */
     148             :                 }
     149             : #endif
     150             :         }
     151             : 
     152             :         // Normal linenumber entry, return it.
     153         110 :         return linenumber;
     154             : }
     155             : 
     156             : 
     157             : /* linenumbertable_list_entry_add **********************************************
     158             : 
     159             :    Add a line number reference.
     160             : 
     161             :    IN:
     162             :       cd.............current codegen data
     163             :       linenumber.....number of line that starts with the given mcodeptr
     164             : 
     165             : *******************************************************************************/
     166             : 
     167      828758 : void linenumbertable_list_entry_add(codegendata *cd, int32_t linenumber)
     168             : {
     169      828758 :         void* pc = (void*) (cd->mcodeptr - cd->mcodebase);
     170      828758 :         Linenumber ln(linenumber, pc);
     171             : 
     172      828758 :         cd->linenumbers->push_front(ln);
     173      828758 : }
     174             : 
     175             : 
     176             : /* linenumbertable_list_entry_add_inline_start *********************************
     177             : 
     178             :    Add a marker to the line number table indicating the start of an
     179             :    inlined method body. (see doc/inlining_stacktrace.txt)
     180             : 
     181             :    IN:
     182             :       cd ..... current codegen data
     183             :       iptr ... the ICMD_INLINE_BODY instruction
     184             : 
     185             : *******************************************************************************/
     186             : 
     187           0 : void linenumbertable_list_entry_add_inline_start(codegendata *cd, instruction *iptr)
     188             : {
     189           0 :         void* pc = (void*) (cd->mcodeptr - cd->mcodebase);
     190             : 
     191           0 :         Linenumber ln(-2 /* marks start of inlined method */, pc);
     192             : 
     193           0 :         cd->linenumbers->push_front(ln);
     194             : 
     195           0 :         insinfo_inline* insinfo = iptr->sx.s23.s3.inlineinfo;
     196           0 :         insinfo->startmpc = (int32_t) (uintptr_t) pc; /* store for corresponding INLINE_END */
     197           0 : }
     198             : 
     199             : 
     200             : /* linenumbertable_list_entry_add_inline_end ***********************************
     201             : 
     202             :    Add a marker to the line number table indicating the end of an
     203             :    inlined method body. (see doc/inlining_stacktrace.txt)
     204             : 
     205             :    IN:
     206             :       cd ..... current codegen data
     207             :       iptr ... the ICMD_INLINE_END instruction
     208             : 
     209             :    Note:
     210             :       iptr->method must point to the inlined callee.
     211             : 
     212             : *******************************************************************************/
     213             : 
     214           0 : void linenumbertable_list_entry_add_inline_end(codegendata *cd, instruction *iptr)
     215             : {
     216           0 :         insinfo_inline* insinfo = iptr->sx.s23.s3.inlineinfo;
     217             : 
     218             :         // Sanity check.
     219           0 :         assert(insinfo);
     220             : 
     221             :         // Special entry containing the methodinfo.
     222           0 :         Linenumber ln((-3) - iptr->line, insinfo->method);
     223             : 
     224           0 :         cd->linenumbers->push_front(ln);
     225             : 
     226             :         // End marker with PC of start of body.
     227           0 :         Linenumber lne(-1, (void*) (std::ptrdiff_t)insinfo->startmpc);
     228             : 
     229           0 :         cd->linenumbers->push_front(lne);
     230           0 : }
     231             : 
     232             : 
     233             : /*
     234             :  * These are local overrides for various environment variables in Emacs.
     235             :  * Please do not remove this and leave it at the end of the file, where
     236             :  * Emacs will automagically detect them.
     237             :  * ---------------------------------------------------------------------
     238             :  * Local variables:
     239             :  * mode: c++
     240             :  * indent-tabs-mode: t
     241             :  * c-basic-offset: 4
     242             :  * tab-width: 4
     243             :  * End:
     244             :  * vim:noexpandtab:sw=4:ts=4:
     245             :  */

Generated by: LCOV version 1.11