1 /* src/vm/jit/linenumbertable.cpp - linenumber handling stuff
3 Copyright (C) 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
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.
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.
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
33 #include "mm/memory.hpp"
35 #include "toolbox/list.hpp"
37 #if defined(ENABLE_STATISTICS)
38 # include "vm/options.h"
39 # include "vm/statistics.h"
42 #include "vm/jit/code.hpp"
43 #include "vm/jit/codegen-common.hpp"
44 #include "vm/jit/linenumbertable.hpp"
48 # define ADDR_MASK(type, x) ((type)((uintptr_t)(x) & 0x7FFFFFFF))
50 # define ADDR_MASK(type, x) (x)
55 * Resolve the linenumber.
57 * If the entry contains an mcode pointer (normal case), resolve it
58 * (see doc/inlining_stacktrace.txt for details).
60 * @param code Code structure.
62 void Linenumber::resolve(const codeinfo* code)
64 void* pv = ADDR_MASK(void*, code->entrypoint);
67 if (_linenumber >= -2)
68 _pc = (void*) ((uintptr_t) pv + (uintptr_t) _pc);
73 * Creates a linenumber table.
75 * We allocate an array and store the linenumber entry in
76 * reverse-order, so we can search the correct linenumber more easily.
80 LinenumberTable::LinenumberTable(jitdata* jd) : _linenumbers(jd->cd->linenumbers->begin(), jd->cd->linenumbers->end())
82 // Get required compiler data.
83 codeinfo* code = jd->code;
85 #if defined(ENABLE_STATISTICS)
87 count_linenumbertable++;
89 size_linenumbertable +=
90 sizeof(LinenumberTable) +
91 sizeof(Linenumber) * _linenumbers.size();
95 // Resolve all linenumbers in the vector.
96 (void) for_each(_linenumbers.begin(), _linenumbers.end(), std::bind2nd(LinenumberResolver(), code));
101 * Search the the line number table for the line corresponding to a
102 * given program counter.
104 * @param pc Program counter.
106 * @return Line number.
108 int32_t LinenumberTable::find(methodinfo **pm, void* pc)
110 void* maskpc = ADDR_MASK(void*, pc);
112 std::vector<Linenumber>::iterator it = find_if(_linenumbers.begin(), _linenumbers.end(), std::bind2nd(comparator(), maskpc));
114 // No matching entry found.
115 if (it == _linenumbers.end())
118 Linenumber& ln = *it;
119 int32_t linenumber = ln.get_linenumber();
121 // Check for linenumber entry type.
122 if (linenumber < 0) {
123 os::abort("FIX ME!");
126 // We found a special inline entry (see
127 // doc/inlining_stacktrace.txt for details).
128 switch (linenumber) {
130 // Begin of an inlined method (ie. INLINE_END instruction.
131 lntinline = --lnte; /* get entry with methodinfo * */
132 lnte--; /* skip the special entry */
134 /* search inside the inlined method */
136 if (linenumbertable_linenumber_for_pc_intern(pm, lnte, lntsize, pc)) {
137 /* the inlined method contained the pc */
139 *pm = (methodinfo *) lntinline->pc;
141 assert(lntinline->linenumber <= -3);
143 return (-3) - lntinline->linenumber;
146 /* pc was not in inlined method, continue search.
147 Entries inside the inlined method will be skipped
148 because their lntentry->pc is higher than pc. */
152 /* end of inlined method */
156 /* default: is only reached for an -3-line entry after
157 a skipped -2 entry. We can safely ignore it and
158 continue searching. */
163 // Normal linenumber entry, return it.
168 /* linenumbertable_list_entry_add **********************************************
170 Add a line number reference.
173 cd.............current codegen data
174 linenumber.....number of line that starts with the given mcodeptr
176 *******************************************************************************/
178 void linenumbertable_list_entry_add(codegendata *cd, int32_t linenumber)
180 void* pc = (void*) (cd->mcodeptr - cd->mcodebase);
181 Linenumber ln(linenumber, pc);
183 cd->linenumbers->push_front(ln);
187 /* linenumbertable_list_entry_add_inline_start *********************************
189 Add a marker to the line number table indicating the start of an
190 inlined method body. (see doc/inlining_stacktrace.txt)
193 cd ..... current codegen data
194 iptr ... the ICMD_INLINE_BODY instruction
196 *******************************************************************************/
198 void linenumbertable_list_entry_add_inline_start(codegendata *cd, instruction *iptr)
200 void* pc = (void*) (cd->mcodeptr - cd->mcodebase);
202 Linenumber ln(-2 /* marks start of inlined method */, pc);
204 cd->linenumbers->push_front(ln);
206 insinfo_inline* insinfo = iptr->sx.s23.s3.inlineinfo;
207 insinfo->startmpc = (int32_t) (uintptr_t) pc; /* store for corresponding INLINE_END */
211 /* linenumbertable_list_entry_add_inline_end ***********************************
213 Add a marker to the line number table indicating the end of an
214 inlined method body. (see doc/inlining_stacktrace.txt)
217 cd ..... current codegen data
218 iptr ... the ICMD_INLINE_END instruction
221 iptr->method must point to the inlined callee.
223 *******************************************************************************/
225 void linenumbertable_list_entry_add_inline_end(codegendata *cd, instruction *iptr)
227 insinfo_inline* insinfo = iptr->sx.s23.s3.inlineinfo;
232 // Special entry containing the methodinfo.
233 Linenumber ln((-3) - iptr->line, insinfo->method);
235 cd->linenumbers->push_front(ln);
237 // End marker with PC of start of body.
238 Linenumber lne(-1, (void*) insinfo->startmpc);
240 cd->linenumbers->push_front(lne);
245 * These are local overrides for various environment variables in Emacs.
246 * Please do not remove this and leave it at the end of the file, where
247 * Emacs will automagically detect them.
248 * ---------------------------------------------------------------------
251 * indent-tabs-mode: t
255 * vim:noexpandtab:sw=4:ts=4: