boehm.c 7.89 KB
Newer Older
1
/* Functions related to the Boehm garbage collector.
2
   Copyright (C) 2000, 2003, 2004, 2006 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 8 9 10
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

11
GCC is distributed in the hope that it will be useful,
12 13 14 15 16
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
17
along with GCC; see the file COPYING.  If not, write to
Kelley Cook committed
18 19
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
20 21 22 23 24 25 26 27 28 29

Java and all Java-based marks are trademarks or registered trademarks
of Sun Microsystems, Inc. in the United States and other countries.
The Free Software Foundation is independent of Sun Microsystems, Inc.  */

/* Written by Tom Tromey <tromey@cygnus.com>.  */

#include <config.h>

#include "system.h"
30 31
#include "coretypes.h"
#include "tm.h"
32 33 34
#include "tree.h"
#include "java-tree.h"
#include "parse.h"
35
#include "toplev.h"
36

37 38 39 40 41
static void mark_reference_fields (tree, unsigned HOST_WIDE_INT *,
				   unsigned HOST_WIDE_INT *, unsigned int,
				   int *, int *, int *, HOST_WIDE_INT *);
static void set_bit (unsigned HOST_WIDE_INT *, unsigned HOST_WIDE_INT *,
		     unsigned int);
42

43 44 45 46 47 48 49 50
/* A procedure-based object descriptor.  We know that our
   `kind' is 0, and `env' is likewise 0, so we have a simple
   computation.  From the GC sources:
   (((((env) << LOG_MAX_MARK_PROCS) | (proc_index)) << DS_TAG_BITS)	\
   | DS_PROC)
   Here DS_PROC == 2.  */
#define PROCEDURE_OBJECT_DESCRIPTOR 2

51 52 53
/* Treat two HOST_WIDE_INT's as a contiguous bitmap, with bit 0 being
   the least significant.  This function sets bit N in the bitmap.  */
static void
54 55
set_bit (unsigned HOST_WIDE_INT *low, unsigned HOST_WIDE_INT *high,
	 unsigned int n)
56
{
57
  unsigned HOST_WIDE_INT *which;
58 59 60 61 62 63 64 65 66

  if (n >= HOST_BITS_PER_WIDE_INT)
    {
      n -= HOST_BITS_PER_WIDE_INT;
      which = high;
    }
  else
    which = low;

67
  *which |= (unsigned HOST_WIDE_INT) 1 << n;
68 69
}

70
/* Recursively mark reference fields.  */
71
static void
72 73 74 75 76 77 78 79
mark_reference_fields (tree field,
		       unsigned HOST_WIDE_INT *low,
		       unsigned HOST_WIDE_INT *high,
		       unsigned int ubit,
		       int *pointer_after_end,
		       int *all_bits_set,
		       int *last_set_index,
		       HOST_WIDE_INT *last_view_index)
80 81 82 83
{
  /* See if we have fields from our superclass.  */
  if (DECL_NAME (field) == NULL_TREE)
    {
84 85 86 87
      mark_reference_fields (TYPE_FIELDS (TREE_TYPE (field)),
			     low, high, ubit,
			     pointer_after_end, all_bits_set,
			     last_set_index, last_view_index);
88 89 90 91 92
      field = TREE_CHAIN (field);
    }

  for (; field != NULL_TREE; field = TREE_CHAIN (field))
    {
93
      HOST_WIDE_INT offset;
94
      HOST_WIDE_INT size_bytes;
95

96 97 98
      if (FIELD_STATIC (field))
	continue;

99
      offset = int_byte_position (field);
100
      size_bytes = int_size_in_bytes (TREE_TYPE (field));
101 102 103 104
      if (JREFERENCE_TYPE_P (TREE_TYPE (field))
	  /* An `object' of type gnu.gcj.RawData is actually non-Java
	     data.  */
	  && TREE_TYPE (field) != rawdata_ptr_type_node)
105
	{
106
	  unsigned int count;
107 108
	  unsigned int size_words;
	  unsigned int i;
109 110 111

	  /* If this reference slot appears to overlay a slot we think
	     we already covered, then we are doomed.  */
112
	  gcc_assert (offset > *last_view_index);
113 114

	  count = offset * BITS_PER_UNIT / POINTER_SIZE;
115
	  size_words = size_bytes * BITS_PER_UNIT / POINTER_SIZE;
116

117
	  *last_set_index = count;
118 119 120 121 122 123 124 125 126 127
	     
	  /* First word in object corresponds to most significant byte of 
	     bitmap. 
	     
	     In the case of a multiple-word record, we set pointer 
	     bits for all words in the record. This is conservative, but the 
	     size_words != 1 case is impossible in regular java code. */
	  for (i = 0; i < size_words; ++i)
	    set_bit (low, high, ubit - count - i - 1);

128
	  if (count >= ubit - 2)
129
	    *pointer_after_end = 1;
130 131 132 133 134 135

	  /* If we saw a non-reference field earlier, then we can't
	     use the count representation.  We keep track of that in
	     *ALL_BITS_SET.  */
	  if (! *all_bits_set)
	    *all_bits_set = -1;
136
	}
137
      else if (*all_bits_set > 0)
138 139
	*all_bits_set = 0;

140
      *last_view_index = offset;
141 142 143
    }
}

