OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [ggc-common.c] - Blame information for rev 849

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 684 jeremybenn
/* Simple garbage collection for the GNU compiler.
2
   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
3
   2009, 2010 Free Software Foundation, Inc.
4
 
5
This file is part of GCC.
6
 
7
GCC is free software; you can redistribute it and/or modify it under
8
the terms of the GNU General Public License as published by the Free
9
Software Foundation; either version 3, or (at your option) any later
10
version.
11
 
12
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13
WARRANTY; without even the implied warranty of MERCHANTABILITY or
14
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15
for more details.
16
 
17
You should have received a copy of the GNU General Public License
18
along with GCC; see the file COPYING3.  If not see
19
<http://www.gnu.org/licenses/>.  */
20
 
21
/* Generic garbage collection (GC) functions and data, not specific to
22
   any particular GC implementation.  */
23
 
24
#include "config.h"
25
#include "system.h"
26
#include "coretypes.h"
27
#include "hashtab.h"
28
#include "ggc.h"
29
#include "ggc-internal.h"
30
#include "diagnostic-core.h"
31
#include "params.h"
32
#include "hosthooks.h"
33
#include "hosthooks-def.h"
34
#include "plugin.h"
35
#include "vec.h"
36
#include "timevar.h"
37
 
38
/* When set, ggc_collect will do collection.  */
39
bool ggc_force_collect;
40
 
41
/* When true, protect the contents of the identifier hash table.  */
42
bool ggc_protect_identifiers = true;
43
 
44
/* Statistics about the allocation.  */
45
static ggc_statistics *ggc_stats;
46
 
47
struct traversal_state;
48
 
49
static int ggc_htab_delete (void **, void *);
50
static hashval_t saving_htab_hash (const void *);
51
static int saving_htab_eq (const void *, const void *);
52
static int call_count (void **, void *);
53
static int call_alloc (void **, void *);
54
static int compare_ptr_data (const void *, const void *);
55
static void relocate_ptrs (void *, void *);
56
static void write_pch_globals (const struct ggc_root_tab * const *tab,
57
                               struct traversal_state *state);
58
 
59
/* Maintain global roots that are preserved during GC.  */
60
 
61
/* Process a slot of an htab by deleting it if it has not been marked.  */
62
 
63
static int
64
ggc_htab_delete (void **slot, void *info)
65
{
66
  const struct ggc_cache_tab *r = (const struct ggc_cache_tab *) info;
67
 
68
  if (! (*r->marked_p) (*slot))
69
    htab_clear_slot (*r->base, slot);
70
  else
71
    (*r->cb) (*slot);
72
 
73
  return 1;
74
}
75
 
76
 
77
/* This extra vector of dynamically registered root_tab-s is used by
78
   ggc_mark_roots and gives the ability to dynamically add new GGC root
79
   tables, for instance from some plugins; this vector is on the heap
80
   since it is used by GGC internally.  */
81
typedef const struct ggc_root_tab *const_ggc_root_tab_t;
82
DEF_VEC_P(const_ggc_root_tab_t);
83
DEF_VEC_ALLOC_P(const_ggc_root_tab_t, heap);
84
static VEC(const_ggc_root_tab_t, heap) *extra_root_vec;
85
 
86
/* Dynamically register a new GGC root table RT. This is useful for
87
   plugins. */
88
 
89
void
90
ggc_register_root_tab (const struct ggc_root_tab* rt)
91
{
92
  if (rt)
93
    VEC_safe_push (const_ggc_root_tab_t, heap, extra_root_vec, rt);
94
}
95
 
96
/* This extra vector of dynamically registered cache_tab-s is used by
97
   ggc_mark_roots and gives the ability to dynamically add new GGC cache
98
   tables, for instance from some plugins; this vector is on the heap
99
   since it is used by GGC internally.  */
100
typedef const struct ggc_cache_tab *const_ggc_cache_tab_t;
101
DEF_VEC_P(const_ggc_cache_tab_t);
102
DEF_VEC_ALLOC_P(const_ggc_cache_tab_t, heap);
103
static VEC(const_ggc_cache_tab_t, heap) *extra_cache_vec;
104
 
105
/* Dynamically register a new GGC cache table CT. This is useful for
106
   plugins. */
107
 
108
void
109
ggc_register_cache_tab (const struct ggc_cache_tab* ct)
110
{
111
  if (ct)
112
    VEC_safe_push (const_ggc_cache_tab_t, heap, extra_cache_vec, ct);
113
}
114
 
115
/* Scan a hash table that has objects which are to be deleted if they are not
116
   already marked.  */
117
 
118
static void
119
ggc_scan_cache_tab (const_ggc_cache_tab_t ctp)
120
{
121
  const struct ggc_cache_tab *cti;
122
 
123
  for (cti = ctp; cti->base != NULL; cti++)
124
    if (*cti->base)
125
      {
126
        ggc_set_mark (*cti->base);
127
        htab_traverse_noresize (*cti->base, ggc_htab_delete,
128
                                CONST_CAST (void *, (const void *)cti));
129
        ggc_set_mark ((*cti->base)->entries);
130
      }
131
}
132
 
133
/* Mark all the roots in the table RT.  */
134
 
135
static void
136
ggc_mark_root_tab (const_ggc_root_tab_t rt)
137
{
138
  size_t i;
139
 
140
  for ( ; rt->base != NULL; rt++)
141
    for (i = 0; i < rt->nelt; i++)
142
      (*rt->cb) (*(void **) ((char *)rt->base + rt->stride * i));
143
}
144
 
145
/* Iterate through all registered roots and mark each element.  */
146
 
