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