OSDN Git Service

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