147
void
148
ggc_mark_roots (void)
149
{
150
  const struct ggc_root_tab *const *rt;
151
  const_ggc_root_tab_t rtp, rti;
152
  const struct ggc_cache_tab *const *ct;
153
  const_ggc_cache_tab_t ctp;
154
  size_t i;
155
 
156
  for (rt = gt_ggc_deletable_rtab; *rt; rt++)
157
    for (rti = *rt; rti->base != NULL; rti++)
158
      memset (rti->base, 0, rti->stride);
159
 
160
  for (rt = gt_ggc_rtab; *rt; rt++)
161
    ggc_mark_root_tab (*rt);
162
 
163
  FOR_EACH_VEC_ELT (const_ggc_root_tab_t, extra_root_vec, i, rtp)
164
    ggc_mark_root_tab (rtp);
165
 
166
  if (ggc_protect_identifiers)
167
    ggc_mark_stringpool ();
168
 
169
  /* Now scan all hash tables that have objects which are to be deleted if
170
     they are not already marked.  */
171
  for (ct = gt_ggc_cache_rtab; *ct; ct++)
172
    ggc_scan_cache_tab (*ct);
173
 
174
  FOR_EACH_VEC_ELT (const_ggc_cache_tab_t, extra_cache_vec, i, ctp)
175
    ggc_scan_cache_tab (ctp);
176
 
177
  if (! ggc_protect_identifiers)
178
    ggc_purge_stringpool ();
179
 
180
  /* Some plugins may call ggc_set_mark from here.  */
181
  invoke_plugin_callbacks (PLUGIN_GGC_MARKING, NULL);
182
}
183
 
184
/* Allocate a block of memory, then clear it.  */
185
void *
186
ggc_internal_cleared_alloc_stat (size_t size MEM_STAT_DECL)
187
{
188
  void *buf = ggc_internal_alloc_stat (size PASS_MEM_STAT);
189
  memset (buf, 0, size);
190
  return buf;
191
}
192
 
193
/* Resize a block of memory, possibly re-allocating it.  */
194
void *
195
ggc_realloc_stat (void *x, size_t size MEM_STAT_DECL)
196
{
197
  void *r;
198
  size_t old_size;
199
 
200
  if (x == NULL)
201
    return ggc_internal_alloc_stat (size PASS_MEM_STAT);
202
 
203
  old_size = ggc_get_size (x);
204
 
205
  if (size <= old_size)
206
    {
207
      /* Mark the unwanted memory as unaccessible.  We also need to make
208
         the "new" size accessible, since ggc_get_size returns the size of
209
         the pool, not the size of the individually allocated object, the
210
         size which was previously made accessible.  Unfortunately, we
211
         don't know that previously allocated size.  Without that
212
         knowledge we have to lose some initialization-tracking for the
213
         old parts of the object.  An alternative is to mark the whole
214
         old_size as reachable, but that would lose tracking of writes
215
         after the end of the object (by small offsets).  Discard the
216
         handle to avoid handle leak.  */
217
      VALGRIND_DISCARD (VALGRIND_MAKE_MEM_NOACCESS ((char *) x + size,
218
                                                    old_size - size));
219
      VALGRIND_DISCARD (VALGRIND_MAKE_MEM_DEFINED (x, size));
220
      return x;
221
    }
222
 
223
  r = ggc_internal_alloc_stat (size PASS_MEM_STAT);
224
 
225
  /* Since ggc_get_size returns the size of the pool, not the size of the
226
     individually allocated object, we'd access parts of the old object
227
     that were marked invalid with the memcpy below.  We lose a bit of the
228
     initialization-tracking since some of it may be uninitialized.  */
229
  VALGRIND_DISCARD (VALGRIND_MAKE_MEM_DEFINED (x, old_size));
230
 
231
  memcpy (r, x, old_size);
232
 
233
  /* The old object is not supposed to be used anymore.  */
234
  ggc_free (x);
235
 
236
  return r;
237
}
238
 
239
void *
240
ggc_cleared_alloc_htab_ignore_args (size_t c ATTRIBUTE_UNUSED,
241
                                    size_t n ATTRIBUTE_UNUSED)
242
{
243
  gcc_assert (c * n == sizeof (struct htab));
244
  return ggc_alloc_cleared_htab ();
245
}
246
 
247
/* TODO: once we actually use type information in GGC, create a new tag
248
   gt_gcc_ptr_array and use it for pointer arrays.  */
249
void *
250
ggc_cleared_alloc_ptr_array_two_args (size_t c, size_t n)
251
{
252
  gcc_assert (sizeof (PTR *) == n);
253
  return ggc_internal_cleared_vec_alloc (sizeof (PTR *), c);
254
}
255
 
256
/* These are for splay_tree_new_ggc.  */
257
void *
258
ggc_splay_alloc (enum gt_types_enum obj_type ATTRIBUTE_UNUSED, int sz,
259
                 void *nl)
260
{
261
  gcc_assert (!nl);
262
  return ggc_internal_alloc (sz);
263
}
264
 
265
void
266
ggc_splay_dont_free (void * x ATTRIBUTE_UNUSED, void *nl)
267
{
268
  gcc_assert (!nl);
269
}
270
 
271
/* Print statistics that are independent of the collector in use.  */
272
#define SCALE(x) ((unsigned long) ((x) < 1024*10 \
273
                  ? (x) \
274
                  : ((x) < 1024*1024*10 \
275
                     ? (x) / 1024 \
276
                     : (x) / (1024*1024))))
277
#define LABEL(x) ((x) < 1024*10 ? ' ' : ((x) < 1024*1024*10 ? 'k' : 'M'))
278
 
279
void
280
ggc_print_common_statistics (FILE *stream ATTRIBUTE_UNUSED,
281
                             ggc_statistics *stats)
