* src/vm/builtin.c (builtin_print_cycles_stats): 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                         Edwin Steiner
33
34    $Id: dseg.c 4734 2006-04-05 09:57:55Z edwin $
35
36 */
37
38
39 #include "config.h"
40
41 #include <assert.h>
42
43 #include "vm/types.h"
44
45 #include "mm/memory.h"
46 #include "vm/jit/codegen-common.h"
47
48
49 /* desg_increase ***************************************************************
50
51    Doubles data area.
52
53 *******************************************************************************/
54
55 void dseg_increase(codegendata *cd)
56 {
57         u1 *newstorage;
58
59         newstorage = DMNEW(u1, cd->dsegsize * 2);
60
61         MCOPY(newstorage + cd->dsegsize, cd->dsegtop - cd->dsegsize, u1,
62                   cd->dsegsize);
63
64         cd->dsegtop   = newstorage;
65         cd->dsegsize *= 2;
66         cd->dsegtop  += cd->dsegsize;
67 }
68
69
70 s4 dseg_adds4_increase(codegendata *cd, s4 value)
71 {
72         dseg_increase(cd);
73
74         *((s4 *) (cd->dsegtop - cd->dseglen)) = value;
75
76         return -(cd->dseglen);
77 }
78
79
80 s4 dseg_adds4(codegendata *cd, s4 value)
81 {
82         s4 *dataptr;
83
84         cd->dseglen += 4;
85         dataptr = (s4 *) (cd->dsegtop - cd->dseglen);
86
87         if (cd->dseglen > cd->dsegsize)
88                 return dseg_adds4_increase(cd, value);
89
90         *dataptr = value;
91
92         return -(cd->dseglen);
93 }
94
95
96 s4 dseg_adds8_increase(codegendata *cd, s8 value)
97 {
98         dseg_increase(cd);
99
100         *((s8 *) (cd->dsegtop - cd->dseglen)) = value;
101
102         return -(cd->dseglen);
103 }
104
105
106 s4 dseg_adds8(codegendata *cd, s8 value)
107 {
108         s8 *dataptr;
109
110         cd->dseglen = ALIGN(cd->dseglen + 8, 8);
111         dataptr = (s8 *) (cd->dsegtop - cd->dseglen);
112
113         if (cd->dseglen > cd->dsegsize)
114                 return dseg_adds8_increase(cd, value);
115
116         *dataptr = value;
117
118         return -(cd->dseglen);
119 }
120
121
122 s4 dseg_addfloat_increase(codegendata *cd, float value)
123 {
124         dseg_increase(cd);
125
126         *((float *) (cd->dsegtop - cd->dseglen)) = value;
127
128         return -(cd->dseglen);
129 }
130
131
132 s4 dseg_addfloat(codegendata *cd, float value)
133 {
134         float *dataptr;
135
136         cd->dseglen += 4;
137         dataptr = (float *) (cd->dsegtop - cd->dseglen);
138
139         if (cd->dseglen > cd->dsegsize)
140                 return dseg_addfloat_increase(cd, value);
141
142         *dataptr = value;
143
144         return -(cd->dseglen);
145 }
146
147
148 s4 dseg_adddouble_increase(codegendata *cd, double value)
149 {
150         dseg_increase(cd);
151
152         *((double *) (cd->dsegtop - cd->dseglen)) = value;
153
154         return -(cd->dseglen);
155 }
156
157
158 s4 dseg_adddouble(codegendata *cd, double value)
159 {
160         double *dataptr;
161
162         cd->dseglen = ALIGN(cd->dseglen + 8, 8);
163         dataptr = (double *) (cd->dsegtop - cd->dseglen);
164
165         if (cd->dseglen > cd->dsegsize)
166                 return dseg_adddouble_increase(cd, value);
167
168         *dataptr = value;
169
170         return -(cd->dseglen);
171 }
172
173
174 void dseg_addtarget(codegendata *cd, basicblock *target)
175 {
176         jumpref *jr;
177
178         jr = DNEW(jumpref);
179
180         jr->tablepos = dseg_addaddress(cd, NULL);
181         jr->target   = target;
182         jr->next     = cd->jumpreferences;
183
184         cd->jumpreferences = jr;
185 }
186
187
188 /* dseg_addlinenumbertablesize *************************************************
189
190    XXX
191
192 *******************************************************************************/
193
194 void dseg_addlinenumbertablesize(codegendata *cd)
195 {
196 #if SIZEOF_VOID_P == 8
197         /* 4-byte ALIGNMENT PADDING */
198
199         dseg_adds4(cd, 0);
200 #endif
201
202         cd->linenumbertablesizepos  = dseg_addaddress(cd, NULL);
203         cd->linenumbertablestartpos = dseg_addaddress(cd, NULL);
204
205 #if SIZEOF_VOID_P == 8
206         /* 4-byte ALIGNMENT PADDING */
207
208         dseg_adds4(cd, 0);
209 #endif
210 }
211
212
213 /* dseg_addlinenumber **********************************************************
214
215    Add a line number reference.
216
217    IN:
218       cd.............current codegen data
219       linenumber.....number of line that starts with the given mcodeptr
220       mcodeptr.......start mcodeptr of line
221
222 *******************************************************************************/
223
224 void dseg_addlinenumber(codegendata *cd, u2 linenumber, u1 *mcodeptr)
225 {
226         linenumberref *lr;
227
228         lr = DNEW(linenumberref);
229
230         lr->linenumber = linenumber;
231         lr->tablepos   = 0;
232         lr->targetmpc  = mcodeptr - cd->mcodebase;
233         lr->next       = cd->linenumberreferences;
234
235         cd->linenumberreferences = lr;
236 }
237
238
239 /* dseg_addlinenumber_inline_start *********************************************
240
241    Add a marker to the line number table indicating the start of an inlined
242    method body. (see doc/inlining_stacktrace.txt)
243
244    IN:
245       cd.............current codegen data
246       iptr...........the ICMD_INLINE_START instruction
247       mcodeptr.......start mcodeptr of inlined body
248
249 *******************************************************************************/
250
251 void dseg_addlinenumber_inline_start(codegendata *cd, 
252                                                                          instruction *iptr, 
253                                                                          u1 *mcodeptr)
254 {
255         linenumberref *lr;
256         insinfo_inline *insinfo;
257         ptrint mpc;
258
259         lr = DNEW(linenumberref);
260
261         lr->linenumber = (-2); /* marks start of inlined method */
262         lr->tablepos   = 0;
263         lr->targetmpc  = (mpc = mcodeptr - cd->mcodebase);
264         lr->next       = cd->linenumberreferences;
265
266         cd->linenumberreferences = lr;
267
268         insinfo = (insinfo_inline *) iptr->target;
269
270         insinfo->startmpc = mpc; /* store for corresponding INLINE_END */
271 }
272
273
274 /* dseg_addlinenumber_inline_end ***********************************************
275
276    Add a marker to the line number table indicating the end of an inlined
277    method body. (see doc/inlining_stacktrace.txt)
278
279    IN:
280       cd.............current codegen data
281       iptr...........the ICMD_INLINE_END instruction
282
283    Note:
284       iptr->method must point to the inlined callee.
285
286 *******************************************************************************/
287
288 void dseg_addlinenumber_inline_end(codegendata *cd, instruction *iptr)
289 {
290         linenumberref *lr;
291         linenumberref *prev;
292         insinfo_inline *insinfo;
293
294         insinfo = (insinfo_inline *) iptr->target;
295
296         assert(insinfo);
297
298         lr = DNEW(linenumberref);
299
300         /* special entry containing the methodinfo * */
301         lr->linenumber = (-3) - iptr->line;
302         lr->tablepos   = 0;
303         lr->targetmpc  = (ptrint) insinfo->method;
304         lr->next       = cd->linenumberreferences;
305
306         prev = lr;
307         lr = DNEW(linenumberref);
308
309         /* end marker with PC of start of body */
310         lr->linenumber = (-1);
311         lr->tablepos   = 0;
312         lr->targetmpc  = insinfo->startmpc;
313         lr->next       = prev;
314
315         cd->linenumberreferences = lr;
316 }
317
318
319 /* dseg_createlinenumbertable **************************************************
320
321    Creates a line number table in the data segment from the created
322    entries in linenumberreferences.
323
324 *******************************************************************************/
325
326 void dseg_createlinenumbertable(codegendata *cd)
327 {
328         linenumberref *lr;
329
330         for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
331                 lr->tablepos = dseg_addaddress(cd, NULL);
332
333                 if (cd->linenumbertab == 0)
334                         cd->linenumbertab = lr->tablepos;
335
336                 dseg_addaddress(cd, lr->linenumber);
337         }
338 }
339
340
341 /* dseg_adddata ****************************************************************
342
343    Adds a data segment reference to the codegendata.
344
345 *******************************************************************************/
346
347 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(ENABLE_INTRP)
348 void dseg_adddata(codegendata *cd, u1 *mcodeptr)
349 {
350         dataref *dr;
351
352         dr = DNEW(dataref);
353
354         dr->datapos = mcodeptr - cd->mcodebase;
355         dr->next    = cd->datareferences;
356
357         cd->datareferences = dr;
358 }
359 #endif
360
361
362 /* dseg_resolve_datareferences *************************************************
363
364    Resolve data segment references.
365
366 *******************************************************************************/
367
368 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(ENABLE_INTRP)
369 void dseg_resolve_datareferences(jitdata *jd)
370 {
371         codeinfo    *code;
372         codegendata *cd;
373         dataref     *dr;
374
375         /* get required compiler data */
376
377         code = jd->code;
378         cd   = jd->cd;
379
380         /* data segment references resolving */
381
382         for (dr = cd->datareferences; dr != NULL; dr = dr->next)
383                 *((u1 **) (code->entrypoint + dr->datapos - SIZEOF_VOID_P)) = code->entrypoint;
384 }
385 #endif
386
387
388 /* dseg_display ****************************************************************
389
390    Displays the content of the methods' data segment.
391
392 *******************************************************************************/
393
394 #if !defined(NDEBUG)
395 void dseg_display(jitdata *jd)
396 {
397         codeinfo    *code;
398         codegendata *cd;
399         s4          *s4ptr;
400         s4           i;
401         
402         /* get required compiler data */
403
404         code = jd->code;
405         cd   = jd->cd;
406
407         s4ptr = (s4 *) (ptrint) code->mcode;
408
409         printf("  --- dump of datasegment\n");
410
411         for (i = cd->dseglen; i > 0 ; i -= 4) {
412 #if SIZEOF_VOID_P == 8
413                 printf("0x%016lx:   -%6x (%6d): %8x\n",
414                            (ptrint) s4ptr, i, i, (s4) *s4ptr);
415 #else
416                 printf("0x%08x:   -%6x (%6d): %8x\n",
417                            (ptrint) s4ptr, i, i, (s4) *s4ptr);
418 #endif
419                 s4ptr++;
420         }
421
422         printf("  --- begin of data segment: %p\n", (void *) s4ptr);
423 }
424 #endif /* !defined(NDEBUG) */
425
426
427 /*
428  * These are local overrides for various environment variables in Emacs.
429  * Please do not remove this and leave it at the end of the file, where
430  * Emacs will automagically detect them.
431  * ---------------------------------------------------------------------
432  * Local variables:
433  * mode: c
434  * indent-tabs-mode: t
435  * c-basic-offset: 4
436  * tab-width: 4
437  * End:
438  * vim:noexpandtab:sw=4:ts=4:
439  */