144 145 146 147 148 149 150 151 152
/* Return the marking bitmap for the class TYPE.  For now this is a
   single word describing the type.  */
tree
get_boehm_type_descriptor (tree type)
{
  unsigned int count, log2_size, ubit;
  int bit;
  int all_bits_set = 1;
  int last_set_index = 0;
153
  HOST_WIDE_INT last_view_index = -1;
154 155
  int pointer_after_end = 0;
  unsigned HOST_WIDE_INT low = 0, high = 0;
156
  tree field, value, value_type;
157 158 159 160 161

  /* If the GC wasn't requested, just use a null pointer.  */
  if (! flag_use_boehm_gc)
    return null_pointer_node;

162
  value_type = java_type_for_mode (ptr_mode, 1);
163 164
  /* If we have a type of unknown size, use a proc.  */
  if (int_size_in_bytes (type) == -1)
165
    goto procedure_object_descriptor;
166

167
  bit = POINTER_SIZE / BITS_PER_UNIT;
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
  /* The size of this node has to be known.  And, we only support 32
     and 64 bit targets, so we need to know that the log2 is one of
     our values.  */
  log2_size = exact_log2 (bit);
  if (bit == -1 || (log2_size != 2 && log2_size != 3))
    {
      /* This means the GC isn't supported.  We should probably
	 abort or give an error.  Instead, for now, we just silently
	 revert.  FIXME.  */
      return null_pointer_node;
    }
  bit *= BITS_PER_UNIT;

  /* Warning avoidance.  */
  ubit = (unsigned int) bit;

184
  if (type == class_type_node)
185
    goto procedure_object_descriptor;
186

187
  field = TYPE_FIELDS (type);
188 189 190
  mark_reference_fields (field, &low, &high, ubit,
			 &pointer_after_end, &all_bits_set,
			 &last_set_index, &last_view_index);
191 192 193 194

  /* If the object is all pointers, or if the part with pointers fits
     in our bitmap, then we are ok.  Otherwise we have to allocate it
     a different way.  */
195
  if (all_bits_set != -1 || (pointer_after_end && flag_reduced_reflection))
196
    {
197 198 199 200 201
      /* In this case the initial part of the object is all reference
	 fields, and the end of the object is all non-reference
	 fields.  We represent the mark as a count of the fields,
	 shifted.  In the GC the computation looks something like
	 this:
202 203
	 value = DS_LENGTH | WORDS_TO_BYTES (last_set_index + 1);
	 DS_LENGTH is 0.
204 205 206 207 208 209
	 WORDS_TO_BYTES shifts by log2(bytes-per-pointer).

         In the case of flag_reduced_reflection and the bitmap would
         overflow, we tell the gc that the object is all pointers so
         that we don't have to emit reflection data for run time
         marking. */
210
      count = 0;
211 212
      low = 0;
      high = 0;
213 214 215 216 217 218 219 220
      ++last_set_index;
      while (last_set_index)
	{
	  if ((last_set_index & 1))
	    set_bit (&low, &high, log2_size + count);
	  last_set_index >>= 1;
	  ++count;
	}
221
      value = build_int_cst_wide (value_type, low, high);
222 223 224 225 226
    }
  else if (! pointer_after_end)
    {
      /* Bottom two bits for bitmap mark type are 01.  */
      set_bit (&low, &high, 0);
227
      value = build_int_cst_wide (value_type, low, high);
228 229
    }
  else
230 231
    {
    procedure_object_descriptor:
232
      value = build_int_cst (value_type, PROCEDURE_OBJECT_DESCRIPTOR);
233
    }
234 235 236

  return value;
}
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252

/* The fourth (index of 3) element in the vtable is the GC descriptor.
   A value of 2 indicates that the class uses _Jv_MarkObj. */
bool
uses_jv_markobj_p (tree dtable)
{
  tree v;
  /* FIXME: what do we return if !flag_use_boehm_gc ? */
  gcc_assert (flag_use_boehm_gc);
  /* FIXME: this is wrong if TARGET_VTABLE_USES_DESCRIPTORS.  However,
     this function is only used with flag_reduced_reflection.  No
     point in asserting unless we hit the bad case.  */
  gcc_assert (!flag_reduced_reflection || TARGET_VTABLE_USES_DESCRIPTORS == 0);
  v = VEC_index (constructor_elt, CONSTRUCTOR_ELTS (dtable), 3)->value;
  return (PROCEDURE_OBJECT_DESCRIPTOR == TREE_INT_CST_LOW (v));
}