282
{
283
  /* Set the pointer so that during collection we will actually gather
284
     the statistics.  */
285
  ggc_stats = stats;
286
 
287
  /* Then do one collection to fill in the statistics.  */
288
  ggc_collect ();
289
 
290
  /* At present, we don't really gather any interesting statistics.  */
291
 
292
  /* Don't gather statistics any more.  */
293
  ggc_stats = NULL;
294
}
295
 
296
/* Functions for saving and restoring GCable memory to disk.  */
297
 
298
static htab_t saving_htab;
299
 
300
struct ptr_data
301
{
302
  void *obj;
303
  void *note_ptr_cookie;
304
  gt_note_pointers note_ptr_fn;
305
  gt_handle_reorder reorder_fn;
306
  size_t size;
307
  void *new_addr;
308
  enum gt_types_enum type;
309
};
310
 
311
#define POINTER_HASH(x) (hashval_t)((long)x >> 3)
312
 
313
/* Register an object in the hash table.  */
314
 
315
int
316
gt_pch_note_object (void *obj, void *note_ptr_cookie,
317
                    gt_note_pointers note_ptr_fn,
318
                    enum gt_types_enum type)
319
{
320
  struct ptr_data **slot;
321
 
322
  if (obj == NULL || obj == (void *) 1)
323
    return 0;
324
 
325
  slot = (struct ptr_data **)
326
    htab_find_slot_with_hash (saving_htab, obj, POINTER_HASH (obj),
327
                              INSERT);
328
  if (*slot != NULL)
329
    {
330
      gcc_assert ((*slot)->note_ptr_fn == note_ptr_fn
331
                  && (*slot)->note_ptr_cookie == note_ptr_cookie);
332
      return 0;
333
    }
334
 
335
  *slot = XCNEW (struct ptr_data);
336
  (*slot)->obj = obj;
337
  (*slot)->note_ptr_fn = note_ptr_fn;
338
  (*slot)->note_ptr_cookie = note_ptr_cookie;
339
  if (note_ptr_fn == gt_pch_p_S)
340
    (*slot)->size = strlen ((const char *)obj) + 1;
341
  else
342
    (*slot)->size = ggc_get_size (obj);
343
  (*slot)->type = type;
344
  return 1;
345
}
346
 
347
/* Register an object in the hash table.  */
348
 
349
void
350
gt_pch_note_reorder (void *obj, void *note_ptr_cookie,
351
                     gt_handle_reorder reorder_fn)
352
{
353
  struct ptr_data *data;
354
 
355
  if (obj == NULL || obj == (void *) 1)
356
    return;
357
 
358
  data = (struct ptr_data *)
359
    htab_find_with_hash (saving_htab, obj, POINTER_HASH (obj));
360
  gcc_assert (data && data->note_ptr_cookie == note_ptr_cookie);
361
 
362
  data->reorder_fn = reorder_fn;
363
}
364
 
365
/* Hash and equality functions for saving_htab, callbacks for htab_create.  */
366
 
367
static hashval_t
368
saving_htab_hash (const void *p)
369
{
370
  return POINTER_HASH (((const struct ptr_data *)p)->obj);
371
}
372
 
373
static int
374
saving_htab_eq (const void *p1, const void *p2)
375
{
376
  return ((const struct ptr_data *)p1)->obj == p2;
377
}
378
 
379
/* Handy state for the traversal functions.  */
380
 
381
struct traversal_state
382
{
383
  FILE *f;
384
  struct ggc_pch_data *d;
385
  size_t count;
386
  struct ptr_data **ptrs;
387
  size_t ptrs_i;
388
};
389
 
390
/* Callbacks for htab_traverse.  */
391
 
392
static int
393
call_count (void **slot, void *state_p)
394
{
395
  struct ptr_data *d = (struct ptr_data *)*slot;
396
  struct traversal_state *state = (struct traversal_state *)state_p;
397
 
398
  ggc_pch_count_object (state->d, d->obj, d->size,
399
                        d->note_ptr_fn == gt_pch_p_S,
400
                        d->type);
401
  state->count++;
402
  return 1;
403
}
404
 
405
static int
406
call_alloc (void **slot, void *state_p)
407
{
408
  struct ptr_data *d = (struct ptr_data *)*slot;
409
  struct traversal_state *state = (struct traversal_state *)state_p;
410
 
411
  d->new_addr = ggc_pch_alloc_object (state->d, d->obj, d->size,
412
                                      d->note_ptr_fn == gt_pch_p_S,
413
                                      d->type);
414
  state->ptrs[state->ptrs_i++] = d;
415
  return 1;
416
}
417
 
418
/* Callback for qsort.  */
419
 
420
static int
421
compare_ptr_data (const void *p1_p, const void *p2_p)
422
{
423
  const struct ptr_data *const p1 = *(const struct ptr_data *const *)p1_p;
424
  const struct ptr_data *const p2 = *(const struct ptr_data *const *)p2_p;
425
  return (((size_t)p1->new_addr > (size_t)p2->new_addr)
426
          - ((size_t)p1->new_addr < (size_t)p2->new_addr));
427
}
428
 
429
/* Callbacks for note_ptr_fn.  */
430
 
431
static void
432
relocate_ptrs (void *ptr_p, void *state_p)
433
{
434
  void **ptr = (void **)ptr_p;
435
  struct traversal_state *state ATTRIBUTE_UNUSED
436
    = (struct traversal_state *)state_p;
437
  struct ptr_data *result;
438
 
439
  if (*ptr == NULL || *ptr == (void *)1)
440
    return;
441
 
442
  result = (struct ptr_data *)
443
    htab_find_with_hash (saving_htab, *ptr, POINTER_HASH (*ptr));
444
  gcc_assert (result);
445
  *ptr = result->new_addr;
446
}
447
 
