Line data Source code
1 : /* src/vm/jit/dseg.cpp - data segment handling stuff
2 :
3 : Copyright (C) 1996-2014
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/dseg.hpp"
26 : #include <assert.h> // for assert
27 : #include <stdio.h> // for printf
28 : #include <inttypes.h> // for printf formatting macros
29 : #include "config.h" // for SIZEOF_VOID_P
30 : #include "mm/dumpmemory.hpp" // for DNEW
31 : #include "vm/jit/code.hpp" // for codeinfo
32 : #include "vm/jit/codegen-common.hpp" // for codegendata, dataref, etc
33 : #include "vm/jit/jit.hpp" // for jitdata, etc
34 : #include "vm/jit/methodheader.hpp"
35 : #include "vm/options.hpp" // for opt_debugcolor
36 : #include "vm/types.hpp" // for s4, s8, u4, ptrint, u1
37 :
38 :
39 :
40 : /* dseg_finish *****************************************************************
41 :
42 : Fills the data segment with the values stored.
43 :
44 : *******************************************************************************/
45 :
46 99456 : void dseg_finish(jitdata *jd)
47 : {
48 : codeinfo *code;
49 : codegendata *cd;
50 : dsegentry *de;
51 :
52 : /* get required compiler data */
53 :
54 99456 : code = jd->code;
55 99456 : cd = jd->cd;
56 :
57 : /* process all data segment entries */
58 :
59 916675 : for (de = cd->dseg; de != NULL; de = de->next) {
60 817219 : switch (de->type) {
61 : case TYPE_INT:
62 397824 : *((s4 *) (code->entrypoint + de->disp)) = de->val.i;
63 397824 : break;
64 :
65 : case TYPE_LNG:
66 19 : *((s8 *) (code->entrypoint + de->disp)) = de->val.l;
67 19 : break;
68 :
69 : case TYPE_FLT:
70 1550 : *((float *) (code->entrypoint + de->disp)) = de->val.f;
71 1550 : break;
72 :
73 : case TYPE_DBL:
74 122 : *((double *) (code->entrypoint + de->disp)) = de->val.d;
75 122 : break;
76 :
77 : case TYPE_ADR:
78 417704 : *((void **) (code->entrypoint + de->disp)) = de->val.a;
79 : break;
80 : }
81 : }
82 99456 : }
83 :
84 :
85 0 : static s4 dseg_find_s4(codegendata *cd, s4 value)
86 : {
87 : dsegentry *de;
88 :
89 : /* search all data segment entries for a matching entry */
90 :
91 0 : for (de = cd->dseg; de != NULL; de = de->next) {
92 0 : if (IS_INT_TYPE(de->type))
93 0 : if (de->flags & DSEG_FLAG_READONLY)
94 0 : if (de->val.i == value)
95 0 : return de->disp;
96 : }
97 :
98 : /* no matching entry was found */
99 :
100 0 : return 0;
101 : }
102 :
103 :
104 61 : static s4 dseg_find_s8(codegendata *cd, s8 value)
105 : {
106 : dsegentry *de;
107 :
108 : /* search all data segment entries for a matching entry */
109 :
110 318 : for (de = cd->dseg; de != NULL; de = de->next) {
111 299 : if (IS_LNG_TYPE(de->type))
112 42 : if (de->flags & DSEG_FLAG_READONLY)
113 42 : if (de->val.l == value)
114 42 : return de->disp;
115 : }
116 :
117 : /* no matching entry was found */
118 :
119 19 : return 0;
120 : }
121 :
122 :
123 4946 : static s4 dseg_find_float(codegendata *cd, float value)
124 : {
125 : dsegentry *de;
126 : imm_union val;
127 :
128 : /* we compare the hex value of the float as 0.0 == -0.0 */
129 :
130 4946 : val.f = value;
131 :
132 : /* search all data segment entries for a matching entry */
133 :
134 27611 : for (de = cd->dseg; de != NULL; de = de->next) {
135 26061 : if (IS_FLT_TYPE(de->type))
136 6880 : if (de->flags & DSEG_FLAG_READONLY)
137 6880 : if (de->val.i == val.i)
138 3396 : return de->disp;
139 : }
140 :
141 : /* no matching entry was found */
142 :
143 1550 : return 0;
144 : }
145 :
146 :
147 233 : static s4 dseg_find_double(codegendata *cd, double value)
148 : {
149 : dsegentry *de;
150 : imm_union val;
151 :
152 : /* we compare the hex value of the double as 0.0 == -0.0 */
153 :
154 233 : val.d = value;
155 :
156 : /* search all data segment entries for a matching entry */
157 :
158 6406 : for (de = cd->dseg; de != NULL; de = de->next) {
159 6284 : if (IS_DBL_TYPE(de->type))
160 803 : if (de->flags & DSEG_FLAG_READONLY)
161 803 : if (de->val.l == val.l)
162 111 : return de->disp;
163 : }
164 :
165 : /* no matching entry was found */
166 :
167 122 : return 0;
168 : }
169 :
170 :
171 305527 : static s4 dseg_find_address(codegendata *cd, void *value)
172 : {
173 : dsegentry *de;
174 :
175 : /* search all data segment entries for a matching entry */
176 :
177 6009066 : for (de = cd->dseg; de != NULL; de = de->next) {
178 5789186 : if (IS_ADR_TYPE(de->type))
179 4893939 : if (de->flags & DSEG_FLAG_READONLY)
180 1944229 : if (de->val.a == value)
181 85647 : return de->disp;
182 : }
183 :
184 : /* no matching entry was found */
185 :
186 219880 : return 0;
187 : }
188 :
189 :
190 : /* dseg_add_s4_intern **********************************************************
191 :
192 : Internal function to add an s4 value to the data segment.
193 :
194 : *******************************************************************************/
195 :
196 397824 : static s4 dseg_add_s4_intern(codegendata *cd, s4 value, u4 flags)
197 : {
198 : dsegentry *de;
199 :
200 : /* Increase data segment size, which is also the displacement into
201 : the data segment. */
202 :
203 397824 : cd->dseglen += 4;
204 :
205 : /* allocate new entry */
206 :
207 397824 : de = DNEW(dsegentry);
208 :
209 397824 : de->type = TYPE_INT;
210 397824 : de->flags = flags;
211 397824 : de->disp = -(cd->dseglen);
212 397824 : de->val.i = value;
213 397824 : de->next = cd->dseg;
214 :
215 : /* insert into the chain */
216 :
217 397824 : cd->dseg = de;
218 :
219 397824 : return de->disp;
220 : }
221 :
222 :
223 : /* dseg_add_unique_s4 **********************************************************
224 :
225 : Adds uniquely an s4 value to the data segment.
226 :
227 : *******************************************************************************/
228 :
229 397824 : s4 dseg_add_unique_s4(codegendata *cd, s4 value)
230 : {
231 : s4 disp;
232 :
233 397824 : disp = dseg_add_s4_intern(cd, value, DSEG_FLAG_UNIQUE);
234 :
235 397824 : return disp;
236 : }
237 :
238 :
239 : /* dseg_add_s4 *****************************************************************
240 :
241 : Adds an s4 value to the data segment. It tries to reuse previously
242 : added values.
243 :
244 : *******************************************************************************/
245 :
246 0 : s4 dseg_add_s4(codegendata *cd, s4 value)
247 : {
248 : s4 disp;
249 :
250 : /* search the data segment if the value is already stored */
251 :
252 0 : disp = dseg_find_s4(cd, value);
253 :
254 0 : if (disp != 0)
255 0 : return disp;
256 :
257 0 : disp = dseg_add_s4_intern(cd, value, DSEG_FLAG_READONLY);
258 :
259 0 : return disp;
260 : }
261 :
262 :
263 : /* dseg_add_s8_intern **********************************************************
264 :
265 : Internal function to add an s8 value to the data segment.
266 :
267 : *******************************************************************************/
268 :
269 19 : static s4 dseg_add_s8_intern(codegendata *cd, s8 value, u4 flags)
270 : {
271 : dsegentry *de;
272 :
273 : /* Increase data segment size, which is also the displacement into
274 : the data segment. */
275 :
276 19 : cd->dseglen = MEMORY_ALIGN(cd->dseglen + 8, 8);
277 :
278 : /* allocate new entry */
279 :
280 19 : de = DNEW(dsegentry);
281 :
282 19 : de->type = TYPE_LNG;
283 19 : de->flags = flags;
284 19 : de->disp = -(cd->dseglen);
285 19 : de->val.l = value;
286 19 : de->next = cd->dseg;
287 :
288 : /* insert into the chain */
289 :
290 19 : cd->dseg = de;
291 :
292 19 : return de->disp;
293 : }
294 :
295 :
296 : /* dseg_add_unique_s8 **********************************************************
297 :
298 : Adds uniquely an s8 value to the data segment.
299 :
300 : *******************************************************************************/
301 :
302 0 : s4 dseg_add_unique_s8(codegendata *cd, s8 value)
303 : {
304 : s4 disp;
305 :
306 0 : disp = dseg_add_s8_intern(cd, value, DSEG_FLAG_UNIQUE);
307 :
308 0 : return disp;
309 : }
310 :
311 :
312 : /* dseg_add_s8 *****************************************************************
313 :
314 : Adds an s8 value to the data segment. It tries to reuse previously
315 : added values.
316 :
317 : *******************************************************************************/
318 :
319 61 : s4 dseg_add_s8(codegendata *cd, s8 value)
320 : {
321 : s4 disp;
322 :
323 : /* search the data segment if the value is already stored */
324 :
325 61 : disp = dseg_find_s8(cd, value);
326 :
327 61 : if (disp != 0)
328 42 : return disp;
329 :
330 19 : disp = dseg_add_s8_intern(cd, value, DSEG_FLAG_READONLY);
331 :
332 19 : return disp;
333 : }
334 :
335 :
336 : /* dseg_add_float_intern *******************************************************
337 :
338 : Internal function to add a float value to the data segment.
339 :
340 : *******************************************************************************/
341 :
342 1550 : static s4 dseg_add_float_intern(codegendata *cd, float value, u4 flags)
343 : {
344 : dsegentry *de;
345 :
346 : /* Increase data segment size, which is also the displacement into
347 : the data segment. */
348 :
349 1550 : cd->dseglen += 4;
350 :
351 : /* allocate new entry */
352 :
353 1550 : de = DNEW(dsegentry);
354 :
355 1550 : de->type = TYPE_FLT;
356 1550 : de->flags = flags;
357 1550 : de->disp = -(cd->dseglen);
358 1550 : de->val.f = value;
359 1550 : de->next = cd->dseg;
360 :
361 : /* insert into the chain */
362 :
363 1550 : cd->dseg = de;
364 :
365 1550 : return de->disp;
366 : }
367 :
368 :
369 : /* dseg_add_unique_float *******************************************************
370 :
371 : Adds uniquely an float value to the data segment.
372 :
373 : *******************************************************************************/
374 :
375 0 : s4 dseg_add_unique_float(codegendata *cd, float value)
376 : {
377 : s4 disp;
378 :
379 0 : disp = dseg_add_float_intern(cd, value, DSEG_FLAG_UNIQUE);
380 :
381 0 : return disp;
382 : }
383 :
384 :
385 : /* dseg_add_float **************************************************************
386 :
387 : Adds an float value to the data segment. It tries to reuse
388 : previously added values.
389 :
390 : *******************************************************************************/
391 :
392 4946 : s4 dseg_add_float(codegendata *cd, float value)
393 : {
394 : s4 disp;
395 :
396 : /* search the data segment if the value is already stored */
397 :
398 4946 : disp = dseg_find_float(cd, value);
399 :
400 4946 : if (disp != 0)
401 3396 : return disp;
402 :
403 1550 : disp = dseg_add_float_intern(cd, value, DSEG_FLAG_READONLY);
404 :
405 1550 : return disp;
406 : }
407 :
408 :
409 : /* dseg_add_double_intern ******************************************************
410 :
411 : Internal function to add a double value to the data segment.
412 :
413 : *******************************************************************************/
414 :
415 122 : static s4 dseg_add_double_intern(codegendata *cd, double value, u4 flags)
416 : {
417 : dsegentry *de;
418 :
419 : /* Increase data segment size, which is also the displacement into
420 : the data segment. */
421 :
422 122 : cd->dseglen = MEMORY_ALIGN(cd->dseglen + 8, 8);
423 :
424 : /* allocate new entry */
425 :
426 122 : de = DNEW(dsegentry);
427 :
428 122 : de->type = TYPE_DBL;
429 122 : de->flags = flags;
430 122 : de->disp = -(cd->dseglen);
431 122 : de->val.d = value;
432 122 : de->next = cd->dseg;
433 :
434 : /* insert into the chain */
435 :
436 122 : cd->dseg = de;
437 :
438 122 : return de->disp;
439 : }
440 :
441 :
442 : /* dseg_add_unique_double ******************************************************
443 :
444 : Adds uniquely a double value to the data segment.
445 :
446 : *******************************************************************************/
447 :
448 0 : s4 dseg_add_unique_double(codegendata *cd, double value)
449 : {
450 : s4 disp;
451 :
452 0 : disp = dseg_add_double_intern(cd, value, DSEG_FLAG_UNIQUE);
453 :
454 0 : return disp;
455 : }
456 :
457 :
458 : /* dseg_add_double *************************************************************
459 :
460 : Adds a double value to the data segment. It tries to reuse
461 : previously added values.
462 :
463 : *******************************************************************************/
464 :
465 233 : s4 dseg_add_double(codegendata *cd, double value)
466 : {
467 : s4 disp;
468 :
469 : /* search the data segment if the value is already stored */
470 :
471 233 : disp = dseg_find_double(cd, value);
472 :
473 233 : if (disp != 0)
474 111 : return disp;
475 :
476 122 : disp = dseg_add_double_intern(cd, value, DSEG_FLAG_READONLY);
477 :
478 122 : return disp;
479 : }
480 :
481 :
482 : /* dseg_add_address_intern *****************************************************
483 :
484 : Internal function to add an address pointer to the data segment.
485 :
486 : *******************************************************************************/
487 :
488 417704 : static s4 dseg_add_address_intern(codegendata *cd, void *value, u4 flags)
489 : {
490 : dsegentry *de;
491 :
492 : /* Increase data segment size, which is also the displacement into
493 : the data segment. */
494 :
495 : #if SIZEOF_VOID_P == 8
496 417704 : cd->dseglen = MEMORY_ALIGN(cd->dseglen + 8, 8);
497 : #else
498 : cd->dseglen += 4;
499 : #endif
500 :
501 : /* allocate new entry */
502 :
503 417704 : de = DNEW(dsegentry);
504 :
505 417704 : de->type = TYPE_ADR;
506 417704 : de->flags = flags;
507 417704 : de->disp = -(cd->dseglen);
508 417704 : de->val.a = value;
509 417704 : de->next = cd->dseg;
510 :
511 : /* insert into the chain */
512 :
513 417704 : cd->dseg = de;
514 :
515 417704 : return de->disp;
516 : }
517 :
518 :
519 : /* dseg_add_unique_address *****************************************************
520 :
521 : Adds uniquely an address value to the data segment.
522 :
523 : *******************************************************************************/
524 :
525 197824 : s4 dseg_add_unique_address(codegendata *cd, void *value)
526 : {
527 : s4 disp;
528 :
529 197824 : disp = dseg_add_address_intern(cd, value, DSEG_FLAG_UNIQUE);
530 :
531 197824 : return disp;
532 : }
533 :
534 :
535 : /* dseg_add_address ************************************************************
536 :
537 : Adds an address value to the data segment. It tries to reuse
538 : previously added values.
539 :
540 : *******************************************************************************/
541 :
542 305527 : s4 dseg_add_address(codegendata *cd, void *value)
543 : {
544 : s4 disp;
545 :
546 : /* search the data segment if the value is already stored */
547 :
548 305527 : disp = dseg_find_address(cd, value);
549 :
550 305527 : if (disp != 0)
551 85647 : return disp;
552 :
553 219880 : disp = dseg_add_address_intern(cd, value, DSEG_FLAG_READONLY);
554 :
555 219880 : return disp;
556 : }
557 :
558 :
559 : /* dseg_add_target *************************************************************
560 :
561 : XXX
562 :
563 : *******************************************************************************/
564 :
565 1074 : void dseg_add_target(codegendata *cd, basicblock *target)
566 : {
567 : jumpref *jr;
568 :
569 1074 : jr = DNEW(jumpref);
570 :
571 1074 : jr->tablepos = dseg_add_unique_address(cd, NULL);
572 1074 : jr->target = target;
573 1074 : jr->next = cd->jumpreferences;
574 :
575 1074 : cd->jumpreferences = jr;
576 1074 : }
577 :
578 :
579 : /* dseg_adddata ****************************************************************
580 :
581 : Adds a data segment reference to the codegendata.
582 :
583 : *******************************************************************************/
584 :
585 : #if defined(__I386__) || defined(__X86_64__) || defined(__S390__) || defined(__XDSPCORE__) || defined(ENABLE_INTRP)
586 72 : void dseg_adddata(codegendata *cd)
587 : {
588 : dataref *dr;
589 :
590 72 : dr = DNEW(dataref);
591 :
592 72 : dr->datapos = cd->mcodeptr - cd->mcodebase;
593 72 : dr->next = cd->datareferences;
594 :
595 72 : cd->datareferences = dr;
596 72 : }
597 : #endif
598 :
599 :
600 : /* dseg_resolve_datareferences *************************************************
601 :
602 : Resolve data segment references.
603 :
604 : *******************************************************************************/
605 :
606 : #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(ENABLE_INTRP)
607 99456 : void dseg_resolve_datareferences(jitdata *jd)
608 : {
609 : codeinfo *code;
610 : codegendata *cd;
611 : dataref *dr;
612 :
613 : /* get required compiler data */
614 :
615 99456 : code = jd->code;
616 99456 : cd = jd->cd;
617 :
618 : /* data segment references resolving */
619 :
620 99528 : for (dr = cd->datareferences; dr != NULL; dr = dr->next)
621 72 : *((u1 **) (code->entrypoint + dr->datapos - SIZEOF_VOID_P)) = code->entrypoint;
622 99456 : }
623 : #endif
624 :
625 :
626 : /* dseg_display ****************************************************************
627 :
628 : Displays the content of the methods' data segment.
629 :
630 : *******************************************************************************/
631 :
632 : #if !defined(NDEBUG)
633 0 : void dseg_display(jitdata *jd)
634 : {
635 : codeinfo *code;
636 : codegendata *cd;
637 : dsegentry *de;
638 : imm_union val;
639 :
640 : /* get required compiler data */
641 :
642 0 : code = jd->code;
643 0 : cd = jd->cd;
644 :
645 0 : if (opt_debugcolor)
646 0 : printf("\033[34m"); /* blue */
647 :
648 0 : printf(" --- dump of datasegment\n");
649 :
650 : /* process all data segment entries */
651 :
652 0 : for (de = cd->dseg; de != NULL; de = de->next) {
653 0 : printf("0x%0" PRINTF_INTPTR_NUM_HEXDIGITS PRIxPTR ":", (ptrint) (code->entrypoint + de->disp));
654 :
655 0 : printf(" %6x (%6d): ", de->disp, de->disp);
656 :
657 : /* We read the values from the data segment as some values,
658 : like the line number table, have been written directly to
659 : the data segment. */
660 :
661 0 : switch (de->type) {
662 : case TYPE_INT:
663 0 : val.i = *((s4 *) (code->entrypoint + de->disp));
664 0 : printf("(INT) %d (0x%08x)", val.i, val.i);
665 0 : break;
666 :
667 : case TYPE_LNG:
668 0 : val.l = *((s8 *) (code->entrypoint + de->disp));
669 : printf("(LNG) %" PRId64 " (0x%0" PRINTF_INTPTR_NUM_HEXDIGITS PRIx64 ")",
670 0 : val.l, val.l);
671 0 : break;
672 :
673 : case TYPE_FLT:
674 0 : val.f = *((float *) (code->entrypoint + de->disp));
675 0 : printf("(FLT) %g (0x%08x)", val.f, val.i);
676 0 : break;
677 :
678 : case TYPE_DBL:
679 0 : val.d = *((double *) (code->entrypoint + de->disp));
680 0 : printf("(DBL) %g (0x%016" PRIx64 ")", val.d, val.l);
681 0 : break;
682 :
683 : case TYPE_ADR:
684 0 : val.a = *((void **) (code->entrypoint + de->disp));
685 0 : printf("(ADR) %0" PRINTF_INTPTR_NUM_HEXDIGITS PRIxPTR, (ptrint) val.a);
686 : break;
687 : }
688 :
689 0 : printf("\n");
690 : }
691 :
692 0 : printf(" --- begin of data segment: ");
693 0 : printf("0x%0" PRINTF_INTPTR_NUM_HEXDIGITS PRIxPTR "\n", (ptrint) code->entrypoint);
694 :
695 0 : if (opt_debugcolor)
696 0 : printf("\033[m");
697 0 : }
698 : #endif /* !defined(NDEBUG) */
699 :
700 :
701 : /*
702 : * These are local overrides for various environment variables in Emacs.
703 : * Please do not remove this and leave it at the end of the file, where
704 : * Emacs will automagically detect them.
705 : * ---------------------------------------------------------------------
706 : * Local variables:
707 : * mode: c++
708 : * indent-tabs-mode: t
709 : * c-basic-offset: 4
710 : * tab-width: 4
711 : * End:
712 : * vim:noexpandtab:sw=4:ts=4:
713 : */
|