OSDN Git Service

contrib/
[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
101       if (JREFERENCE_TYPE_P (TREE_TYPE (field))
102           /* An `object' of type gnu.gcj.RawData is actually non-Java
103              data.  */
104           && TREE_TYPE (field) != rawdata_ptr_type_node)
105         {
106           unsigned int count;
107           unsigned int size_words;
108           unsigned int i;
109
110           /* If this reference slot appears to overlay a slot we think
111              we already covered, then we are doomed.  */
112           gcc_assert (offset > *last_view_index);
113
114           if (offset % (POINTER_SIZE / BITS_PER_UNIT))
115             {
116               *all_bits_set = -1;
117               *pointer_after_end = 1;
118               break;
119             }
120
121           count = offset * BITS_PER_UNIT / POINTER_SIZE;
122           size_words = size_bytes * BITS_PER_UNIT / POINTER_SIZE;
123
124           *last_set_index = count;
125              
126           /* First word in object corresponds to most significant byte of 
127              bitmap. 
128              
129              In the case of a multiple-word record, we set pointer 
130              bits for all words in the record. This is conservative, but the 
131              size_words != 1 case is impossible in regular java code. */
132           for (i = 0; i < size_words; ++i)
133             set_bit (low, high, ubit - count - i - 1);
134
135           if (count >= ubit - 2)
136             *pointer_after_end = 1;
137
138           /* If we saw a non-reference field earlier, then we can't
139              use the count representation.  We keep track of that in
140              *ALL_BITS_SET.  */
141           if (! *all_bits_set)
142             *all_bits_set = -1;
143         }
144       else if (*all_bits_set > 0)
145         *all_bits_set = 0;
146
147       *last_view_index = offset;
148     }
149 }
150
151 /* Return the marking bitmap for the class TYPE.  For now this is a
152    single word describing the type.  */
153 tree
154 get_boehm_type_descriptor (tree type)
155 {
156   unsigned int count, log2_size, ubit;
157   int bit;
158   int all_bits_set = 1;
159   int last_set_index = 0;
160   HOST_WIDE_INT last_view_index = -1;
161   int pointer_after_end = 0;
162   unsigned HOST_WIDE_INT low = 0, high = 0;
163   tree field, value, value_type;
164
165   /* If the GC wasn't requested, just use a null pointer.  */
166   if (! flag_use_boehm_gc)
167     return null_pointer_node;
168
169   value_type = java_type_for_mode (ptr_mode, 1);
170   /* If we have a type of unknown size, use a proc.  */
171   if (int_size_in_bytes (type) == -1)
172     goto procedure_object_descriptor;
173
174   bit = POINTER_SIZE / BITS_PER_UNIT;
175   /* The size of this node has to be known.  And, we only support 32
176      and 64 bit targets, so we need to know that the log2 is one of
177      our values.  */
178   log2_size = exact_log2 (bit);
179   if (bit == -1 || (log2_size != 2 && log2_size != 3))
180     {
181       /* This means the GC isn't supported.  We should probably
182          abort or give an error.  Instead, for now, we just silently
183          revert.  FIXME.  */
184       return null_pointer_node;
185     }
186   bit *= BITS_PER_UNIT;
187
188   /* Warning avoidance.  */
189   ubit = (unsigned int) bit;
190
191   if (type == class_type_node)
192     goto procedure_object_descriptor;
193
194   field = TYPE_FIELDS (type);
195   mark_reference_fields (field, &low, &high, ubit,
196                          &pointer_after_end, &all_bits_set,
197                          &last_set_index, &last_view_index);
198
199   /* If the object is all pointers, or if the part with pointers fits
200      in our bitmap, then we are ok.  Otherwise we have to allocate it
201      a different way.  */
202   if (all_bits_set != -1 || (pointer_after_end && flag_reduced_reflection))
203     {
204       /* In this case the initial part of the object is all reference
205          fields, and the end of the object is all non-reference
206          fields.  We represent the mark as a count of the fields,
207          shifted.  In the GC the computation looks something like
208          this:
209          value = DS_LENGTH | WORDS_TO_BYTES (last_set_index + 1);
210          DS_LENGTH is 0.
211          WORDS_TO_BYTES shifts by log2(bytes-per-pointer).
212
213          In the case of flag_reduced_reflection and the bitmap would
214          overflow, we tell the gc that the object is all pointers so
215          that we don't have to emit reflection data for run time
216          marking. */
217       count = 0;
218       low = 0;
219       high = 0;
220       ++last_set_index;
221       while (last_set_index)
222         {
223           if ((last_set_index & 1))
224             set_bit (&low, &high, log2_size + count);
225           last_set_index >>= 1;
226           ++count;
227         }
228       value = build_int_cst_wide (value_type, low, high);
229     }
230   else if (! pointer_after_end)
231     {
232       /* Bottom two bits for bitmap mark type are 01.  */
233       set_bit (&low, &high, 0);
234       value = build_int_cst_wide (value_type, low, high);
235     }
236   else
237     {
238     procedure_object_descriptor:
239       value = build_int_cst (value_type, PROCEDURE_OBJECT_DESCRIPTOR);
240     }
241
242   return value;
243 }
244
245 /* The fourth (index of 3) element in the vtable is the GC descriptor.
246    A value of 2 indicates that the class uses _Jv_MarkObj. */
247 bool
248 uses_jv_markobj_p (tree dtable)
249 {
250   tree v;
251   /* FIXME: what do we return if !flag_use_boehm_gc ? */
252   gcc_assert (flag_use_boehm_gc);
253   /* FIXME: this is wrong if TARGET_VTABLE_USES_DESCRIPTORS.  However,
254      this function is only used with flag_reduced_reflection.  No
255      point in asserting unless we hit the bad case.  */
256   gcc_assert (!flag_reduced_reflection || TARGET_VTABLE_USES_DESCRIPTORS == 0);
257   v = VEC_index (constructor_elt, CONSTRUCTOR_ELTS (dtable), 3)->value;
258   return (PROCEDURE_OBJECT_DESCRIPTOR == TREE_INT_CST_LOW (v));
259 }