448
/* Write out, after relocation, the pointers in TAB.  */
449
static void
450
write_pch_globals (const struct ggc_root_tab * const *tab,
451
                   struct traversal_state *state)
452
{
453
  const struct ggc_root_tab *const *rt;
454
  const struct ggc_root_tab *rti;
455
  size_t i;
456
 
457
  for (rt = tab; *rt; rt++)
458
    for (rti = *rt; rti->base != NULL; rti++)
459
      for (i = 0; i < rti->nelt; i++)
460
        {
461
          void *ptr = *(void **)((char *)rti->base + rti->stride * i);
462
          struct ptr_data *new_ptr;
463
          if (ptr == NULL || ptr == (void *)1)
464
            {
465
              if (fwrite (&ptr, sizeof (void *), 1, state->f)
466
                  != 1)
467
                fatal_error ("can%'t write PCH file: %m");
468
            }
469
          else
470
            {
471
              new_ptr = (struct ptr_data *)
472
                htab_find_with_hash (saving_htab, ptr, POINTER_HASH (ptr));
473
              if (fwrite (&new_ptr->new_addr, sizeof (void *), 1, state->f)
474
                  != 1)
475
                fatal_error ("can%'t write PCH file: %m");
476
            }
477
        }
478
}
479
 
480
/* Hold the information we need to mmap the file back in.  */
481
 
482
struct mmap_info
483
{
484
  size_t offset;
485
  size_t size;
486
  void *preferred_base;
487
};
488
 
489
/* Write out the state of the compiler to F.  */
490
 
491
void
492
gt_pch_save (FILE *f)
493
{
494
  const struct ggc_root_tab *const *rt;
495
  const struct ggc_root_tab *rti;
496
  size_t i;
497
  struct traversal_state state;
498
  char *this_object = NULL;
499
  size_t this_object_size = 0;
500
  struct mmap_info mmi;
501
  const size_t mmap_offset_alignment = host_hooks.gt_pch_alloc_granularity();
502
 
503
  gt_pch_save_stringpool ();
504
 
505
  timevar_push (TV_PCH_PTR_REALLOC);
506
  saving_htab = htab_create (50000, saving_htab_hash, saving_htab_eq, free);
507
 
508
  for (rt = gt_ggc_rtab; *rt; rt++)
509
    for (rti = *rt; rti->base != NULL; rti++)
510
      for (i = 0; i < rti->nelt; i++)
511
        (*rti->pchw)(*(void **)((char *)rti->base + rti->stride * i));
512
 
513
  for (rt = gt_pch_cache_rtab; *rt; rt++)
514
    for (rti = *rt; rti->base != NULL; rti++)
515
      for (i = 0; i < rti->nelt; i++)
516
        (*rti->pchw)(*(void **)((char *)rti->base + rti->stride * i));
517
 
518
  /* Prepare the objects for writing, determine addresses and such.  */
519
  state.f = f;
520
  state.d = init_ggc_pch ();
521
  state.count = 0;
522
  htab_traverse (saving_htab, call_count, &state);
523
 
524
  mmi.size = ggc_pch_total_size (state.d);
525
 
526
  /* Try to arrange things so that no relocation is necessary, but
527
     don't try very hard.  On most platforms, this will always work,
528
     and on the rest it's a lot of work to do better.
529
     (The extra work goes in HOST_HOOKS_GT_PCH_GET_ADDRESS and
530
     HOST_HOOKS_GT_PCH_USE_ADDRESS.)  */
531
  mmi.preferred_base = host_hooks.gt_pch_get_address (mmi.size, fileno (f));
532
 
533
  ggc_pch_this_base (state.d, mmi.preferred_base);
534
 
535
  state.ptrs = XNEWVEC (struct ptr_data *, state.count);
536
  state.ptrs_i = 0;
537
 
538
  htab_traverse (saving_htab, call_alloc, &state);
539
  timevar_pop (TV_PCH_PTR_REALLOC);
540
 
541
  timevar_push (TV_PCH_PTR_SORT);
542
  qsort (state.ptrs, state.count, sizeof (*state.ptrs), compare_ptr_data);
543
  timevar_pop (TV_PCH_PTR_SORT);
544
 
545
  /* Write out all the scalar variables.  */
546
  for (rt = gt_pch_scalar_rtab; *rt; rt++)
547
    for (rti = *rt; rti->base != NULL; rti++)
548
      if (fwrite (rti->base, rti->stride, 1, f) != 1)
549
        fatal_error ("can%'t write PCH file: %m");
550
 
551
  /* Write out all the global pointers, after translation.  */
552
  write_pch_globals (gt_ggc_rtab, &state);
553
  write_pch_globals (gt_pch_cache_rtab, &state);
554
 
555
  /* Pad the PCH file so that the mmapped area starts on an allocation
556
     granularity (usually page) boundary.  */
557
  {
558
    long o;
559
    o = ftell (state.f) + sizeof (mmi);
560
    if (o == -1)
561
      fatal_error ("can%'t get position in PCH file: %m");
562
    mmi.offset = mmap_offset_alignment - o % mmap_offset_alignment;
563
    if (mmi.offset == mmap_offset_alignment)
564
      mmi.offset = 0;
565
    mmi.offset += o;
566
  }
567
  if (fwrite (&mmi, sizeof (mmi), 1, state.f) != 1)
568
    fatal_error ("can%'t write PCH file: %m");
569
  if (mmi.offset != 0
570
      && fseek (state.f, mmi.offset, SEEK_SET) != 0)
571
    fatal_error ("can%'t write padding to PCH file: %m");
572
 
573
  ggc_pch_prepare_write (state.d, state.f);
574
 
575
  /* Actually write out the objects.  */
576
  for (i = 0; i < state.count; i++)
577
    {
578
      if (this_object_size < state.ptrs[i]->size)
579
        {
580
          this_object_size = state.ptrs[i]->size;
581
          this_object = XRESIZEVAR (char, this_object, this_object_size);
582
        }
583
      memcpy (this_object, state.ptrs[i]->obj, state.ptrs[i]->size);
584
      if (state.ptrs[i]->reorder_fn != NULL)
585
        state.ptrs[i]->reorder_fn (state.ptrs[i]->obj,
586
                                   state.ptrs[i]->note_ptr_cookie,
587
                                   relocate_ptrs, &state);
588
      state.ptrs[i]->note_ptr_fn (state.ptrs[i]->obj,
589
                                  state.ptrs[i]->note_ptr_cookie,
590
                                  relocate_ptrs, &state);
591
      ggc_pch_write_object (state.d, state.f, state.ptrs[i]->obj,
592
                            state.ptrs[i]->new_addr, state.ptrs[i]->size,
593
                            state.ptrs[i]->note_ptr_fn == gt_pch_p_S);
594
      if (state.ptrs[i]->note_ptr_fn != gt_pch_p_S)
595
        memcpy (state.ptrs[i]->obj, this_object, state.ptrs[i]->size);
596
    }
597
  ggc_pch_finish (state.d, state.f);
598
  gt_pch_fixup_stringpool ();
599
 
600
  free (state.ptrs);
601
  htab_delete (saving_htab);
602
}
603
 
