CACAO
dseg.cpp
Go to the documentation of this file.
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 
47 {
48  codeinfo *code;
49  codegendata *cd;
50  dsegentry *de;
51 
52  /* get required compiler data */
53 
54  code = jd->code;
55  cd = jd->cd;
56 
57  /* process all data segment entries */
58 
59  for (de = cd->dseg; de != NULL; de = de->next) {
60  switch (de->type) {
61  case TYPE_INT:
62  *((s4 *) (code->entrypoint + de->disp)) = de->val.i;
63  break;
64 
65  case TYPE_LNG:
66  *((s8 *) (code->entrypoint + de->disp)) = de->val.l;
67  break;
68 
69  case TYPE_FLT:
70  *((float *) (code->entrypoint + de->disp)) = de->val.f;
71  break;
72 
73  case TYPE_DBL:
74  *((double *) (code->entrypoint + de->disp)) = de->val.d;
75  break;
76 
77  case TYPE_ADR:
78  *((void **) (code->entrypoint + de->disp)) = de->val.a;
79  break;
80  }
81  }
82 }
83 
84 
85 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  for (de = cd->dseg; de != NULL; de = de->next) {
92  if (IS_INT_TYPE(de->type))
93  if (de->flags & DSEG_FLAG_READONLY)
94  if (de->val.i == value)
95  return de->disp;
96  }
97 
98  /* no matching entry was found */
99 
100  return 0;
101 }
102 
103 
104 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  for (de = cd->dseg; de != NULL; de = de->next) {
111  if (IS_LNG_TYPE(de->type))
112  if (de->flags & DSEG_FLAG_READONLY)
113  if (de->val.l == value)
114  return de->disp;
115  }
116 
117  /* no matching entry was found */
118 
119  return 0;
120 }
121 
122 
123 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  val.f = value;
131 
132  /* search all data segment entries for a matching entry */
133 
134  for (de = cd->dseg; de != NULL; de = de->next) {
135  if (IS_FLT_TYPE(de->type))
136  if (de->flags & DSEG_FLAG_READONLY)
137  if (de->val.i == val.i)
138  return de->disp;
139  }
140 
141  /* no matching entry was found */
142 
143  return 0;
144 }
145 
146 
147 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  val.d = value;
155 
156  /* search all data segment entries for a matching entry */
157 
158  for (de = cd->dseg; de != NULL; de = de->next) {
159  if (IS_DBL_TYPE(de->type))
160  if (de->flags & DSEG_FLAG_READONLY)
161  if (de->val.l == val.l)
162  return de->disp;
163  }
164 
165  /* no matching entry was found */
166 
167  return 0;
168 }
169 
170 
171 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  for (de = cd->dseg; de != NULL; de = de->next) {
178  if (IS_ADR_TYPE(de->type))
179  if (de->flags & DSEG_FLAG_READONLY)
180  if (de->val.a == value)
181  return de->disp;
182  }
183 
184  /* no matching entry was found */
185 
186  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 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  cd->dseglen += 4;
204 
205  /* allocate new entry */
206 
207  de = DNEW(dsegentry);
208 
209  de->type = TYPE_INT;
210  de->flags = flags;
211  de->disp = -(cd->dseglen);
212  de->val.i = value;
213  de->next = cd->dseg;
214 
215  /* insert into the chain */
216 
217  cd->dseg = de;
218 
219  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 
230 {
231  s4 disp;
232 
233  disp = dseg_add_s4_intern(cd, value, DSEG_FLAG_UNIQUE);
234 
235  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 
247 {
248  s4 disp;
249 
250  /* search the data segment if the value is already stored */
251 
252  disp = dseg_find_s4(cd, value);
253 
254  if (disp != 0)
255  return disp;
256 
257  disp = dseg_add_s4_intern(cd, value, DSEG_FLAG_READONLY);
258 
259  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 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  cd->dseglen = MEMORY_ALIGN(cd->dseglen + 8, 8);
277 
278  /* allocate new entry */
279 
280  de = DNEW(dsegentry);
281 
282  de->type = TYPE_LNG;
283  de->flags = flags;
284  de->disp = -(cd->dseglen);
285  de->val.l = value;
286  de->next = cd->dseg;
287 
288  /* insert into the chain */
289 
290  cd->dseg = de;
291 
292  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 
303 {
304  s4 disp;
305 
306  disp = dseg_add_s8_intern(cd, value, DSEG_FLAG_UNIQUE);
307 
308  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 
320 {
321  s4 disp;
322 
323  /* search the data segment if the value is already stored */
324 
325  disp = dseg_find_s8(cd, value);
326 
327  if (disp != 0)
328  return disp;
329 
330  disp = dseg_add_s8_intern(cd, value, DSEG_FLAG_READONLY);
331 
332  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 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  cd->dseglen += 4;
350 
351  /* allocate new entry */
352 
353  de = DNEW(dsegentry);
354 
355  de->type = TYPE_FLT;
356  de->flags = flags;
357  de->disp = -(cd->dseglen);
358  de->val.f = value;
359  de->next = cd->dseg;
360 
361  /* insert into the chain */
362 
363  cd->dseg = de;
364 
365  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 
376 {
377  s4 disp;
378 
379  disp = dseg_add_float_intern(cd, value, DSEG_FLAG_UNIQUE);
380 
381  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 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  disp = dseg_find_float(cd, value);
399 
400  if (disp != 0)
401  return disp;
402 
403  disp = dseg_add_float_intern(cd, value, DSEG_FLAG_READONLY);
404 
405  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 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  cd->dseglen = MEMORY_ALIGN(cd->dseglen + 8, 8);
423 
424  /* allocate new entry */
425 
426  de = DNEW(dsegentry);
427 
428  de->type = TYPE_DBL;
429  de->flags = flags;
430  de->disp = -(cd->dseglen);
431  de->val.d = value;
432  de->next = cd->dseg;
433 
434  /* insert into the chain */
435 
436  cd->dseg = de;
437 
438  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 
449 {
450  s4 disp;
451 
452  disp = dseg_add_double_intern(cd, value, DSEG_FLAG_UNIQUE);
453 
454  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 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  disp = dseg_find_double(cd, value);
472 
473  if (disp != 0)
474  return disp;
475 
476  disp = dseg_add_double_intern(cd, value, DSEG_FLAG_READONLY);
477 
478  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 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  cd->dseglen = MEMORY_ALIGN(cd->dseglen + 8, 8);
497 #else
498  cd->dseglen += 4;
499 #endif
500 
501  /* allocate new entry */
502 
503  de = DNEW(dsegentry);
504 
505  de->type = TYPE_ADR;
506  de->flags = flags;
507  de->disp = -(cd->dseglen);
508  de->val.a = value;
509  de->next = cd->dseg;
510 
511  /* insert into the chain */
512 
513  cd->dseg = de;
514 
515  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 
526 {
527  s4 disp;
528 
529  disp = dseg_add_address_intern(cd, value, DSEG_FLAG_UNIQUE);
530 
531  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 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  disp = dseg_find_address(cd, value);
549 
550  if (disp != 0)
551  return disp;
552 
553  disp = dseg_add_address_intern(cd, value, DSEG_FLAG_READONLY);
554 
555  return disp;
556 }
557 
558 
559 /* dseg_add_target *************************************************************
560 
561  XXX
562 
563 *******************************************************************************/
564 
566 {
567  jumpref *jr;
568 
569  jr = DNEW(jumpref);
570 
571  jr->tablepos = dseg_add_unique_address(cd, NULL);
572  jr->target = target;
573  jr->next = cd->jumpreferences;
574 
575  cd->jumpreferences = jr;
576 }
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 void dseg_adddata(codegendata *cd)
587 {
588  dataref *dr;
589 
590  dr = DNEW(dataref);
591 
592  dr->datapos = cd->mcodeptr - cd->mcodebase;
593  dr->next = cd->datareferences;
594 
595  cd->datareferences = dr;
596 }
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 void dseg_resolve_datareferences(jitdata *jd)
608 {
609  codeinfo *code;
610  codegendata *cd;
611  dataref *dr;
612 
613  /* get required compiler data */
614 
615  code = jd->code;
616  cd = jd->cd;
617 
618  /* data segment references resolving */
619 
620  for (dr = cd->datareferences; dr != NULL; dr = dr->next)
621  *((u1 **) (code->entrypoint + dr->datapos - SIZEOF_VOID_P)) = code->entrypoint;
622 }
623 #endif
624 
625 
626 /* dseg_display ****************************************************************
627 
628  Displays the content of the methods' data segment.
629 
630 *******************************************************************************/
631 
632 #if !defined(NDEBUG)
634 {
635  codeinfo *code;
636  codegendata *cd;
637  dsegentry *de;
638  imm_union val;
639 
640  /* get required compiler data */
641 
642  code = jd->code;
643  cd = jd->cd;
644 
645  if (opt_debugcolor)
646  printf("\033[34m"); /* blue */
647 
648  printf(" --- dump of datasegment\n");
649 
650  /* process all data segment entries */
651 
652  for (de = cd->dseg; de != NULL; de = de->next) {
653  printf("0x%0" PRINTF_INTPTR_NUM_HEXDIGITS PRIxPTR ":", (ptrint) (code->entrypoint + de->disp));
654 
655  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  switch (de->type) {
662  case TYPE_INT:
663  val.i = *((s4 *) (code->entrypoint + de->disp));
664  printf("(INT) %d (0x%08x)", val.i, val.i);
665  break;
666 
667  case TYPE_LNG:
668  val.l = *((s8 *) (code->entrypoint + de->disp));
669  printf("(LNG) %" PRId64 " (0x%0" PRINTF_INTPTR_NUM_HEXDIGITS PRIx64 ")",
670  val.l, val.l);
671  break;
672 
673  case TYPE_FLT:
674  val.f = *((float *) (code->entrypoint + de->disp));
675  printf("(FLT) %g (0x%08x)", val.f, val.i);
676  break;
677 
678  case TYPE_DBL:
679  val.d = *((double *) (code->entrypoint + de->disp));
680  printf("(DBL) %g (0x%016" PRIx64 ")", val.d, val.l);
681  break;
682 
683  case TYPE_ADR:
684  val.a = *((void **) (code->entrypoint + de->disp));
685  printf("(ADR) %0" PRINTF_INTPTR_NUM_HEXDIGITS PRIxPTR, (ptrint) val.a);
686  break;
687  }
688 
689  printf("\n");
690  }
691 
692  printf(" --- begin of data segment: ");
693  printf("0x%0" PRINTF_INTPTR_NUM_HEXDIGITS PRIxPTR "\n", (ptrint) code->entrypoint);
694 
695  if (opt_debugcolor)
696  printf("\033[m");
697 }
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  */
s4 dseg_add_double(codegendata *cd, double value)
Definition: dseg.cpp:465
static s4 dseg_find_s4(codegendata *cd, s4 value)
Definition: dseg.cpp:85
basicblock * target
u2 flags
Definition: dseg.hpp:50
static s4 dseg_find_s8(codegendata *cd, s8 value)
Definition: dseg.cpp:104
float f
Definition: global.hpp:56
Definition: jit.hpp:126
double d
Definition: global.hpp:57
s4 dseg_add_unique_address(codegendata *cd, void *value)
Definition: dseg.cpp:525
dataref * next
s4 disp
Definition: dseg.hpp:51
void * a
Definition: global.hpp:58
jumpref * next
s4 dseg_add_address(codegendata *cd, void *value)
Definition: dseg.cpp:542
codeinfo * code
Definition: jit.hpp:128
s4 dseg_add_unique_double(codegendata *cd, double value)
Definition: dseg.cpp:448
s4 dseg_add_unique_float(codegendata *cd, float value)
Definition: dseg.cpp:375
u2 type
Definition: dseg.hpp:49
codegendata * cd
Definition: jit.hpp:129
uint8_t u1
Definition: types.hpp:40
void dseg_add_target(codegendata *cd, basicblock *target)
Definition: dseg.cpp:565
int64_t s8
Definition: types.hpp:48
static s4 dseg_add_double_intern(codegendata *cd, double value, u4 flags)
Definition: dseg.cpp:415
#define IS_FLT_TYPE(a)
Definition: global.hpp:136
void dseg_display(jitdata *jd)
Definition: dseg.cpp:633
#define DNEW(type)
Definition: dumpmemory.hpp:370
s4 dseg_add_s4(codegendata *cd, s4 value)
Definition: dseg.cpp:246
bool opt_debugcolor
Definition: options.cpp:68
static s4 dseg_add_s4_intern(codegendata *cd, s4 value, u4 flags)
Definition: dseg.cpp:196
#define DSEG_FLAG_READONLY
Definition: dseg.hpp:46
jumpref * jumpreferences
dsegentry * next
Definition: dseg.hpp:53
static s4 dseg_find_float(codegendata *cd, float value)
Definition: dseg.cpp:123
void dseg_finish(jitdata *jd)
Definition: dseg.cpp:46
int32_t s4
Definition: types.hpp:45
s4 dseg_add_unique_s4(codegendata *cd, s4 value)
Definition: dseg.cpp:229
static s4 dseg_add_address_intern(codegendata *cd, void *value, u4 flags)
Definition: dseg.cpp:488
#define IS_INT_TYPE(a)
Definition: global.hpp:134
static s4 dseg_find_double(codegendata *cd, double value)
Definition: dseg.cpp:147
#define IS_ADR_TYPE(a)
Definition: global.hpp:138
#define IS_LNG_TYPE(a)
Definition: global.hpp:135
uint32_t u4
Definition: types.hpp:46
static s4 dseg_find_address(codegendata *cd, void *value)
Definition: dseg.cpp:171
static s4 dseg_add_s8_intern(codegendata *cd, s8 value, u4 flags)
Definition: dseg.cpp:269
#define DSEG_FLAG_UNIQUE
Definition: dseg.hpp:45
#define MEMORY_ALIGN(pos, size)
Definition: memory.hpp:37
imm_union val
Definition: dseg.hpp:52
s4 dseg_add_s8(codegendata *cd, s8 value)
Definition: dseg.cpp:319
BeginInst * target
uintptr_t ptrint
Definition: types.hpp:54
dsegentry * dseg
#define PRINTF_INTPTR_NUM_HEXDIGITS
Definition: global.hpp:80
s4 dseg_add_float(codegendata *cd, float value)
Definition: dseg.cpp:392
#define printf(...)
Definition: ssa2.cpp:40
static s4 dseg_add_float_intern(codegendata *cd, float value, u4 flags)
Definition: dseg.cpp:342
u1 * entrypoint
Definition: code.hpp:84
s4 dseg_add_unique_s8(codegendata *cd, s8 value)
Definition: dseg.cpp:302
#define IS_DBL_TYPE(a)
Definition: global.hpp:137