OSDN Git Service

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