604
/* Read the state of the compiler back in from F.  */
605
 
606
void
607
gt_pch_restore (FILE *f)
608
{
609
  const struct ggc_root_tab *const *rt;
610
  const struct ggc_root_tab *rti;
611
  size_t i;
612
  struct mmap_info mmi;
613
  int result;
614
 
615
  /* Delete any deletable objects.  This makes ggc_pch_read much
616
     faster, as it can be sure that no GCable objects remain other
617
     than the ones just read in.  */
618
  for (rt = gt_ggc_deletable_rtab; *rt; rt++)
619
    for (rti = *rt; rti->base != NULL; rti++)
620
      memset (rti->base, 0, rti->stride);
621
 
622
  /* Read in all the scalar variables.  */
623
  for (rt = gt_pch_scalar_rtab; *rt; rt++)
624
    for (rti = *rt; rti->base != NULL; rti++)
625
      if (fread (rti->base, rti->stride, 1, f) != 1)
626
        fatal_error ("can%'t read PCH file: %m");
627
 
628
  /* Read in all the global pointers, in 6 easy loops.  */
629
  for (rt = gt_ggc_rtab; *rt; rt++)
630
    for (rti = *rt; rti->base != NULL; rti++)
631
      for (i = 0; i < rti->nelt; i++)
632
        if (fread ((char *)rti->base + rti->stride * i,
633
                   sizeof (void *), 1, f) != 1)
634
          fatal_error ("can%'t read PCH file: %m");
635
 
636
  for (rt = gt_pch_cache_rtab; *rt; rt++)
637
    for (rti = *rt; rti->base != NULL; rti++)
638
      for (i = 0; i < rti->nelt; i++)
639
        if (fread ((char *)rti->base + rti->stride * i,
640
                   sizeof (void *), 1, f) != 1)
641
          fatal_error ("can%'t read PCH file: %m");
642
 
643
  if (fread (&mmi, sizeof (mmi), 1, f) != 1)
644
    fatal_error ("can%'t read PCH file: %m");
645
 
646
  result = host_hooks.gt_pch_use_address (mmi.preferred_base, mmi.size,
647
                                          fileno (f), mmi.offset);
648
  if (result < 0)
649
    fatal_error ("had to relocate PCH");
650
  if (result == 0)
651
    {
652
      if (fseek (f, mmi.offset, SEEK_SET) != 0
653
          || fread (mmi.preferred_base, mmi.size, 1, f) != 1)
654
        fatal_error ("can%'t read PCH file: %m");
655
    }
656
  else if (fseek (f, mmi.offset + mmi.size, SEEK_SET) != 0)
657
    fatal_error ("can%'t read PCH file: %m");
658
 
659
  ggc_pch_read (f, mmi.preferred_base);
660
 
661
  gt_pch_restore_stringpool ();
662
}
663
 
664
/* Default version of HOST_HOOKS_GT_PCH_GET_ADDRESS when mmap is not present.
665
   Select no address whatsoever, and let gt_pch_save choose what it will with
666
   malloc, presumably.  */
667
 
668
void *
669
default_gt_pch_get_address (size_t size ATTRIBUTE_UNUSED,
670
                            int fd ATTRIBUTE_UNUSED)
671
{
672
  return NULL;
673
}
674
 
675
/* Default version of HOST_HOOKS_GT_PCH_USE_ADDRESS when mmap is not present.
676
   Allocate SIZE bytes with malloc.  Return 0 if the address we got is the
677
   same as base, indicating that the memory has been allocated but needs to
678
   be read in from the file.  Return -1 if the address differs, to relocation
679
   of the PCH file would be required.  */
680
 
681
int
682
default_gt_pch_use_address (void *base, size_t size, int fd ATTRIBUTE_UNUSED,
683
                            size_t offset ATTRIBUTE_UNUSED)
684
{
685
  void *addr = xmalloc (size);
686
  return (addr == base) - 1;
687
}
688
 
689
/* Default version of HOST_HOOKS_GT_PCH_GET_ADDRESS.   Return the
690
   alignment required for allocating virtual memory. Usually this is the
691
   same as pagesize.  */
692
 
693
size_t
694
default_gt_pch_alloc_granularity (void)
695
{
696
  return getpagesize();
697
}
698
 
699
#if HAVE_MMAP_FILE
700
/* Default version of HOST_HOOKS_GT_PCH_GET_ADDRESS when mmap is present.
701
   We temporarily allocate SIZE bytes, and let the kernel place the data
702
   wherever it will.  If it worked, that's our spot, if not we're likely
703
   to be in trouble.  */
