OSDN Git Service

2007-08-20 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / gcc / java / boehm.c
1 /* Functions related to the Boehm garbage collector.
2    Copyright (C) 2000, 2003, 2004, 2006 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
10
11 GCC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3.  If not see
18 <http://www.gnu.org/licenses/>.
19
20 Java and all Java-based marks are trademarks or registered trademarks
21 of Sun Microsystems, Inc. in the United States and other countries.
22 The Free Software Foundation is independent of Sun Microsystems, Inc.  */
23
24 /* Written by Tom Tromey <tromey@cygnus.com>.  */
25
26 #include <config.h>
27
28 #include "system.h"
29 #include "coretypes.h"
30 #include "tm.h"
31 #include "tree.h"
32 #include "java-tree.h"
33 #include "parse.h"
34 #include "toplev.h"
35
36 static void mark_reference_fields (tree, unsigned HOST_WIDE_INT *,
37                                    unsigned HOST_WIDE_INT *, unsigned int,
38                                    int *, int *, int *, HOST_WIDE_INT *);
39 static void set_bit (unsigned HOST_WIDE_INT *, unsigned HOST_WIDE_INT *,
40                      unsigned int);
41
42 /* A procedure-based object descriptor.  We know that our
43    `kind' is 0, and `env' is likewise 0, so we have a simple
44    computation.  From the GC sources:
45    (((((env) << LOG_MAX_MARK_PROCS) | (proc_index)) << DS_TAG_BITS)     \
46    | DS_PROC)
47    Here DS_PROC == 2.  */
48 #define PROCEDURE_OBJECT_DESCRIPTOR 2
49
50 /* Treat two HOST_WIDE_INT's as a contiguous bitmap, with bit 0 being
51    the least significant.  This function sets bit N in the bitmap.  */
52 static void
53 set_bit (unsigned HOST_WIDE_INT *low, unsigned HOST_WIDE_INT *high,
54          unsigned int n)
55 {
56   unsigned HOST_WIDE_INT *which;
57
58   if (n >= HOST_BITS_PER_WIDE_INT)
59     {
60       n -= HOST_BITS_PER_WIDE_INT;
61       which = high;
62     }
63   else
64     which = low;
65
66   *which |= (unsigned HOST_WIDE_INT) 1 << n;
67 }
68
69 /* Recursively mark reference fields.  */
70 static void
71 mark_reference_fields (tree field,
72                        unsigned HOST_WIDE_INT *low,
73                        unsigned HOST_WIDE_INT *high,
74                        unsigned int ubit,
75                        int *pointer_after_end,
76                        int *all_bits_set,
77                        int *last_set_index,
78                        HOST_WIDE_INT *last_view_index)
79 {
80   /* See if we have fields from our superclass.  */
81   if (DECL_NAME (field) == NULL_TREE)
82     {
83       mark_reference_fields (TYPE_FIELDS (TREE_TYPE (field)),
84                              low, high, ubit,
85                              pointer_after_end, all_bits_set,
86                              last_set_index, last_view_index);
87       field = TREE_CHAIN (field);
88     }
89
90   for (; field != NULL_TREE; field = TREE_CHAIN (field))
91     {
92       HOST_WIDE_INT offset;
93       HOST_WIDE_INT size_bytes;
94
95       if (FIELD_STATIC (field))
96         continue;
97
98       offset = int_byte_position (field);
99       size_bytes = int_size_in_bytes (TREE_TYPE (field));
100       if (JREFERENCE_TYPE_P (TREE_TYPE (field))
101           /* An `object' of type gnu.gcj.RawData is actually non-Java
102              data.  */
103           && TREE_TYPE (field) != rawdata_ptr_type_node)
104         {
105           unsigned int count;
106           unsigned int size_words;
107           unsigned int i;
108
109           /* If this reference slot appears to overlay a slot we think
110              we already covered, then we are doomed.  */
111           gcc_assert (offset > *last_view_index);
112
113           count = offset * BITS_PER_UNIT / POINTER_SIZE;
114           size_words = size_bytes * BITS_PER_UNIT / POINTER_SIZE;
115
116           *last_set_index = count;
117              
118           /* First word in object corresponds to most significant byte of 
119              bitmap. 
120              
121              In the case of a multiple-word record, we set pointer 
122              bits for all words in the record. This is conservative, but the 
123              size_words != 1 case is impossible in regular java code. */
124           for (i = 0; i < size_words; ++i)
125             set_bit (low, high, ubit - count - i - 1);
126
127           if (count >= ubit - 2)
128             *pointer_after_end = 1;
129
130           /* If we saw a non-reference field earlier, then we can't
131              use the count representation.  We keep track of that in
132              *ALL_BITS_SET.  */
133           if (! *all_bits_set)
134             *all_bits_set = -1;
135         }
136       else if (*all_bits_set > 0)
137         *all_bits_set = 0;
138
139       *last_view_index = offset;
140     }
141 }
142
143 /* Return the marking bitmap for the class TYPE.  For now this is a
144    single word describing the type.  */
145 tree
146 get_boehm_type_descriptor (tree type)
147 {
148   unsigned int count, log2_size, ubit;
149   int bit;
150   int all_bits_set = 1;
151   int last_set_index = 0;
152   HOST_WIDE_INT last_view_index = -1;
153   int pointer_after_end = 0;
154   unsigned HOST_WIDE_INT low = 0, high = 0;
155   tree field, value, value_type;
156
157   /* If the GC wasn't requested, just use a null pointer.  */
158   if (! flag_use_boehm_gc)
159     return null_pointer_node;
160
161   value_type = java_type_for_mode (ptr_mode, 1);
162   /* If we have a type of unknown size, use a proc.  */
163   if (int_size_in_bytes (type) == -1)
164     goto procedure_object_descriptor;
165
166   bit = POINTER_SIZE / BITS_PER_UNIT;
167   /* The size of this node has to be known.  And, we only support 32
168      and 64 bit targets, so we need to know that the log2 is one of
169      our values.  */
170   log2_size = exact_log2 (bit);
171   if (bit == -1 || (log2_size != 2 && log2_size != 3))
172     {
173       /* This means the GC isn't supported.  We should probably
174          abort or give an error.  Instead, for now, we just silently
175          revert.  FIXME.  */
176       return null_pointer_node;
177     }
178   bit *= BITS_PER_UNIT;
179
180   /* Warning avoidance.  */
181   ubit = (unsigned int) bit;
182
183   if (type == class_type_node)
184     goto procedure_object_descriptor;
185
186   field = TYPE_FIELDS (type);
187   mark_reference_fields (field, &low, &high, ubit,
188                          &pointer_after_end, &all_bits_set,
189                          &last_set_index, &last_view_index);
190
191   /* If the object is all pointers, or if the part with pointers fits
192      in our bitmap, then we are ok.  Otherwise we have to allocate it
193      a different way.  */
194   if (all_bits_set != -1 || (pointer_after_end && flag_reduced_reflection))
195     {
196       /* In this case the initial part of the object is all reference
197          fields, and the end of the object is all non-reference
198          fields.  We represent the mark as a count of the fields,
199          shifted.  In the GC the computation looks something like
200          this:
201          value = DS_LENGTH | WORDS_TO_BYTES (last_set_index + 1);
202          DS_LENGTH is 0.
203          WORDS_TO_BYTES shifts by log2(bytes-per-pointer).
204
205          In the case of flag_reduced_reflection and the bitmap would
206          overflow, we tell the gc that the object is all pointers so
207          that we don't have to emit reflection data for run time
208          marking. */
209       count = 0;
210       low = 0;
211       high = 0;
212       ++last_set_index;
213       while (last_set_index)
214         {
215           if ((last_set_index & 1))
216             set_bit (&low, &high, log2_size + count);
217           last_set_index >>= 1;
218           ++count;
219         }
220       value = build_int_cst_wide (value_type, low, high);
221     }
222   else if (! pointer_after_end)
223     {
224       /* Bottom two bits for bitmap mark type are 01.  */
225       set_bit (&low, &high, 0);
226       value = build_int_cst_wide (value_type, low, high);
227     }
228   else
229     {
230     procedure_object_descriptor:
231       value = build_int_cst (value_type, PROCEDURE_OBJECT_DESCRIPTOR);
232     }
233
234   return value;
235 }
236
237 /* The fourth (index of 3) element in the vtable is the GC descriptor.
238    A value of 2 indicates that the class uses _Jv_MarkObj. */
239 bool
240 uses_jv_markobj_p (tree dtable)
241 {
242   tree v;
243   /* FIXME: what do we return if !flag_use_boehm_gc ? */
244   gcc_assert (flag_use_boehm_gc);
245   /* FIXME: this is wrong if TARGET_VTABLE_USES_DESCRIPTORS.  However,
246      this function is only used with flag_reduced_reflection.  No
247      point in asserting unless we hit the bad case.  */
248   gcc_assert (!flag_reduced_reflection || TARGET_VTABLE_USES_DESCRIPTORS == 0);
249   v = VEC_index (constructor_elt, CONSTRUCTOR_ELTS (dtable), 3)->value;
250   return (PROCEDURE_OBJECT_DESCRIPTOR == TREE_INT_CST_LOW (v));
251 }