* boehm.c (PROCEDURE_OBJECT_DESCRIPTOR): Merge into ..
[official-gcc.git] / gcc / java / boehm.c
blob3eb20434d26f43f1bc231f65ac7e122c12dca16d
1 /* Functions related to the Boehm garbage collector.
2 Copyright (C) 2000 Free Software Foundation, Inc.
4 This file is part of GNU CC.
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.
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.
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.
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. */
25 /* Written by Tom Tromey <tromey@cygnus.com>. */
27 #include <config.h>
29 #include "system.h"
30 #include "tree.h"
31 #include "java-tree.h"
32 #include "parse.h"
33 #include "toplev.h"
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));
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;
53 HOST_WIDE_INT *which;
55 if (n >= HOST_BITS_PER_WIDE_INT)
57 n -= HOST_BITS_PER_WIDE_INT;
58 which = high;
60 else
61 which = low;
63 *which |= (HOST_WIDE_INT) 1 << n;
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;
78 /* See if we have fields from our superclass. */
79 if (DECL_NAME (field) == NULL_TREE)
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);
88 for (; field != NULL_TREE; field = TREE_CHAIN (field))
90 HOST_WIDE_INT offset;
91 HOST_WIDE_INT size_bytes;
93 if (FIELD_STATIC (field))
94 continue;
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)
103 unsigned int count;
104 unsigned int size_words;
105 unsigned int i;
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 ();
112 count = offset * BITS_PER_UNIT / POINTER_SIZE;
113 size_words = size_bytes * BITS_PER_UNIT / POINTER_SIZE;
115 *last_set_index = count;
117 /* First word in object corresponds to most significant byte of
118 bitmap.
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);
126 if (count >= ubit - 2)
127 *pointer_after_end = 1;
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;
135 else if (*all_bits_set > 0)
136 *all_bits_set = 0;
138 *last_view_index = offset;
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)
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;
156 /* If the GC wasn't requested, just use a null pointer. */
157 if (! flag_use_boehm_gc)
158 return null_pointer_node;
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;
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))
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;
176 bit *= BITS_PER_UNIT;
178 /* Warning avoidance. */
179 ubit = (unsigned int) bit;
181 if (type == class_type_node)
182 goto procedure_object_descriptor;
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);
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)
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)
208 if ((last_set_index & 1))
209 set_bit (&low, &high, log2_size + count);
210 last_set_index >>= 1;
211 ++count;
213 value = build_int_2 (low, high);
215 else if (! pointer_after_end)
217 /* Bottom two bits for bitmap mark type are 01. */
218 set_bit (&low, &high, 0);
219 value = build_int_2 (low, high);
221 else
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);
233 TREE_TYPE (value) = type_for_mode (ptr_mode, 1);
234 return value;