704
 
705
void *
706
mmap_gt_pch_get_address (size_t size, int fd)
707
{
708
  void *ret;
709
 
710
  ret = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
711
  if (ret == (void *) MAP_FAILED)
712
    ret = NULL;
713
  else
714
    munmap ((caddr_t) ret, size);
715
 
716
  return ret;
717
}
718
 
719
/* Default version of HOST_HOOKS_GT_PCH_USE_ADDRESS when mmap is present.
720
   Map SIZE bytes of FD+OFFSET at BASE.  Return 1 if we succeeded at
721
   mapping the data at BASE, -1 if we couldn't.
722
 
723
   This version assumes that the kernel honors the START operand of mmap
724
   even without MAP_FIXED if START through START+SIZE are not currently
725
   mapped with something.  */
726
 
727
int
728
mmap_gt_pch_use_address (void *base, size_t size, int fd, size_t offset)
729
{
730
  void *addr;
731
 
732
  /* We're called with size == 0 if we're not planning to load a PCH
733
     file at all.  This allows the hook to free any static space that
734
     we might have allocated at link time.  */
735
  if (size == 0)
736
    return -1;
737
 
738
  addr = mmap ((caddr_t) base, size, PROT_READ | PROT_WRITE, MAP_PRIVATE,
739
               fd, offset);
740
 
741
  return addr == base ? 1 : -1;
742
}
743
#endif /* HAVE_MMAP_FILE */
744
 
745
#if !defined ENABLE_GC_CHECKING && !defined ENABLE_GC_ALWAYS_COLLECT
746
 
747
/* Modify the bound based on rlimits.  */
748
static double
749
ggc_rlimit_bound (double limit)
750
{
751
#if defined(HAVE_GETRLIMIT)
752
  struct rlimit rlim;
753
# if defined (RLIMIT_AS)
754
  /* RLIMIT_AS is what POSIX says is the limit on mmap.  Presumably
755
     any OS which has RLIMIT_AS also has a working mmap that GCC will use.  */
756
  if (getrlimit (RLIMIT_AS, &rlim) == 0
757
      && rlim.rlim_cur != (rlim_t) RLIM_INFINITY
758
      && rlim.rlim_cur < limit)
759
    limit = rlim.rlim_cur;
760
# elif defined (RLIMIT_DATA)
761
  /* ... but some older OSs bound mmap based on RLIMIT_DATA, or we
762
     might be on an OS that has a broken mmap.  (Others don't bound
763
     mmap at all, apparently.)  */
764
  if (getrlimit (RLIMIT_DATA, &rlim) == 0
765
      && rlim.rlim_cur != (rlim_t) RLIM_INFINITY
766
      && rlim.rlim_cur < limit
767
      /* Darwin has this horribly bogus default setting of
768
         RLIMIT_DATA, to 6144Kb.  No-one notices because RLIMIT_DATA
769
         appears to be ignored.  Ignore such silliness.  If a limit
770
         this small was actually effective for mmap, GCC wouldn't even
771
         start up.  */
772
      && rlim.rlim_cur >= 8 * 1024 * 1024)
773
    limit = rlim.rlim_cur;
774
# endif /* RLIMIT_AS or RLIMIT_DATA */
775
#endif /* HAVE_GETRLIMIT */
776
 
777
  return limit;
778
}
779
 
780
/* Heuristic to set a default for GGC_MIN_EXPAND.  */
781
static int
782
ggc_min_expand_heuristic (void)
783
{
784
  double min_expand = physmem_total();
785
 
786
  /* Adjust for rlimits.  */
787
  min_expand = ggc_rlimit_bound (min_expand);
788
 
789
  /* The heuristic is a percentage equal to 30% + 70%*(RAM/1GB), yielding
790
     a lower bound of 30% and an upper bound of 100% (when RAM >= 1GB).  */
791
  min_expand /= 1024*1024*1024;
792
  min_expand *= 70;
793
  min_expand = MIN (min_expand, 70);
794
  min_expand += 30;
795
 
796
  return min_expand;
797
}
798
 
799
/* Heuristic to set a default for GGC_MIN_HEAPSIZE.  */
800
static int
801
ggc_min_heapsize_heuristic (void)
802
{
803
  double phys_kbytes = physmem_total();
804
  double limit_kbytes = ggc_rlimit_bound (phys_kbytes * 2);
805
 
806
  phys_kbytes /= 1024; /* Convert to Kbytes.  */
807
  limit_kbytes /= 1024;
808
 
809
  /* The heuristic is RAM/8, with a lower bound of 4M and an upper
810
     bound of 128M (when RAM >= 1GB).  */
811
  phys_kbytes /= 8;
812
 
813
#if defined(HAVE_GETRLIMIT) && defined (RLIMIT_RSS)
814
  /* Try not to overrun the RSS limit while doing garbage collection.
815
     The RSS limit is only advisory, so no margin is subtracted.  */
816
 {
817
   struct rlimit rlim;
818
   if (getrlimit (RLIMIT_RSS, &rlim) == 0
819
       && rlim.rlim_cur != (rlim_t) RLIM_INFINITY)
820
     phys_kbytes = MIN (phys_kbytes, rlim.rlim_cur / 1024);
821
 }
822
# endif
823
 
824
  /* Don't blindly run over our data limit; do GC at least when the
825
     *next* GC would be within 20Mb of the limit or within a quarter of
826
     the limit, whichever is larger.  If GCC does hit the data limit,
827
     compilation will fail, so this tries to be conservative.  */
828
  limit_kbytes = MAX (0, limit_kbytes - MAX (limit_kbytes / 4, 20 * 1024));
829
  limit_kbytes = (limit_kbytes * 100) / (110 + ggc_min_expand_heuristic ());
830
  phys_kbytes = MIN (phys_kbytes, limit_kbytes);
831
 
832
  phys_kbytes = MAX (phys_kbytes, 4 * 1024);
833
  phys_kbytes = MIN (phys_kbytes, 128 * 1024);
834
 
835
  return phys_kbytes;
836
}
837
#endif
838
 
