OSDN Git Service

2007-04-16 H.J. Lu <hongjiu.lu@intel.com>
[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 2, 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 COPYING.  If not, write to
18 the Free Software Foundation, 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20
21 Java and all Java-based marks are trademarks or registered trademarks
22 of Sun Microsystems, Inc. in the United States and other countries.
23 The Free Software Foundation is independent of Sun Microsystems, Inc.  */
24
25 /* Written by Tom Tromey <tromey@cygnus.com>.  */
26
27 #include <config.h>
28
29 #include "system.h"
30 #include "coretypes.h"
31 #include "tm.h"
32 #include "tree.h"
33 #include "java-tree.h"
34 #include "parse.h"
35 #include "toplev.h"
36
37 static void mark_reference_fields (tree, unsigned HOST_WIDE_INT *,
38                                    unsigned HOST_WIDE_INT *, unsigned int,
39                                    int *, int *, int *, HOST_WIDE_INT *);
40 static void set_bit (unsigned HOST_WIDE_INT *, unsigned HOST_WIDE_INT *,
41                      unsigned int);
42
43 /* A procedure-based object descriptor.  We know that our
44    `kind' is 0, and `env' is likewise 0, so we have a simple
45    computation.  From the GC sources:
46    (((((env) << LOG_MAX_MARK_PROCS) | (proc_index)) << DS_TAG_BITS)     \
47    | DS_PROC)
48    Here DS_PROC == 2.  */
49 #define PROCEDURE_OBJECT_DESCRIPTOR 2
50
51 /* Treat two HOST_WIDE_INT's as a contiguous bitmap, with bit 0 being
52    the least significant.  This function sets bit N in the bitmap.  */
53 static void
54 set_bit (unsigned HOST_WIDE_INT *low, unsigned HOST_WIDE_INT *high,
55          unsigned int n)
56 {
57   unsigned HOST_WIDE_INT *which;
58
59   if (n >= HOST_BITS_PER_WIDE_INT)
60     {
61       n -= HOST_BITS_PER_WIDE_INT;
62       which = high;
63     }
64   else
65     which = low;
66
67   *which |= (unsigned HOST_WIDE_INT) 1 << n;
68 }
69
70 /* Recursively mark reference fields.  */
71 static void
72 mark_reference_fields (tree field,
73                        unsigned HOST_WIDE_INT *low,
74                        unsigned HOST_WIDE_INT *high,
75                        unsigned int ubit,
76                        int *pointer_after_end,
77                        int *all_bits_set,
78                        int *last_set_index,
79                        HOST_WIDE_INT *last_view_index)
80 {
81   /* See if we have fields from our superclass.  */
82   if (DECL_NAME (field) == NULL_TREE)
83     {
84       mark_reference_fields (TYPE_FIELDS (TREE_TYPE (field)),
85                              low, high, ubit,
86                              pointer_after_end, all_bits_set,
87                              last_set_index, last_view_index);
88       field = TREE_CHAIN (field);
89     }
90
91   for (; field != NULL_TREE; field = TREE_CHAIN (field))
92     {
93       HOST_WIDE_INT offset;
94       HOST_WIDE_INT size_bytes;
95
96       if (FIELD_STATIC (field))
97         continue;
98
99       offset = int_byte_position (field);
100       size_bytes = int_size_in_bytes (TREE_TYPE (field));
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           count = offset * BITS_PER_UNIT / POINTER_SIZE;
115           size_words = size_bytes * BITS_PER_UNIT / POINTER_SIZE;
116
117           *last_set_index = count;
118              
119           /* First word in object corresponds to most significant byte of 
120              bitmap. 
121              
122              In the case of a multiple-word record, we set pointer 
123              bits for all words in the record. This is conservative, but the 
124              size_words != 1 case is impossible in regular java code. */
125           for (i = 0; i < size_words; ++i)
126             set_bit (low, high, ubit - count - i - 1);
127
128           if (count >= ubit - 2)
129             *pointer_after_end = 1;
130
131           /* If we saw a non-reference field earlier, then we can't
132              use the count representation.  We keep track of that in
133              *ALL_BITS_SET.  */
134           if (! *all_bits_set)
135             *all_bits_set = -1;
136         }
137       else if (*all_bits_set > 0)
138         *all_bits_set = 0;
139
140       *last_view_index = offset;
141     }
142 }
143
144 /* Return the marking bitmap for the class TYPE.  For now this is a
145    single word describing the type.  */
146 tree
147 get_boehm_type_descriptor (tree type)
148 {
149   unsigned int count, log2_size, ubit;
150   int bit;
151   int all_bits_set = 1;
152   int last_set_index = 0;
153   HOST_WIDE_INT last_view_index = -1;
154   int pointer_after_end = 0;
155   unsigned HOST_WIDE_INT low = 0, high = 0;
156   tree field, value, value_type;
157
158   /* If the GC wasn't requested, just use a null pointer.  */
159   if (! flag_use_boehm_gc)
160     return null_pointer_node;
161
162   value_type = java_type_for_mode (ptr_mode, 1);
163   /* If we have a type of unknown size, use a proc.  */
164   if (int_size_in_bytes (type) == -1)
165     goto procedure_object_descriptor;
166
167   bit = POINTER_SIZE / BITS_PER_UNIT;
168   /* The size of this node has to be known.  And, we only support 32
169      and 64 bit targets, so we need to know that the log2 is one of
170      our values.  */
171   log2_size = exact_log2 (bit);
172   if (bit == -1 || (log2_size != 2 && log2_size != 3))
173     {
174       /* This means the GC isn't supported.  We should probably
175          abort or give an error.  Instead, for now, we just silently
176          revert.  FIXME.  */
177       return null_pointer_node;
178     }
179   bit *= BITS_PER_UNIT;
180
181   /* Warning avoidance.  */
182   ubit = (unsigned int) bit;
183
184   if (type == class_type_node)
185     goto procedure_object_descriptor;
186
187   field = TYPE_FIELDS (type);
188   mark_reference_fields (field, &low, &high, ubit,
189                          &pointer_after_end, &all_bits_set,
190                          &last_set_index, &last_view_index);
191
192   /* If the object is all pointers, or if the part with pointers fits
193      in our bitmap, then we are ok.  Otherwise we have to allocate it
194      a different way.  */
195   if (all_bits_set != -1 || (pointer_after_end && flag_reduced_reflection))
196     {
197       /* In this case the initial part of the object is all reference
198          fields, and the end of the object is all non-reference
199          fields.  We represent the mark as a count of the fields,
200          shifted.  In the GC the computation looks something like
201          this:
202          value = DS_LENGTH | WORDS_TO_BYTES (last_set_index + 1);
203          DS_LENGTH is 0.
204          WORDS_TO_BYTES shifts by log2(bytes-per-pointer).
205
206          In the case of flag_reduced_reflection and the bitmap would
207          overflow, we tell the gc that the object is all pointers so
208          that we don't have to emit reflection data for run time
209          marking. */
210       count = 0;
211       low = 0;
212       high = 0;
213       ++last_set_index;
214       while (last_set_index)
215         {
216           if ((last_set_index & 1))
217             set_bit (&low, &high, log2_size + count);
218           last_set_index >>= 1;
219           ++count;
220         }
221       value = build_int_cst_wide (value_type, low, high);
222     }
223   else if (! pointer_after_end)
224     {
225       /* Bottom two bits for bitmap mark type are 01.  */
226       set_bit (&low, &high, 0);
227       value = build_int_cst_wide (value_type, low, high);
228     }
229   else
230     {
231     procedure_object_descriptor:
232       value = build_int_cst (value_type, PROCEDURE_OBJECT_DESCRIPTOR);
233     }
234
235   return value;
236 }
237
238 /* The fourth (index of 3) element in the vtable is the GC descriptor.
239    A value of 2 indicates that the class uses _Jv_MarkObj. */
240 bool
241 uses_jv_markobj_p (tree dtable)
242 {
243   tree v;
244   /* FIXME: what do we return if !flag_use_boehm_gc ? */
245   gcc_assert (flag_use_boehm_gc);
246   /* FIXME: this is wrong if TARGET_VTABLE_USES_DESCRIPTORS.  However,
247      this function is only used with flag_reduced_reflection.  No
248      point in asserting unless we hit the bad case.  */
249   gcc_assert (!flag_reduced_reflection || TARGET_VTABLE_USES_DESCRIPTORS == 0);
250   v = VEC_index (constructor_elt, CONSTRUCTOR_ELTS (dtable), 3)->value;
251   return (PROCEDURE_OBJECT_DESCRIPTOR == TREE_INT_CST_LOW (v));
252 }