OSDN Git Service

* c-typeck.c (common_type): Correct comment.
[pf3gnuchains/gcc-fork.git] / gcc / java / boehm.c
1 /* Functions related to the Boehm garbage collector.
2    Copyright (C) 2000, 2003 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, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, 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 /* Treat two HOST_WIDE_INT's as a contiguous bitmap, with bit 0 being
44    the least significant.  This function sets bit N in the bitmap.  */
45 static void
46 set_bit (unsigned HOST_WIDE_INT *low, unsigned HOST_WIDE_INT *high,
47          unsigned int n)
48 {
49   HOST_WIDE_INT *which;
50
51   if (n >= HOST_BITS_PER_WIDE_INT)
52     {
53       n -= HOST_BITS_PER_WIDE_INT;
54       which = high;
55     }
56   else
57     which = low;
58
59   *which |= (HOST_WIDE_INT) 1 << n;
60 }
61
62 /* Recursively mark reference fields.  */
63 static void
64 mark_reference_fields (tree field,
65                        unsigned HOST_WIDE_INT *low,
66                        unsigned HOST_WIDE_INT *high,
67                        unsigned int ubit,
68                        int *pointer_after_end,
69                        int *all_bits_set,
70                        int *last_set_index,
71                        HOST_WIDE_INT *last_view_index)
72 {
73   /* See if we have fields from our superclass.  */
74   if (DECL_NAME (field) == NULL_TREE)
75     {
76       mark_reference_fields (TYPE_FIELDS (TREE_TYPE (field)),
77                              low, high, ubit,
78                              pointer_after_end, all_bits_set,
79                              last_set_index, last_view_index);
80       field = TREE_CHAIN (field);
81     }
82
83   for (; field != NULL_TREE; field = TREE_CHAIN (field))
84     {
85       HOST_WIDE_INT offset;
86       HOST_WIDE_INT size_bytes;
87
88       if (FIELD_STATIC (field))
89         continue;
90
91       offset = int_byte_position (field);
92       size_bytes = int_size_in_bytes (TREE_TYPE (field));
93       if (JREFERENCE_TYPE_P (TREE_TYPE (field))
94           /* An `object' of type gnu.gcj.RawData is actually non-Java
95              data.  */
96           && TREE_TYPE (field) != rawdata_ptr_type_node)
97         {
98           unsigned int count;
99           unsigned int size_words;
100           unsigned int i;
101
102           /* If this reference slot appears to overlay a slot we think
103              we already covered, then we are doomed.  */
104           if (offset <= *last_view_index)
105             abort ();
106
107           count = offset * BITS_PER_UNIT / POINTER_SIZE;
108           size_words = size_bytes * BITS_PER_UNIT / POINTER_SIZE;
109
110           *last_set_index = count;
111              
112           /* First word in object corresponds to most significant byte of 
113              bitmap. 
114              
115              In the case of a multiple-word record, we set pointer 
116              bits for all words in the record. This is conservative, but the 
117              size_words != 1 case is impossible in regular java code. */
118           for (i = 0; i < size_words; ++i)
119             set_bit (low, high, ubit - count - i - 1);
120
121           if (count >= ubit - 2)
122             *pointer_after_end = 1;
123
124           /* If we saw a non-reference field earlier, then we can't
125              use the count representation.  We keep track of that in
126              *ALL_BITS_SET.  */
127           if (! *all_bits_set)
128             *all_bits_set = -1;
129         }
130       else if (*all_bits_set > 0)
131         *all_bits_set = 0;
132
133       *last_view_index = offset;
134     }
135 }
136
137 /* Return the marking bitmap for the class TYPE.  For now this is a
138    single word describing the type.  */
139 tree
140 get_boehm_type_descriptor (tree type)
141 {
142   unsigned int count, log2_size, ubit;
143   int bit;
144   int all_bits_set = 1;
145   int last_set_index = 0;
146   HOST_WIDE_INT last_view_index = -1;
147   int pointer_after_end = 0;
148   unsigned HOST_WIDE_INT low = 0, high = 0;
149   tree field, value;
150
151   /* If the GC wasn't requested, just use a null pointer.  */
152   if (! flag_use_boehm_gc)
153     return null_pointer_node;
154
155   /* If we have a type of unknown size, use a proc.  */
156   if (int_size_in_bytes (type) == -1)
157     goto procedure_object_descriptor;
158
159   bit = POINTER_SIZE / BITS_PER_UNIT;
160   /* The size of this node has to be known.  And, we only support 32
161      and 64 bit targets, so we need to know that the log2 is one of
162      our values.  */
163   log2_size = exact_log2 (bit);
164   if (bit == -1 || (log2_size != 2 && log2_size != 3))
165     {
166       /* This means the GC isn't supported.  We should probably
167          abort or give an error.  Instead, for now, we just silently
168          revert.  FIXME.  */
169       return null_pointer_node;
170     }
171   bit *= BITS_PER_UNIT;
172
173   /* Warning avoidance.  */
174   ubit = (unsigned int) bit;
175
176   if (type == class_type_node)
177     goto procedure_object_descriptor;
178
179   field = TYPE_FIELDS (type);
180   mark_reference_fields (field, &low, &high, ubit,
181                          &pointer_after_end, &all_bits_set,
182                          &last_set_index, &last_view_index);
183
184   /* If the object is all pointers, or if the part with pointers fits
185      in our bitmap, then we are ok.  Otherwise we have to allocate it
186      a different way.  */
187   if (all_bits_set != -1)
188     {
189       /* In this case the initial part of the object is all reference
190          fields, and the end of the object is all non-reference
191          fields.  We represent the mark as a count of the fields,
192          shifted.  In the GC the computation looks something like
193          this:
194          value = DS_LENGTH | WORDS_TO_BYTES (last_set_index + 1);
195          DS_LENGTH is 0.
196          WORDS_TO_BYTES shifts by log2(bytes-per-pointer).  */
197       count = 0;
198       low = 0;
199       high = 0;
200       ++last_set_index;
201       while (last_set_index)
202         {
203           if ((last_set_index & 1))
204             set_bit (&low, &high, log2_size + count);
205           last_set_index >>= 1;
206           ++count;
207         }
208       value = build_int_2 (low, high);
209     }
210   else if (! pointer_after_end)
211     {
212       /* Bottom two bits for bitmap mark type are 01.  */
213       set_bit (&low, &high, 0);
214       value = build_int_2 (low, high);
215     }
216   else
217     {
218       /* Compute a procedure-based object descriptor.  We know that our
219          `kind' is 0, and `env' is likewise 0, so we have a simple
220          computation.  From the GC sources:
221             (((((env) << LOG_MAX_MARK_PROCS) | (proc_index)) << DS_TAG_BITS) \
222             | DS_PROC)
223          Here DS_PROC == 2.  */
224     procedure_object_descriptor:
225       value = build_int_2 (2, 0);
226     }
227
228   TREE_TYPE (value) = java_type_for_mode (ptr_mode, 1);
229   return value;
230 }