839
void
840
init_ggc_heuristics (void)
841
{
842
#if !defined ENABLE_GC_CHECKING && !defined ENABLE_GC_ALWAYS_COLLECT
843
  set_default_param_value (GGC_MIN_EXPAND, ggc_min_expand_heuristic ());
844
  set_default_param_value (GGC_MIN_HEAPSIZE, ggc_min_heapsize_heuristic ());
845
#endif
846
}
847
 
848
#ifdef GATHER_STATISTICS
849
 
850
/* Datastructure used to store per-call-site statistics.  */
851
struct loc_descriptor
852
{
853
  const char *file;
854
  int line;
855
  const char *function;
856
  int times;
857
  size_t allocated;
858
  size_t overhead;
859
  size_t freed;
860
  size_t collected;
861
};
862
 
863
/* Hashtable used for statistics.  */
864
static htab_t loc_hash;
865
 
866
/* Hash table helpers functions.  */
867
static hashval_t
868
hash_descriptor (const void *p)
869
{
870
  const struct loc_descriptor *const d = (const struct loc_descriptor *) p;
871
 
872
  return htab_hash_pointer (d->function) | d->line;
873
}
874
 
875
static int
876
eq_descriptor (const void *p1, const void *p2)
877
{
878
  const struct loc_descriptor *const d = (const struct loc_descriptor *) p1;
879
  const struct loc_descriptor *const d2 = (const struct loc_descriptor *) p2;
880
 
881
  return (d->file == d2->file && d->line == d2->line
882
          && d->function == d2->function);
883
}
884
 
885
/* Hashtable converting address of allocated field to loc descriptor.  */
886
static htab_t ptr_hash;
887
struct ptr_hash_entry
888
{
889
  void *ptr;
890
  struct loc_descriptor *loc;
891
  size_t size;
892
};
893
 
894
/* Hash table helpers functions.  */
895
static hashval_t
896
hash_ptr (const void *p)
897
{
898
  const struct ptr_hash_entry *const d = (const struct ptr_hash_entry *) p;
899
 
900
  return htab_hash_pointer (d->ptr);
901
}
902
 
903
static int
904
eq_ptr (const void *p1, const void *p2)
905
{
906
  const struct ptr_hash_entry *const p = (const struct ptr_hash_entry *) p1;
907
 
908
  return (p->ptr == p2);
909
}
910
 
911
/* Return descriptor for given call site, create new one if needed.  */
912
static struct loc_descriptor *
913
loc_descriptor (const char *name, int line, const char *function)
914
{
915
  struct loc_descriptor loc;
916
  struct loc_descriptor **slot;
917
 
918
  loc.file = name;
919
  loc.line = line;
920
  loc.function = function;
921
  if (!loc_hash)
922
    loc_hash = htab_create (10, hash_descriptor, eq_descriptor, NULL);
923
 
924
  slot = (struct loc_descriptor **) htab_find_slot (loc_hash, &loc, INSERT);
925
  if (*slot)
926
    return *slot;
927
  *slot = XCNEW (struct loc_descriptor);
928
  (*slot)->file = name;
929
  (*slot)->line = line;
930
  (*slot)->function = function;
931
  return *slot;
932
}
933
 
934
/* Record ALLOCATED and OVERHEAD bytes to descriptor NAME:LINE (FUNCTION).  */
935
void
936
ggc_record_overhead (size_t allocated, size_t overhead, void *ptr,
937
                     const char *name, int line, const char *function)
938
{
939
  struct loc_descriptor *loc = loc_descriptor (name, line, function);
940
  struct ptr_hash_entry *p = XNEW (struct ptr_hash_entry);
941
  PTR *slot;
942
 
943
  p->ptr = ptr;
944
  p->loc = loc;
945
  p->size = allocated + overhead;
946
  if (!ptr_hash)
947
    ptr_hash = htab_create (10, hash_ptr, eq_ptr, NULL);
948
  slot = htab_find_slot_with_hash (ptr_hash, ptr, htab_hash_pointer (ptr), INSERT);
949
  gcc_assert (!*slot);
950
  *slot = p;
951
 
952
  loc->times++;
953
  loc->allocated+=allocated;
954
  loc->overhead+=overhead;
955
}
956
 
957
/* Helper function for prune_overhead_list.  See if SLOT is still marked and
958
   remove it from hashtable if it is not.  */
959
static int
960
ggc_prune_ptr (void **slot, void *b ATTRIBUTE_UNUSED)
961
{
962
  struct ptr_hash_entry *p = (struct ptr_hash_entry *) *slot;
963
  if (!ggc_marked_p (p->ptr))
964
    {
965
      p->loc->collected += p->size;
966
      htab_clear_slot (ptr_hash, slot);
967
      free (p);
968
    }
969
  return 1;
970
}
971
 
972
/* After live values has been marked, walk all recorded pointers and see if
973
   they are still live.  */
974
void
975
ggc_prune_overhead_list (void)
976
{
977
  htab_traverse (ptr_hash, ggc_prune_ptr, NULL);
978
}
979
 
