OSDN Git Service

* boehm.c (mark_reference_fields): Only call byte_position on
[pf3gnuchains/gcc-fork.git] / gcc / java / boehm.c
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
34 static void mark_reference_fields PARAMS ((tree,
35                                            unsigned HOST_WIDE_INT *,
36                                            unsigned HOST_WIDE_INT *,
37                                            unsigned int,
38                                            int *, int *,
39                                            int *,
40                                            HOST_WIDE_INT *));
41 static void set_bit PARAMS ((unsigned HOST_WIDE_INT *,
42                              unsigned HOST_WIDE_INT *,
43                              unsigned int));
44
45 /* Compute a procedure-based object descriptor.  We know that our
46    `kind' is 0, and `env' is likewise 0, so we have a simple
47    computation.  From the GC sources:
48             (((((env) << LOG_MAX_MARK_PROCS) | (proc_index)) << DS_TAG_BITS) \
49             | DS_PROC)
50    Here DS_PROC == 2.  */
51 #define PROCEDURE_OBJECT_DESCRIPTOR integer_two_node
52
53 /* Treat two HOST_WIDE_INT's as a contiguous bitmap, with bit 0 being
54    the least significant.  This function sets bit N in the bitmap.  */
55 static void
56 set_bit (low, high, n)
57      unsigned HOST_WIDE_INT *low, *high;
58      unsigned int n;
59 {
60   HOST_WIDE_INT *which;
61
62   if (n >= HOST_BITS_PER_WIDE_INT)
63     {
64       n -= HOST_BITS_PER_WIDE_INT;
65       which = high;
66     }
67   else
68     which = low;
69
70   *which |= (HOST_WIDE_INT) 1 << n;
71 }
72
73 /* Recursively mark reference fields.  */
74 static void
75 mark_reference_fields (field, low, high, ubit,
76                        pointer_after_end, all_bits_set,
77                        last_set_index, last_view_index)
78      tree field;
79      unsigned HOST_WIDE_INT *low, *high;
80      unsigned int ubit;
81      int *pointer_after_end, *all_bits_set;
82      int *last_set_index;
83      HOST_WIDE_INT *last_view_index;
84 {
85   /* See if we have fields from our superclass.  */
86   if (DECL_NAME (field) == NULL_TREE)
87     {
88       mark_reference_fields (TYPE_FIELDS (TREE_TYPE (field)),
89                              low, high, ubit,
90                              pointer_after_end, all_bits_set,
91                              last_set_index, last_view_index);
92       field = TREE_CHAIN (field);
93     }
94
95   for (; field != NULL_TREE; field = TREE_CHAIN (field))
96     {
97       HOST_WIDE_INT offset;
98
99       if (FIELD_STATIC (field))
100         continue;
101
102       offset = tree_low_cst (byte_position (field), 1);
103       if (JREFERENCE_TYPE_P (TREE_TYPE (field)))
104         {
105           unsigned int count;
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
114           *last_set_index = count;
115           /* First word in object corresponds to most significant byte
116              of bitmap.  */
117           set_bit (low, high, ubit - count - 1);
118           if (count > ubit - 2)
119             *pointer_after_end = 1;
120         }
121       else
122         *all_bits_set = 0;
123
124       *last_view_index = offset;
125     }
126 }
127
128 /* Return the marking bitmap for the class TYPE.  For now this is a
129    single word describing the type.  */
130 tree
131 get_boehm_type_descriptor (tree type)
132 {
133   unsigned int count, log2_size, ubit;
134   int bit;
135   int all_bits_set = 1;
136   int last_set_index = 0;
137   HOST_WIDE_INT last_view_index = -1;
138   int pointer_after_end = 0;
139   unsigned HOST_WIDE_INT low = 0, high = 0;
140   tree field, value;
141
142   /* If the GC wasn't requested, just use a null pointer.  */
143   if (! flag_use_boehm_gc)
144     return null_pointer_node;
145
146   /* If we have a type of unknown size, use a proc.  */
147   if (int_size_in_bytes (type) == -1)
148     return PROCEDURE_OBJECT_DESCRIPTOR;
149
150   bit = POINTER_SIZE / BITS_PER_UNIT;
151   /* The size of this node has to be known.  And, we only support 32
152      and 64 bit targets, so we need to know that the log2 is one of
153      our values.  */
154   log2_size = exact_log2 (bit);
155   if (bit == -1 || (log2_size != 2 && log2_size != 3))
156     {
157       /* This means the GC isn't supported.  We should probably
158          abort or give an error.  Instead, for now, we just silently
159          revert.  FIXME.  */
160       return null_pointer_node;
161     }
162   bit *= BITS_PER_UNIT;
163
164   /* Warning avoidance.  */
165   ubit = (unsigned int) bit;
166
167   field = TYPE_FIELDS (type);
168   mark_reference_fields (field, &low, &high, ubit,
169                          &pointer_after_end, &all_bits_set,
170                          &last_set_index, &last_view_index);
171
172   /* If the object is all pointers, or if the part with pointers fits
173      in our bitmap, then we are ok.  Otherwise we have to allocate it
174      a different way.  */
175   if (all_bits_set)
176     {
177       /* In the GC the computation looks something like this:
178          value = DS_LENGTH | WORDS_TO_BYTES (last_set_index + 1);
179          DS_LENGTH is 0.
180          WORDS_TO_BYTES shifts by log2(bytes-per-pointer).  */
181       count = 0;
182       low = 0;
183       high = 0;
184       ++last_set_index;
185       while (last_set_index)
186         {
187           if ((last_set_index & 1))
188             set_bit (&low, &high, log2_size + count);
189           last_set_index >>= 1;
190           ++count;
191         }
192       value = build_int_2 (low, high);
193     }
194   else if (! pointer_after_end)
195     {
196       /* Bottom two bits for bitmap mark type are 01.  */
197       set_bit (&low, &high, 0);
198       value = build_int_2 (low, high);
199     }
200   else
201     value = PROCEDURE_OBJECT_DESCRIPTOR;
202
203   return value;
204 }