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 : */
|