980
/* Notice that the pointer has been freed.  */
981
void
982
ggc_free_overhead (void *ptr)
983
{
984
  PTR *slot = htab_find_slot_with_hash (ptr_hash, ptr, htab_hash_pointer (ptr),
985
                                        NO_INSERT);
986
  struct ptr_hash_entry *p;
987
  /* The pointer might be not found if a PCH read happened between allocation
988
     and ggc_free () call.  FIXME: account memory properly in the presence of
989
     PCH. */
990
  if (!slot)
991
      return;
992
  p = (struct ptr_hash_entry *) *slot;
993
  p->loc->freed += p->size;
994
  htab_clear_slot (ptr_hash, slot);
995
  free (p);
996
}
997
 
998
/* Helper for qsort; sort descriptors by amount of memory consumed.  */
999
static int
1000
final_cmp_statistic (const void *loc1, const void *loc2)
1001
{
1002
  const struct loc_descriptor *const l1 =
1003
    *(const struct loc_descriptor *const *) loc1;
1004
  const struct loc_descriptor *const l2 =
1005
    *(const struct loc_descriptor *const *) loc2;
1006
  long diff;
1007
  diff = ((long)(l1->allocated + l1->overhead - l1->freed) -
1008
          (l2->allocated + l2->overhead - l2->freed));
1009
  return diff > 0 ? 1 : diff < 0 ? -1 : 0;
1010
}
1011
 
1012
/* Helper for qsort; sort descriptors by amount of memory consumed.  */
1013
static int
1014
cmp_statistic (const void *loc1, const void *loc2)
1015
{
1016
  const struct loc_descriptor *const l1 =
1017
    *(const struct loc_descriptor *const *) loc1;
1018
  const struct loc_descriptor *const l2 =
1019
    *(const struct loc_descriptor *const *) loc2;
1020
  long diff;
1021
 
1022
  diff = ((long)(l1->allocated + l1->overhead - l1->freed - l1->collected) -
1023
          (l2->allocated + l2->overhead - l2->freed - l2->collected));
1024
  if (diff)
1025
    return diff > 0 ? 1 : diff < 0 ? -1 : 0;
1026
  diff =  ((long)(l1->allocated + l1->overhead - l1->freed) -
1027
           (l2->allocated + l2->overhead - l2->freed));
1028
  return diff > 0 ? 1 : diff < 0 ? -1 : 0;
1029
}
1030
 
1031
/* Collect array of the descriptors from hashtable.  */
1032
static struct loc_descriptor **loc_array;
1033
static int
1034
add_statistics (void **slot, void *b)
1035
{
1036
  int *n = (int *)b;
1037
  loc_array[*n] = (struct loc_descriptor *) *slot;
1038
  (*n)++;
1039
  return 1;
1040
}
1041
 
1042
/* Dump per-site memory statistics.  */
1043
#endif
1044
void
1045
dump_ggc_loc_statistics (bool final ATTRIBUTE_UNUSED)
1046
{
1047
#ifdef GATHER_STATISTICS
1048
  int nentries = 0;
1049
  char s[4096];
1050
  size_t collected = 0, freed = 0, allocated = 0, overhead = 0, times = 0;
1051
  int i;
1052
 
1053
  ggc_force_collect = true;
1054
  ggc_collect ();
1055
 
1056
  loc_array = XCNEWVEC (struct loc_descriptor *, loc_hash->n_elements);
1057
  fprintf (stderr, "-------------------------------------------------------\n");
1058
  fprintf (stderr, "\n%-48s %10s       %10s       %10s       %10s       %10s\n",
1059
           "source location", "Garbage", "Freed", "Leak", "Overhead", "Times");
1060
  fprintf (stderr, "-------------------------------------------------------\n");
1061
  htab_traverse (loc_hash, add_statistics, &nentries);
1062
  qsort (loc_array, nentries, sizeof (*loc_array),
1063
         final ? final_cmp_statistic : cmp_statistic);
1064
  for (i = 0; i < nentries; i++)
1065
    {
1066
      struct loc_descriptor *d = loc_array[i];
1067
      allocated += d->allocated;
1068
      times += d->times;
1069
      freed += d->freed;
1070
      collected += d->collected;
1071
      overhead += d->overhead;
1072
    }
1073
  for (i = 0; i < nentries; i++)
1074
    {
1075
      struct loc_descriptor *d = loc_array[i];
1076
      if (d->allocated)
1077
        {
1078
          const char *s1 = d->file;
1079
          const char *s2;
1080
          while ((s2 = strstr (s1, "gcc/")))
1081
            s1 = s2 + 4;
1082
          sprintf (s, "%s:%i (%s)", s1, d->line, d->function);
1083
          s[48] = 0;
1084
          fprintf (stderr, "%-48s %10li:%4.1f%% %10li:%4.1f%% %10li:%4.1f%% %10li:%4.1f%% %10li\n", s,
1085
                   (long)d->collected,
1086
                   (d->collected) * 100.0 / collected,
1087
                   (long)d->freed,
1088
                   (d->freed) * 100.0 / freed,
1089
                   (long)(d->allocated + d->overhead - d->freed - d->collected),
1090
                   (d->allocated + d->overhead - d->freed - d->collected) * 100.0
1091
                   / (allocated + overhead - freed - collected),
1092
                   (long)d->overhead,
1093
                   d->overhead * 100.0 / overhead,
1094
                   (long)d->times);
1095
        }
1096
    }
1097
  fprintf (stderr, "%-48s %10ld       %10ld       %10ld       %10ld       %10ld\n",
1098
           "Total", (long)collected, (long)freed,
1099
           (long)(allocated + overhead - freed - collected), (long)overhead,
1100
           (long)times);
1101
  fprintf (stderr, "%-48s %10s       %10s       %10s       %10s       %10s\n",
1102
           "source location", "Garbage", "Freed", "Leak", "Overhead", "Times");
1103
  fprintf (stderr, "-------------------------------------------------------\n");
1104
  ggc_force_collect = false;
1105
#endif
1106
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.