OSDN Git Service

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