2008-07-01 Jerry DeLisle <jvdelisle@gcc.gnu.org>
[official-gcc.git] / gcc / java / boehm.c
blob5c65c8bb0cc392c5fe57da8f82692ef7574a9e34
1 /* Functions related to the Boehm garbage collector.
2 Copyright (C) 2000, 2003, 2004, 2006 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC 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 3, or (at your option)
9 any later version.
11 GCC 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 GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>.
20 Java and all Java-based marks are trademarks or registered trademarks
21 of Sun Microsystems, Inc. in the United States and other countries.
22 The Free Software Foundation is independent of Sun Microsystems, Inc. */
24 /* Written by Tom Tromey <tromey@cygnus.com>. */
26 #include <config.h>
28 #include "system.h"
29 #include "coretypes.h"
30 #include "tm.h"
31 #include "tree.h"
32 #include "java-tree.h"
33 #include "parse.h"
34 #include "toplev.h"
36 static void mark_reference_fields (tree, unsigned HOST_WIDE_INT *,
37 unsigned HOST_WIDE_INT *, unsigned int,
38 int *, int *, int *, HOST_WIDE_INT *);
39 static void set_bit (unsigned HOST_WIDE_INT *, unsigned HOST_WIDE_INT *,
40 unsigned int);
42 /* A procedure-based object descriptor. We know that our
43 `kind' is 0, and `env' is likewise 0, so we have a simple
44 computation. From the GC sources:
45 (((((env) << LOG_MAX_MARK_PROCS) | (proc_index)) << DS_TAG_BITS) \
46 | DS_PROC)
47 Here DS_PROC == 2. */
48 #define PROCEDURE_OBJECT_DESCRIPTOR 2
50 /* Treat two HOST_WIDE_INT's as a contiguous bitmap, with bit 0 being
51 the least significant. This function sets bit N in the bitmap. */
52 static void
53 set_bit (unsigned HOST_WIDE_INT *low, unsigned HOST_WIDE_INT *high,
54 unsigned int n)
56 unsigned HOST_WIDE_INT *which;
58 if (n >= HOST_BITS_PER_WIDE_INT)
60 n -= HOST_BITS_PER_WIDE_INT;
61 which = high;
63 else
64 which = low;
66 *which |= (unsigned HOST_WIDE_INT) 1 << n;
69 /* Recursively mark reference fields. */
70 static void
71 mark_reference_fields (tree field,
72 unsigned HOST_WIDE_INT *low,
73 unsigned HOST_WIDE_INT *high,
74 unsigned int ubit,
75 int *pointer_after_end,
76 int *all_bits_set,
77 int *last_set_index,
78 HOST_WIDE_INT *last_view_index)
80 /* See if we have fields from our superclass. */
81 if (DECL_NAME (field) == NULL_TREE)
83 mark_reference_fields (TYPE_FIELDS (TREE_TYPE (field)),
84 low, high, ubit,
85 pointer_after_end, all_bits_set,
86 last_set_index, last_view_index);
87 field = TREE_CHAIN (field);
90 for (; field != NULL_TREE; field = TREE_CHAIN (field))
92 HOST_WIDE_INT offset;
93 HOST_WIDE_INT size_bytes;
95 if (FIELD_STATIC (field))
96 continue;
98 offset = int_byte_position (field);
99 size_bytes = int_size_in_bytes (TREE_TYPE (field));
101 if (JREFERENCE_TYPE_P (TREE_TYPE (field))
102 /* An `object' of type gnu.gcj.RawData is actually non-Java
103 data. */
104 && TREE_TYPE (field) != rawdata_ptr_type_node)
106 unsigned int count;
107 unsigned int size_words;
108 unsigned int i;
110 /* If this reference slot appears to overlay a slot we think
111 we already covered, then we are doomed. */
112 gcc_assert (offset > *last_view_index);
114 if (offset % (POINTER_SIZE / BITS_PER_UNIT))
116 *all_bits_set = -1;
117 *pointer_after_end = 1;
118 break;
121 count = offset * BITS_PER_UNIT / POINTER_SIZE;
122 size_words = size_bytes * BITS_PER_UNIT / POINTER_SIZE;
124 *last_set_index = count;
126 /* First word in object corresponds to most significant byte of
127 bitmap.
129 In the case of a multiple-word record, we set pointer
130 bits for all words in the record. This is conservative, but the
131 size_words != 1 case is impossible in regular java code. */
132 for (i = 0; i < size_words; ++i)
133 set_bit (low, high, ubit - count - i - 1);
135 if (count >= ubit - 2)
136 *pointer_after_end = 1;
138 /* If we saw a non-reference field earlier, then we can't
139 use the count representation. We keep track of that in
140 *ALL_BITS_SET. */
141 if (! *all_bits_set)
142 *all_bits_set = -1;
144 else if (*all_bits_set > 0)
145 *all_bits_set = 0;
147 *last_view_index = offset;
151 /* Return the marking bitmap for the class TYPE. For now this is a
152 single word describing the type. */
153 tree
154 get_boehm_type_descriptor (tree type)
156 unsigned int count, log2_size, ubit;
157 int bit;
158 int all_bits_set = 1;
159 int last_set_index = 0;
160 HOST_WIDE_INT last_view_index = -1;
161 int pointer_after_end = 0;
162 unsigned HOST_WIDE_INT low = 0, high = 0;
163 tree field, value, value_type;
165 /* If the GC wasn't requested, just use a null pointer. */
166 if (! flag_use_boehm_gc)
167 return null_pointer_node;
169 value_type = java_type_for_mode (ptr_mode, 1);
170 /* If we have a type of unknown size, use a proc. */
171 if (int_size_in_bytes (type) == -1)
172 goto procedure_object_descriptor;
174 bit = POINTER_SIZE / BITS_PER_UNIT;
175 /* The size of this node has to be known. And, we only support 32
176 and 64 bit targets, so we need to know that the log2 is one of
177 our values. */
178 log2_size = exact_log2 (bit);
179 if (bit == -1 || (log2_size != 2 && log2_size != 3))
181 /* This means the GC isn't supported. We should probably
182 abort or give an error. Instead, for now, we just silently
183 revert. FIXME. */
184 return null_pointer_node;
186 bit *= BITS_PER_UNIT;
188 /* Warning avoidance. */
189 ubit = (unsigned int) bit;
191 if (type == class_type_node)
192 goto procedure_object_descriptor;
194 field = TYPE_FIELDS (type);
195 mark_reference_fields (field, &low, &high, ubit,
196 &pointer_after_end, &all_bits_set,
197 &last_set_index, &last_view_index);
199 /* If the object is all pointers, or if the part with pointers fits
200 in our bitmap, then we are ok. Otherwise we have to allocate it
201 a different way. */
202 if (all_bits_set != -1 || (pointer_after_end && flag_reduced_reflection))
204 /* In this case the initial part of the object is all reference
205 fields, and the end of the object is all non-reference
206 fields. We represent the mark as a count of the fields,
207 shifted. In the GC the computation looks something like
208 this:
209 value = DS_LENGTH | WORDS_TO_BYTES (last_set_index + 1);
210 DS_LENGTH is 0.
211 WORDS_TO_BYTES shifts by log2(bytes-per-pointer).
213 In the case of flag_reduced_reflection and the bitmap would
214 overflow, we tell the gc that the object is all pointers so
215 that we don't have to emit reflection data for run time
216 marking. */
217 count = 0;
218 low = 0;
219 high = 0;
220 ++last_set_index;
221 while (last_set_index)
223 if ((last_set_index & 1))
224 set_bit (&low, &high, log2_size + count);
225 last_set_index >>= 1;
226 ++count;
228 value = build_int_cst_wide (value_type, low, high);
230 else if (! pointer_after_end)
232 /* Bottom two bits for bitmap mark type are 01. */
233 set_bit (&low, &high, 0);
234 value = build_int_cst_wide (value_type, low, high);
236 else
238 procedure_object_descriptor:
239 value = build_int_cst (value_type, PROCEDURE_OBJECT_DESCRIPTOR);
242 return value;
245 /* The fourth (index of 3) element in the vtable is the GC descriptor.
246 A value of 2 indicates that the class uses _Jv_MarkObj. */
247 bool
248 uses_jv_markobj_p (tree dtable)
250 tree v;
251 /* FIXME: what do we return if !flag_use_boehm_gc ? */
252 gcc_assert (flag_use_boehm_gc);
253 /* FIXME: this is wrong if TARGET_VTABLE_USES_DESCRIPTORS. However,
254 this function is only used with flag_reduced_reflection. No
255 point in asserting unless we hit the bad case. */
256 gcc_assert (!flag_reduced_reflection || TARGET_VTABLE_USES_DESCRIPTORS == 0);
257 v = VEC_index (constructor_elt, CONSTRUCTOR_ELTS (dtable), 3)->value;
258 return (PROCEDURE_OBJECT_DESCRIPTOR == TREE_INT_CST_LOW (v));