OSDN Git Service

gcc/
[pf3gnuchains/gcc-fork.git] / gcc / java / boehm.c
1 /* Functions related to the Boehm garbage collector.
2    Copyright (C) 2000, 2003, 2004, 2006, 2009 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
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.
10
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.
15
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/>.
19
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.  */
23
24 /* Written by Tom Tromey <tromey@cygnus.com>.  */
25
26 #include <config.h>
27
28 #include "system.h"
29 #include "coretypes.h"
30 #include "double-int.h"
31 #include "tm.h"
32 #include "tree.h"
33 #include "java-tree.h"
34 #include "parse.h"
35 #include "diagnostic-core.h"
36 #include "toplev.h"
37
38 static void mark_reference_fields (tree, double_int *, unsigned int,
39                                    int *, int *, int *, HOST_WIDE_INT *);
40
41 /* A procedure-based object descriptor.  We know that our
42    `kind' is 0, and `env' is likewise 0, so we have a simple
43    computation.  From the GC sources:
44    (((((env) << LOG_MAX_MARK_PROCS) | (proc_index)) << DS_TAG_BITS)     \
45    | DS_PROC)
46    Here DS_PROC == 2.  */
47 #define PROCEDURE_OBJECT_DESCRIPTOR 2
48
49 /* Recursively mark reference fields.  */
50 static void
51 mark_reference_fields (tree field,
52                        double_int *mask,
53                        unsigned int ubit,
54                        int *pointer_after_end,
55                        int *all_bits_set,
56                        int *last_set_index,
57                        HOST_WIDE_INT *last_view_index)
58 {
59   /* See if we have fields from our superclass.  */
60   if (DECL_NAME (field) == NULL_TREE)
61     {
62       mark_reference_fields (TYPE_FIELDS (TREE_TYPE (field)),
63                              mask, ubit,
64                              pointer_after_end, all_bits_set,
65                              last_set_index, last_view_index);
66       field = DECL_CHAIN (field);
67     }
68
69   for (; field != NULL_TREE; field = DECL_CHAIN (field))
70     {
71       HOST_WIDE_INT offset;
72       HOST_WIDE_INT size_bytes;
73
74       if (FIELD_STATIC (field))
75         continue;
76
77       offset = int_byte_position (field);
78       size_bytes = int_size_in_bytes (TREE_TYPE (field));
79
80       if (JREFERENCE_TYPE_P (TREE_TYPE (field))
81           /* An `object' of type gnu.gcj.RawData is actually non-Java
82              data.  */
83           && TREE_TYPE (field) != rawdata_ptr_type_node)
84         {
85           unsigned int count;
86           unsigned int size_words;
87           unsigned int i;
88
89           /* If this reference slot appears to overlay a slot we think
90              we already covered, then we are doomed.  */
91           gcc_assert (offset > *last_view_index);
92
93           if (offset % (HOST_WIDE_INT) (POINTER_SIZE / BITS_PER_UNIT))
94             {
95               *all_bits_set = -1;
96               *pointer_after_end = 1;
97               break;
98             }
99
100           count = offset * BITS_PER_UNIT / POINTER_SIZE;
101           size_words = size_bytes * BITS_PER_UNIT / POINTER_SIZE;
102
103           *last_set_index = count;
104              
105           /* First word in object corresponds to most significant byte of 
106              bitmap. 
107              
108              In the case of a multiple-word record, we set pointer 
109              bits for all words in the record. This is conservative, but the 
110              size_words != 1 case is impossible in regular java code. */
111           for (i = 0; i < size_words; ++i)
112             *mask = double_int_setbit (*mask, ubit - count - i - 1);
113
114           if (count >= ubit - 2)
115             *pointer_after_end = 1;
116
117           /* If we saw a non-reference field earlier, then we can't
118              use the count representation.  We keep track of that in
119              *ALL_BITS_SET.  */
120           if (! *all_bits_set)
121             *all_bits_set = -1;
122         }
123       else if (*all_bits_set > 0)
124         *all_bits_set = 0;
125
126       *last_view_index = offset;
127     }
128 }
129
130 /* Return the marking bitmap for the class TYPE.  For now this is a
131    single word describing the type.  */
132 tree
133 get_boehm_type_descriptor (tree type)
134 {
135   unsigned int count, log2_size, ubit;
136   int bit;
137   int all_bits_set = 1;
138   int last_set_index = 0;
139   HOST_WIDE_INT last_view_index = -1;
140   int pointer_after_end = 0;
141   double_int mask;
142   tree field, value, value_type;
143
144   mask = double_int_zero;
145
146   /* If the GC wasn't requested, just use a null pointer.  */
147   if (! flag_use_boehm_gc)
148     return null_pointer_node;
149
150   value_type = java_type_for_mode (ptr_mode, 1);
151   /* If we have a type of unknown size, use a proc.  */
152   if (int_size_in_bytes (type) == -1)
153     goto procedure_object_descriptor;
154
155   bit = POINTER_SIZE / BITS_PER_UNIT;
156   /* The size of this node has to be known.  And, we only support 32
157      and 64 bit targets, so we need to know that the log2 is one of
158      our values.  */
159   log2_size = exact_log2 (bit);
160   if (bit == -1 || (log2_size != 2 && log2_size != 3))
161     {
162       /* This means the GC isn't supported.  We should probably
163          abort or give an error.  Instead, for now, we just silently
164          revert.  FIXME.  */
165       return null_pointer_node;
166     }
167   bit *= BITS_PER_UNIT;
168
169   /* Warning avoidance.  */
170   ubit = (unsigned int) bit;
171
172   if (type == class_type_node)
173     goto procedure_object_descriptor;
174
175   field = TYPE_FIELDS (type);
176   mark_reference_fields (field, &mask, ubit,
177                          &pointer_after_end, &all_bits_set,
178                          &last_set_index, &last_view_index);
179
180   /* If the object is all pointers, or if the part with pointers fits
181      in our bitmap, then we are ok.  Otherwise we have to allocate it
182      a different way.  */
183   if (all_bits_set != -1 || (pointer_after_end && flag_reduced_reflection))
184     {
185       /* In this case the initial part of the object is all reference
186          fields, and the end of the object is all non-reference
187          fields.  We represent the mark as a count of the fields,
188          shifted.  In the GC the computation looks something like
189          this:
190          value = DS_LENGTH | WORDS_TO_BYTES (last_set_index + 1);
191          DS_LENGTH is 0.
192          WORDS_TO_BYTES shifts by log2(bytes-per-pointer).
193
194          In the case of flag_reduced_reflection and the bitmap would
195          overflow, we tell the gc that the object is all pointers so
196          that we don't have to emit reflection data for run time
197          marking. */
198       count = 0;
199       mask = double_int_zero;
200       ++last_set_index;
201       while (last_set_index)
202         {
203           if ((last_set_index & 1))
204             mask = double_int_setbit (mask, log2_size + count);
205           last_set_index >>= 1;
206           ++count;
207         }
208       value = double_int_to_tree (value_type, mask);
209     }
210   else if (! pointer_after_end)
211     {
212       /* Bottom two bits for bitmap mark type are 01.  */
213       mask = double_int_setbit (mask, 0);
214       value = double_int_to_tree (value_type, mask);
215     }
216   else
217     {
218     procedure_object_descriptor:
219       value = build_int_cst (value_type, PROCEDURE_OBJECT_DESCRIPTOR);
220     }
221
222   return value;
223 }
224
225 /* The fourth (index of 3) element in the vtable is the GC descriptor.
226    A value of 2 indicates that the class uses _Jv_MarkObj. */
227 bool
228 uses_jv_markobj_p (tree dtable)
229 {
230   tree v;
231   /* FIXME: what do we return if !flag_use_boehm_gc ? */
232   gcc_assert (flag_use_boehm_gc);
233   /* FIXME: this is wrong if TARGET_VTABLE_USES_DESCRIPTORS.  However,
234      this function is only used with flag_reduced_reflection.  No
235      point in asserting unless we hit the bad case.  */
236   gcc_assert (!flag_reduced_reflection || TARGET_VTABLE_USES_DESCRIPTORS == 0);
237   v = VEC_index (constructor_elt, CONSTRUCTOR_ELTS (dtable), 3)->value;
238   return (PROCEDURE_OBJECT_DESCRIPTOR == TREE_INT_CST_LOW (v));
239 }