xref: /openbsd/gnu/usr.bin/gcc/gcc/java/boehm.c (revision c87b03e5)
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
set_bit(low,high,n)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
mark_reference_fields(field,low,high,ubit,pointer_after_end,all_bits_set,last_set_index,last_view_index)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
get_boehm_type_descriptor(tree type)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) = java_type_for_mode (ptr_mode, 1);
234   return value;
235 }
236