CACAO
linenumbertable.cpp
Go to the documentation of this file.
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 
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 void Linenumber::resolve(const codeinfo* code)
57 {
58  void* pv = ADDR_MASK(void*, code->entrypoint);
59 
60  // TODO Use constant.
61  if (_linenumber >= -2)
62  _pc = (void*) ((uintptr_t) pv + (uintptr_t) _pc);
63 }
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 LinenumberTable::LinenumberTable(jitdata* jd) : _linenumbers(jd->cd->linenumbers->begin(), jd->cd->linenumbers->end())
75 {
76  // Get required compiler data.
77  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  (void) for_each(_linenumbers.begin(), _linenumbers.end(), std::bind2nd(LinenumberResolver(), code));
86 }
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 int32_t LinenumberTable::find(methodinfo **pm, void* pc)
98 {
99  void* maskpc = ADDR_MASK(void*, pc);
100 
101  std::vector<Linenumber>::iterator it = find_if(_linenumbers.begin(), _linenumbers.end(), std::bind2nd(comparator(), maskpc));
102 
103  // No matching entry found.
104  if (it == _linenumbers.end())
105  return 0;
106 
107  Linenumber& ln = *it;
108  int32_t linenumber = ln.get_linenumber();
109 
110  // Check for linenumber entry type.
111  if (linenumber < 0) {
112  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  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 void linenumbertable_list_entry_add(codegendata *cd, int32_t linenumber)
168 {
169  void* pc = (void*) (cd->mcodeptr - cd->mcodebase);
170  Linenumber ln(linenumber, pc);
171 
172  cd->linenumbers->push_front(ln);
173 }
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 
188 {
189  void* pc = (void*) (cd->mcodeptr - cd->mcodebase);
190 
191  Linenumber ln(-2 /* marks start of inlined method */, pc);
192 
193  cd->linenumbers->push_front(ln);
194 
195  insinfo_inline* insinfo = iptr->sx.s23.s3.inlineinfo;
196  insinfo->startmpc = (int32_t) (uintptr_t) pc; /* store for corresponding INLINE_END */
197 }
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 
215 {
216  insinfo_inline* insinfo = iptr->sx.s23.s3.inlineinfo;
217 
218  // Sanity check.
219  assert(insinfo);
220 
221  // Special entry containing the methodinfo.
222  Linenumber ln((-3) - iptr->line, insinfo->method);
223 
224  cd->linenumbers->push_front(ln);
225 
226  // End marker with PC of start of body.
227  Linenumber lne(-1, (void*) (std::ptrdiff_t)insinfo->startmpc);
228 
229  cd->linenumbers->push_front(lne);
230 }
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  */
#define pv
Definition: md-asm.hpp:65
#define STATISTICS(x)
Wrapper for statistics only code.
Definition: statistics.hpp:975
DumpList< Linenumber > * linenumbers
List of line numbers.
Definition: jit.hpp:126
void linenumbertable_list_entry_add(codegendata *cd, int32_t linenumber)
Linenumber table of a Java method.
codeinfo * code
Definition: jit.hpp:128
typedef void(JNICALL *jvmtiEventSingleStep)(jvmtiEnv *jvmti_env
int32_t get_linenumber() const
Unary function to resolve Linenumber objects.
#define ADDR_MASK(type, x)
methodinfo * method
This file contains the statistics framework.
void linenumbertable_list_entry_add_inline_start(codegendata *cd, instruction *iptr)
std::vector< Linenumber > _linenumbers
union instruction::@12 sx
static void abort()
Definition: os.hpp:196
#define pc
Definition: md-asm.hpp:56
struct instruction::@12::@13 s23
void linenumbertable_list_entry_add_inline_end(codegendata *cd, instruction *iptr)
int32_t find(methodinfo **pm, void *pc)
Search the the line number table for the line corresponding to a given program counter.
#define STAT_DECLARE_VAR(type, var, init)
Declare an external statistics variable.
Definition: statistics.hpp:963
LinenumberTable(jitdata *jd)
Creates a linenumber table.
Represents a Java line number.