* doc/inlining_stacktrace.txt: Added.
[cacao.git] / src / vm / jit / dseg.c
1 /* src/vm/jit/dseg.c - data segment handling stuff
2
3    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    Contact: cacao@cacaojvm.org
26
27    Authors: Reinhard Grafl
28             Andreas  Krall
29
30    Changes: Christian Thalinger
31             Joseph Wenninger
32
33    $Id: dseg.c 4445 2006-02-05 15:26:34Z edwin $
34
35 */
36
37
38 #include "config.h"
39
40 #include "vm/types.h"
41
42 #include <assert.h>
43 #include "mm/memory.h"
44 #include "vm/jit/codegen-common.h"
45
46
47 /* desg_increase ***************************************************************
48
49    Doubles data area.
50
51 *******************************************************************************/
52
53 void dseg_increase(codegendata *cd)
54 {
55         u1 *newstorage;
56
57         newstorage = DMNEW(u1, cd->dsegsize * 2);
58
59         MCOPY(newstorage + cd->dsegsize, cd->dsegtop - cd->dsegsize, u1,
60                   cd->dsegsize);
61
62         cd->dsegtop   = newstorage;
63         cd->dsegsize *= 2;
64         cd->dsegtop  += cd->dsegsize;
65 }
66
67
68 s4 dseg_adds4_increase(codegendata *cd, s4 value)
69 {
70         dseg_increase(cd);
71
72         *((s4 *) (cd->dsegtop - cd->dseglen)) = value;
73
74         return -(cd->dseglen);
75 }
76
77
78 s4 dseg_adds4(codegendata *cd, s4 value)
79 {
80         s4 *dataptr;
81
82         cd->dseglen += 4;
83         dataptr = (s4 *) (cd->dsegtop - cd->dseglen);
84
85         if (cd->dseglen > cd->dsegsize)
86                 return dseg_adds4_increase(cd, value);
87
88         *dataptr = value;
89
90         return -(cd->dseglen);
91 }
92
93
94 s4 dseg_adds8_increase(codegendata *cd, s8 value)
95 {
96         dseg_increase(cd);
97
98         *((s8 *) (cd->dsegtop - cd->dseglen)) = value;
99
100         return -(cd->dseglen);
101 }
102
103
104 s4 dseg_adds8(codegendata *cd, s8 value)
105 {
106         s8 *dataptr;
107
108         cd->dseglen = ALIGN(cd->dseglen + 8, 8);
109         dataptr = (s8 *) (cd->dsegtop - cd->dseglen);
110
111         if (cd->dseglen > cd->dsegsize)
112                 return dseg_adds8_increase(cd, value);
113
114         *dataptr = value;
115
116         return -(cd->dseglen);
117 }
118
119
120 s4 dseg_addfloat_increase(codegendata *cd, float value)
121 {
122         dseg_increase(cd);
123
124         *((float *) (cd->dsegtop - cd->dseglen)) = value;
125
126         return -(cd->dseglen);
127 }
128
129
130 s4 dseg_addfloat(codegendata *cd, float value)
131 {
132         float *dataptr;
133
134         cd->dseglen += 4;
135         dataptr = (float *) (cd->dsegtop - cd->dseglen);
136
137         if (cd->dseglen > cd->dsegsize)
138                 return dseg_addfloat_increase(cd, value);
139
140         *dataptr = value;
141
142         return -(cd->dseglen);
143 }
144
145
146 s4 dseg_adddouble_increase(codegendata *cd, double value)
147 {
148         dseg_increase(cd);
149
150         *((double *) (cd->dsegtop - cd->dseglen)) = value;
151
152         return -(cd->dseglen);
153 }
154
155
156 s4 dseg_adddouble(codegendata *cd, double value)
157 {
158         double *dataptr;
159
160         cd->dseglen = ALIGN(cd->dseglen + 8, 8);
161         dataptr = (double *) (cd->dsegtop - cd->dseglen);
162
163         if (cd->dseglen > cd->dsegsize)
164                 return dseg_adddouble_increase(cd, value);
165
166         *dataptr = value;
167
168         return -(cd->dseglen);
169 }
170
171
172 void dseg_addtarget(codegendata *cd, basicblock *target)
173 {
174         jumpref *jr;
175
176         jr = DNEW(jumpref);
177
178         jr->tablepos = dseg_addaddress(cd, NULL);
179         jr->target   = target;
180         jr->next     = cd->jumpreferences;
181
182         cd->jumpreferences = jr;
183 }
184
185
186 /* dseg_addlinenumbertablesize *************************************************
187
188    XXX
189
190 *******************************************************************************/
191
192 void dseg_addlinenumbertablesize(codegendata *cd)
193 {
194 #if SIZEOF_VOID_P == 8
195         /* 4-byte ALIGNMENT PADDING */
196
197         dseg_adds4(cd, 0);
198 #endif
199
200         cd->linenumbertablesizepos  = dseg_addaddress(cd, NULL);
201         cd->linenumbertablestartpos = dseg_addaddress(cd, NULL);
202
203 #if SIZEOF_VOID_P == 8
204         /* 4-byte ALIGNMENT PADDING */
205
206         dseg_adds4(cd, 0);
207 #endif
208 }
209
210
211 /* dseg_addlinenumber **********************************************************
212
213    Add a line number reference.
214
215    IN:
216       cd.............current codegen data
217       linenumber.....number of line that starts with the given mcodeptr
218       mcodeptr.......start mcodeptr of line
219
220 *******************************************************************************/
221
222 void dseg_addlinenumber(codegendata *cd, u2 linenumber, u1 *mcodeptr)
223 {
224         linenumberref *lr;
225
226         lr = DNEW(linenumberref);
227
228         lr->linenumber = linenumber;
229         lr->tablepos   = 0;
230         lr->targetmpc  = mcodeptr - cd->mcodebase;
231         lr->next       = cd->linenumberreferences;
232
233         cd->linenumberreferences = lr;
234 }
235
236
237 /* dseg_addlinenumber_inline_start *********************************************
238
239    Add a marker to the line number table indicating the start of an inlined
240    method body. (see doc/inlining_stacktrace.txt)
241
242    IN:
243       cd.............current codegen data
244       iptr...........the ICMD_INLINE_START instruction
245       mcodeptr.......start mcodeptr of inlined body
246
247 *******************************************************************************/
248
249 void dseg_addlinenumber_inline_start(codegendata *cd, 
250                                                                          instruction *iptr, 
251                                                                          u1 *mcodeptr)
252 {
253         linenumberref *lr;
254
255         lr = DNEW(linenumberref);
256
257         lr->linenumber = (-2); /* marks start of inlined method */
258         lr->tablepos   = 0;
259         lr->targetmpc  = mcodeptr - cd->mcodebase;
260         lr->next       = cd->linenumberreferences;
261
262         cd->linenumberreferences = lr;
263
264         iptr->target = mcodeptr; /* store for corresponding INLINE_END */
265 }
266
267
268 /* dseg_addlinenumber_inline_end ***********************************************
269
270    Add a marker to the line number table indicating the end of an inlined
271    method body. (see doc/inlining_stacktrace.txt)
272
273    IN:
274       cd.............current codegen data
275       iptr...........the ICMD_INLINE_END instruction
276
277    Note:
278       iptr->method must point to the inlined callee.
279
280 *******************************************************************************/
281
282 void dseg_addlinenumber_inline_end(codegendata *cd, instruction *iptr)
283 {
284         linenumberref *lr;
285         linenumberref *prev;
286         instruction *inlinestart;
287
288         /* get the pointer to the corresponding ICMD_INLINE_START */
289         inlinestart = (instruction *)iptr->target;
290
291         assert(inlinestart);
292         assert(iptr->method);
293
294         lr = DNEW(linenumberref);
295
296         /* special entry containing the methodinfo * */
297         lr->linenumber = (-3) - iptr->line;
298         lr->tablepos   = 0;
299         lr->targetmpc  = (ptrint) iptr->method;
300         lr->next       = cd->linenumberreferences;
301
302         prev = lr;
303         lr = DNEW(linenumberref);
304
305         /* end marker with PC of start of body */
306         lr->linenumber = (-1);
307         lr->tablepos   = 0;
308         lr->targetmpc  = (u1*)inlinestart->target - cd->mcodebase;
309         lr->next       = prev;
310
311         cd->linenumberreferences = lr;
312 }
313
314
315 /* dseg_createlinenumbertable **************************************************
316
317    Creates a line number table in the data segment from the created
318    entries in linenumberreferences.
319
320 *******************************************************************************/
321
322 void dseg_createlinenumbertable(codegendata *cd)
323 {
324         linenumberref *lr;
325
326         for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
327                 lr->tablepos = dseg_addaddress(cd, NULL);
328
329                 if (cd->linenumbertab == 0)
330                         cd->linenumbertab = lr->tablepos;
331
332                 dseg_addaddress(cd, lr->linenumber);
333         }
334 }
335
336
337 /* dseg_adddata ****************************************************************
338
339    Adds a data segment reference to the codegendata.
340
341 *******************************************************************************/
342
343 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(ENABLE_INTRP)
344 void dseg_adddata(codegendata *cd, u1 *mcodeptr)
345 {
346         dataref *dr;
347
348         dr = DNEW(dataref);
349
350         dr->datapos = mcodeptr - cd->mcodebase;
351         dr->next    = cd->datareferences;
352
353         cd->datareferences = dr;
354 }
355 #endif
356
357
358 /* dseg_resolve_datareferences *************************************************
359
360    Resolve data segment references.
361
362 *******************************************************************************/
363
364 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(ENABLE_INTRP)
365 void dseg_resolve_datareferences(codegendata *cd, methodinfo *m)
366 {
367         dataref *dr;
368
369         /* data segment references resolving */
370
371         for (dr = cd->datareferences; dr != NULL; dr = dr->next)
372                 *((u1 **) (m->entrypoint + dr->datapos - SIZEOF_VOID_P)) = m->entrypoint;
373 }
374 #endif
375
376
377 /* dseg_display ****************************************************************
378
379    Displays the content of the methods' data segment.
380
381 *******************************************************************************/
382
383 #if !defined(NDEBUG)
384 void dseg_display(methodinfo *m, codegendata *cd)
385 {
386         s4 *s4ptr;
387         s4 i;
388         
389         s4ptr = (s4 *) (ptrint) m->mcode;
390
391         printf("  --- dump of datasegment\n");
392
393         for (i = cd->dseglen; i > 0 ; i -= 4) {
394 #if SIZEOF_VOID_P == 8
395                 printf("0x%016lx:   -%6x (%6d): %8x\n",
396                            (ptrint) s4ptr, i, i, (s4) *s4ptr);
397 #else
398                 printf("0x%08x:   -%6x (%6d): %8x\n",
399                            (ptrint) s4ptr, i, i, (s4) *s4ptr);
400 #endif
401                 s4ptr++;
402         }
403
404         printf("  --- begin of data segment: %p\n", (void *) s4ptr);
405 }
406 #endif /* !defined(NDEBUG) */
407
408
409 /*
410  * These are local overrides for various environment variables in Emacs.
411  * Please do not remove this and leave it at the end of the file, where
412  * Emacs will automagically detect them.
413  * ---------------------------------------------------------------------
414  * Local variables:
415  * mode: c
416  * indent-tabs-mode: t
417  * c-basic-offset: 4
418  * tab-width: 4
419  * End:
420  * vim:noexpandtab:sw=4:ts=4:
421  */