190075Sobrien/* Simple garbage collection for the GNU compiler. 2169689Skan Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 3132718Skan Free Software Foundation, Inc. 490075Sobrien 590075SobrienThis file is part of GCC. 690075Sobrien 790075SobrienGCC is free software; you can redistribute it and/or modify it under 890075Sobrienthe terms of the GNU General Public License as published by the Free 990075SobrienSoftware Foundation; either version 2, or (at your option) any later 1090075Sobrienversion. 1190075Sobrien 1290075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY 1390075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or 1490075SobrienFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1590075Sobrienfor more details. 1690075Sobrien 1790075SobrienYou should have received a copy of the GNU General Public License 1890075Sobrienalong with GCC; see the file COPYING. If not, write to the Free 19169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 20169689Skan02110-1301, USA. */ 2190075Sobrien 2290075Sobrien/* Generic garbage collection (GC) functions and data, not specific to 2390075Sobrien any particular GC implementation. */ 2490075Sobrien 2590075Sobrien#include "config.h" 2690075Sobrien#include "system.h" 27132718Skan#include "coretypes.h" 2890075Sobrien#include "hashtab.h" 2990075Sobrien#include "ggc.h" 30132718Skan#include "toplev.h" 31117395Skan#include "params.h" 32132718Skan#include "hosthooks.h" 33161651Skan#include "hosthooks-def.h" 34132718Skan 35117395Skan#ifdef HAVE_SYS_RESOURCE_H 36117395Skan# include <sys/resource.h> 37117395Skan#endif 38132718Skan 39132718Skan#ifdef HAVE_MMAP_FILE 40132718Skan# include <sys/mman.h> 41132718Skan# ifdef HAVE_MINCORE 42132718Skan/* This is on Solaris. */ 43132718Skan# include <sys/types.h> 44132718Skan# endif 45132718Skan#endif 46132718Skan 47132718Skan#ifndef MAP_FAILED 48132718Skan# define MAP_FAILED ((void *)-1) 49132718Skan#endif 50132718Skan 51117395Skan#ifdef ENABLE_VALGRIND_CHECKING 52132718Skan# ifdef HAVE_VALGRIND_MEMCHECK_H 53132718Skan# include <valgrind/memcheck.h> 54132718Skan# elif defined HAVE_MEMCHECK_H 55132718Skan# include <memcheck.h> 56132718Skan# else 57132718Skan# include <valgrind.h> 58132718Skan# endif 59117395Skan#else 60117395Skan/* Avoid #ifdef:s when we can help it. */ 61117395Skan#define VALGRIND_DISCARD(x) 62117395Skan#endif 6390075Sobrien 64169689Skan/* When set, ggc_collect will do collection. */ 65169689Skanbool ggc_force_collect; 66169689Skan 6790075Sobrien/* Statistics about the allocation. */ 6890075Sobrienstatic ggc_statistics *ggc_stats; 6990075Sobrien 70132718Skanstruct traversal_state; 7190075Sobrien 72132718Skanstatic int ggc_htab_delete (void **, void *); 73132718Skanstatic hashval_t saving_htab_hash (const void *); 74132718Skanstatic int saving_htab_eq (const void *, const void *); 75132718Skanstatic int call_count (void **, void *); 76132718Skanstatic int call_alloc (void **, void *); 77132718Skanstatic int compare_ptr_data (const void *, const void *); 78132718Skanstatic void relocate_ptrs (void *, void *); 79132718Skanstatic void write_pch_globals (const struct ggc_root_tab * const *tab, 80132718Skan struct traversal_state *state); 81132718Skanstatic double ggc_rlimit_bound (double); 82132718Skan 8390075Sobrien/* Maintain global roots that are preserved during GC. */ 8490075Sobrien 8590075Sobrien/* Process a slot of an htab by deleting it if it has not been marked. */ 8690075Sobrien 8790075Sobrienstatic int 88132718Skanggc_htab_delete (void **slot, void *info) 8990075Sobrien{ 90117395Skan const struct ggc_cache_tab *r = (const struct ggc_cache_tab *) info; 9190075Sobrien 9290075Sobrien if (! (*r->marked_p) (*slot)) 93117395Skan htab_clear_slot (*r->base, slot); 94117395Skan else 95117395Skan (*r->cb) (*slot); 9690075Sobrien 9790075Sobrien return 1; 9890075Sobrien} 9990075Sobrien 10090075Sobrien/* Iterate through all registered roots and mark each element. */ 10190075Sobrien 10290075Sobrienvoid 103132718Skanggc_mark_roots (void) 10490075Sobrien{ 105117395Skan const struct ggc_root_tab *const *rt; 106117395Skan const struct ggc_root_tab *rti; 107117395Skan const struct ggc_cache_tab *const *ct; 108117395Skan const struct ggc_cache_tab *cti; 109117395Skan size_t i; 11090075Sobrien 111117395Skan for (rt = gt_ggc_deletable_rtab; *rt; rt++) 112117395Skan for (rti = *rt; rti->base != NULL; rti++) 113117395Skan memset (rti->base, 0, rti->stride); 114117395Skan 115117395Skan for (rt = gt_ggc_rtab; *rt; rt++) 116117395Skan for (rti = *rt; rti->base != NULL; rti++) 117117395Skan for (i = 0; i < rti->nelt; i++) 118117395Skan (*rti->cb)(*(void **)((char *)rti->base + rti->stride * i)); 119117395Skan 120132718Skan ggc_mark_stringpool (); 12190075Sobrien 12290075Sobrien /* Now scan all hash tables that have objects which are to be deleted if 123117395Skan they are not already marked. */ 124117395Skan for (ct = gt_ggc_cache_rtab; *ct; ct++) 125117395Skan for (cti = *ct; cti->base != NULL; cti++) 126117395Skan if (*cti->base) 127132718Skan { 128132718Skan ggc_set_mark (*cti->base); 129132718Skan htab_traverse_noresize (*cti->base, ggc_htab_delete, (void *) cti); 130132718Skan ggc_set_mark ((*cti->base)->entries); 131132718Skan } 13290075Sobrien} 13390075Sobrien 134117395Skan/* Allocate a block of memory, then clear it. */ 135117395Skanvoid * 136169689Skanggc_alloc_cleared_stat (size_t size MEM_STAT_DECL) 13790075Sobrien{ 138169689Skan void *buf = ggc_alloc_stat (size PASS_MEM_STAT); 139117395Skan memset (buf, 0, size); 140117395Skan return buf; 14196263Sobrien} 14296263Sobrien 143117395Skan/* Resize a block of memory, possibly re-allocating it. */ 144117395Skanvoid * 145169689Skanggc_realloc_stat (void *x, size_t size MEM_STAT_DECL) 14696263Sobrien{ 147117395Skan void *r; 148117395Skan size_t old_size; 14990075Sobrien 150117395Skan if (x == NULL) 151169689Skan return ggc_alloc_stat (size PASS_MEM_STAT); 15290075Sobrien 153117395Skan old_size = ggc_get_size (x); 154169689Skan 155117395Skan if (size <= old_size) 15690075Sobrien { 157117395Skan /* Mark the unwanted memory as unaccessible. We also need to make 158117395Skan the "new" size accessible, since ggc_get_size returns the size of 159117395Skan the pool, not the size of the individually allocated object, the 160117395Skan size which was previously made accessible. Unfortunately, we 161117395Skan don't know that previously allocated size. Without that 162117395Skan knowledge we have to lose some initialization-tracking for the 163117395Skan old parts of the object. An alternative is to mark the whole 164132718Skan old_size as reachable, but that would lose tracking of writes 165117395Skan after the end of the object (by small offsets). Discard the 166117395Skan handle to avoid handle leak. */ 167117395Skan VALGRIND_DISCARD (VALGRIND_MAKE_NOACCESS ((char *) x + size, 168117395Skan old_size - size)); 169117395Skan VALGRIND_DISCARD (VALGRIND_MAKE_READABLE (x, size)); 170117395Skan return x; 17190075Sobrien } 17290075Sobrien 173169689Skan r = ggc_alloc_stat (size PASS_MEM_STAT); 17490075Sobrien 175117395Skan /* Since ggc_get_size returns the size of the pool, not the size of the 176117395Skan individually allocated object, we'd access parts of the old object 177117395Skan that were marked invalid with the memcpy below. We lose a bit of the 178117395Skan initialization-tracking since some of it may be uninitialized. */ 179117395Skan VALGRIND_DISCARD (VALGRIND_MAKE_READABLE (x, old_size)); 18090075Sobrien 181117395Skan memcpy (r, x, old_size); 18290075Sobrien 183117395Skan /* The old object is not supposed to be used anymore. */ 184169689Skan ggc_free (x); 18590075Sobrien 186117395Skan return r; 18790075Sobrien} 18890075Sobrien 189117395Skan/* Like ggc_alloc_cleared, but performs a multiplication. */ 19090075Sobrienvoid * 191132718Skanggc_calloc (size_t s1, size_t s2) 19290075Sobrien{ 193117395Skan return ggc_alloc_cleared (s1 * s2); 19490075Sobrien} 19590075Sobrien 196132718Skan/* These are for splay_tree_new_ggc. */ 197132718Skanvoid * 198132718Skanggc_splay_alloc (int sz, void *nl) 199132718Skan{ 200169689Skan gcc_assert (!nl); 201132718Skan return ggc_alloc (sz); 202132718Skan} 203132718Skan 204132718Skanvoid 205132718Skanggc_splay_dont_free (void * x ATTRIBUTE_UNUSED, void *nl) 206132718Skan{ 207169689Skan gcc_assert (!nl); 208132718Skan} 209132718Skan 21090075Sobrien/* Print statistics that are independent of the collector in use. */ 21190075Sobrien#define SCALE(x) ((unsigned long) ((x) < 1024*10 \ 21290075Sobrien ? (x) \ 21390075Sobrien : ((x) < 1024*1024*10 \ 21490075Sobrien ? (x) / 1024 \ 21590075Sobrien : (x) / (1024*1024)))) 21690075Sobrien#define LABEL(x) ((x) < 1024*10 ? ' ' : ((x) < 1024*1024*10 ? 'k' : 'M')) 21790075Sobrien 21890075Sobrienvoid 219132718Skanggc_print_common_statistics (FILE *stream ATTRIBUTE_UNUSED, 220132718Skan ggc_statistics *stats) 22190075Sobrien{ 22290075Sobrien /* Set the pointer so that during collection we will actually gather 22390075Sobrien the statistics. */ 22490075Sobrien ggc_stats = stats; 22590075Sobrien 22690075Sobrien /* Then do one collection to fill in the statistics. */ 22790075Sobrien ggc_collect (); 22890075Sobrien 229132718Skan /* At present, we don't really gather any interesting statistics. */ 230132718Skan 231132718Skan /* Don't gather statistics any more. */ 232132718Skan ggc_stats = NULL; 233132718Skan} 234132718Skan 235132718Skan/* Functions for saving and restoring GCable memory to disk. */ 236132718Skan 237132718Skanstatic htab_t saving_htab; 238132718Skan 239132718Skanstruct ptr_data 240132718Skan{ 241132718Skan void *obj; 242132718Skan void *note_ptr_cookie; 243132718Skan gt_note_pointers note_ptr_fn; 244132718Skan gt_handle_reorder reorder_fn; 245132718Skan size_t size; 246132718Skan void *new_addr; 247169689Skan enum gt_types_enum type; 248132718Skan}; 249132718Skan 250132718Skan#define POINTER_HASH(x) (hashval_t)((long)x >> 3) 251132718Skan 252132718Skan/* Register an object in the hash table. */ 253132718Skan 254132718Skanint 255132718Skangt_pch_note_object (void *obj, void *note_ptr_cookie, 256169689Skan gt_note_pointers note_ptr_fn, 257169689Skan enum gt_types_enum type) 258132718Skan{ 259132718Skan struct ptr_data **slot; 260132718Skan 261132718Skan if (obj == NULL || obj == (void *) 1) 262132718Skan return 0; 263132718Skan 264132718Skan slot = (struct ptr_data **) 265132718Skan htab_find_slot_with_hash (saving_htab, obj, POINTER_HASH (obj), 266132718Skan INSERT); 267132718Skan if (*slot != NULL) 26890075Sobrien { 269169689Skan gcc_assert ((*slot)->note_ptr_fn == note_ptr_fn 270169689Skan && (*slot)->note_ptr_cookie == note_ptr_cookie); 271132718Skan return 0; 27290075Sobrien } 273132718Skan 274132718Skan *slot = xcalloc (sizeof (struct ptr_data), 1); 275132718Skan (*slot)->obj = obj; 276132718Skan (*slot)->note_ptr_fn = note_ptr_fn; 277132718Skan (*slot)->note_ptr_cookie = note_ptr_cookie; 278132718Skan if (note_ptr_fn == gt_pch_p_S) 279132718Skan (*slot)->size = strlen (obj) + 1; 280132718Skan else 281132718Skan (*slot)->size = ggc_get_size (obj); 282169689Skan (*slot)->type = type; 283132718Skan return 1; 284132718Skan} 285132718Skan 286132718Skan/* Register an object in the hash table. */ 287132718Skan 288132718Skanvoid 289132718Skangt_pch_note_reorder (void *obj, void *note_ptr_cookie, 290132718Skan gt_handle_reorder reorder_fn) 291132718Skan{ 292132718Skan struct ptr_data *data; 293132718Skan 294132718Skan if (obj == NULL || obj == (void *) 1) 295132718Skan return; 296132718Skan 297132718Skan data = htab_find_with_hash (saving_htab, obj, POINTER_HASH (obj)); 298169689Skan gcc_assert (data && data->note_ptr_cookie == note_ptr_cookie); 299132718Skan 300132718Skan data->reorder_fn = reorder_fn; 301132718Skan} 302132718Skan 303132718Skan/* Hash and equality functions for saving_htab, callbacks for htab_create. */ 304132718Skan 305132718Skanstatic hashval_t 306132718Skansaving_htab_hash (const void *p) 307132718Skan{ 308132718Skan return POINTER_HASH (((struct ptr_data *)p)->obj); 309132718Skan} 310132718Skan 311132718Skanstatic int 312132718Skansaving_htab_eq (const void *p1, const void *p2) 313132718Skan{ 314132718Skan return ((struct ptr_data *)p1)->obj == p2; 315132718Skan} 316132718Skan 317132718Skan/* Handy state for the traversal functions. */ 318132718Skan 319132718Skanstruct traversal_state 320132718Skan{ 321132718Skan FILE *f; 322132718Skan struct ggc_pch_data *d; 323132718Skan size_t count; 324132718Skan struct ptr_data **ptrs; 325132718Skan size_t ptrs_i; 326132718Skan}; 327132718Skan 328132718Skan/* Callbacks for htab_traverse. */ 329132718Skan 330132718Skanstatic int 331132718Skancall_count (void **slot, void *state_p) 332132718Skan{ 333132718Skan struct ptr_data *d = (struct ptr_data *)*slot; 334132718Skan struct traversal_state *state = (struct traversal_state *)state_p; 335132718Skan 336169689Skan ggc_pch_count_object (state->d, d->obj, d->size, 337169689Skan d->note_ptr_fn == gt_pch_p_S, 338169689Skan d->type); 339132718Skan state->count++; 340132718Skan return 1; 341132718Skan} 342132718Skan 343132718Skanstatic int 344132718Skancall_alloc (void **slot, void *state_p) 345132718Skan{ 346132718Skan struct ptr_data *d = (struct ptr_data *)*slot; 347132718Skan struct traversal_state *state = (struct traversal_state *)state_p; 348132718Skan 349169689Skan d->new_addr = ggc_pch_alloc_object (state->d, d->obj, d->size, 350169689Skan d->note_ptr_fn == gt_pch_p_S, 351169689Skan d->type); 352132718Skan state->ptrs[state->ptrs_i++] = d; 353132718Skan return 1; 354132718Skan} 355132718Skan 356132718Skan/* Callback for qsort. */ 357132718Skan 358132718Skanstatic int 359132718Skancompare_ptr_data (const void *p1_p, const void *p2_p) 360132718Skan{ 361132718Skan struct ptr_data *p1 = *(struct ptr_data *const *)p1_p; 362132718Skan struct ptr_data *p2 = *(struct ptr_data *const *)p2_p; 363132718Skan return (((size_t)p1->new_addr > (size_t)p2->new_addr) 364132718Skan - ((size_t)p1->new_addr < (size_t)p2->new_addr)); 365132718Skan} 366132718Skan 367132718Skan/* Callbacks for note_ptr_fn. */ 368132718Skan 369132718Skanstatic void 370132718Skanrelocate_ptrs (void *ptr_p, void *state_p) 371132718Skan{ 372132718Skan void **ptr = (void **)ptr_p; 373132718Skan struct traversal_state *state ATTRIBUTE_UNUSED 374132718Skan = (struct traversal_state *)state_p; 375132718Skan struct ptr_data *result; 376132718Skan 377132718Skan if (*ptr == NULL || *ptr == (void *)1) 378132718Skan return; 379132718Skan 380132718Skan result = htab_find_with_hash (saving_htab, *ptr, POINTER_HASH (*ptr)); 381169689Skan gcc_assert (result); 382132718Skan *ptr = result->new_addr; 383132718Skan} 384132718Skan 385132718Skan/* Write out, after relocation, the pointers in TAB. */ 386132718Skanstatic void 387132718Skanwrite_pch_globals (const struct ggc_root_tab * const *tab, 388132718Skan struct traversal_state *state) 389132718Skan{ 390132718Skan const struct ggc_root_tab *const *rt; 391132718Skan const struct ggc_root_tab *rti; 392132718Skan size_t i; 393132718Skan 394132718Skan for (rt = tab; *rt; rt++) 395132718Skan for (rti = *rt; rti->base != NULL; rti++) 396132718Skan for (i = 0; i < rti->nelt; i++) 397132718Skan { 398132718Skan void *ptr = *(void **)((char *)rti->base + rti->stride * i); 399132718Skan struct ptr_data *new_ptr; 400132718Skan if (ptr == NULL || ptr == (void *)1) 401132718Skan { 402132718Skan if (fwrite (&ptr, sizeof (void *), 1, state->f) 403132718Skan != 1) 404132718Skan fatal_error ("can't write PCH file: %m"); 405132718Skan } 406132718Skan else 407132718Skan { 408132718Skan new_ptr = htab_find_with_hash (saving_htab, ptr, 409132718Skan POINTER_HASH (ptr)); 410132718Skan if (fwrite (&new_ptr->new_addr, sizeof (void *), 1, state->f) 411132718Skan != 1) 412132718Skan fatal_error ("can't write PCH file: %m"); 413132718Skan } 414132718Skan } 415132718Skan} 416132718Skan 417132718Skan/* Hold the information we need to mmap the file back in. */ 418132718Skan 419132718Skanstruct mmap_info 420132718Skan{ 421132718Skan size_t offset; 422132718Skan size_t size; 423132718Skan void *preferred_base; 424132718Skan}; 425132718Skan 426132718Skan/* Write out the state of the compiler to F. */ 427132718Skan 428132718Skanvoid 429132718Skangt_pch_save (FILE *f) 430132718Skan{ 431132718Skan const struct ggc_root_tab *const *rt; 432132718Skan const struct ggc_root_tab *rti; 433132718Skan size_t i; 434132718Skan struct traversal_state state; 435132718Skan char *this_object = NULL; 436132718Skan size_t this_object_size = 0; 437132718Skan struct mmap_info mmi; 438169689Skan const size_t mmap_offset_alignment = host_hooks.gt_pch_alloc_granularity(); 439132718Skan 440132718Skan gt_pch_save_stringpool (); 441132718Skan 442132718Skan saving_htab = htab_create (50000, saving_htab_hash, saving_htab_eq, free); 443132718Skan 444132718Skan for (rt = gt_ggc_rtab; *rt; rt++) 445132718Skan for (rti = *rt; rti->base != NULL; rti++) 446132718Skan for (i = 0; i < rti->nelt; i++) 447132718Skan (*rti->pchw)(*(void **)((char *)rti->base + rti->stride * i)); 448132718Skan 449132718Skan for (rt = gt_pch_cache_rtab; *rt; rt++) 450132718Skan for (rti = *rt; rti->base != NULL; rti++) 451132718Skan for (i = 0; i < rti->nelt; i++) 452132718Skan (*rti->pchw)(*(void **)((char *)rti->base + rti->stride * i)); 453132718Skan 454132718Skan /* Prepare the objects for writing, determine addresses and such. */ 455132718Skan state.f = f; 456132718Skan state.d = init_ggc_pch(); 457132718Skan state.count = 0; 458132718Skan htab_traverse (saving_htab, call_count, &state); 459132718Skan 460132718Skan mmi.size = ggc_pch_total_size (state.d); 461132718Skan 462132718Skan /* Try to arrange things so that no relocation is necessary, but 463132718Skan don't try very hard. On most platforms, this will always work, 464132718Skan and on the rest it's a lot of work to do better. 465132718Skan (The extra work goes in HOST_HOOKS_GT_PCH_GET_ADDRESS and 466132718Skan HOST_HOOKS_GT_PCH_USE_ADDRESS.) */ 467161651Skan mmi.preferred_base = host_hooks.gt_pch_get_address (mmi.size, fileno (f)); 468132718Skan 469132718Skan ggc_pch_this_base (state.d, mmi.preferred_base); 47090075Sobrien 471169689Skan state.ptrs = XNEWVEC (struct ptr_data *, state.count); 472132718Skan state.ptrs_i = 0; 473132718Skan htab_traverse (saving_htab, call_alloc, &state); 474132718Skan qsort (state.ptrs, state.count, sizeof (*state.ptrs), compare_ptr_data); 47590075Sobrien 476132718Skan /* Write out all the scalar variables. */ 477132718Skan for (rt = gt_pch_scalar_rtab; *rt; rt++) 478132718Skan for (rti = *rt; rti->base != NULL; rti++) 479132718Skan if (fwrite (rti->base, rti->stride, 1, f) != 1) 480132718Skan fatal_error ("can't write PCH file: %m"); 481132718Skan 482132718Skan /* Write out all the global pointers, after translation. */ 483132718Skan write_pch_globals (gt_ggc_rtab, &state); 484132718Skan write_pch_globals (gt_pch_cache_rtab, &state); 485132718Skan 486169689Skan /* Pad the PCH file so that the mmapped area starts on an allocation 487169689Skan granularity (usually page) boundary. */ 488132718Skan { 489132718Skan long o; 490132718Skan o = ftell (state.f) + sizeof (mmi); 491132718Skan if (o == -1) 492132718Skan fatal_error ("can't get position in PCH file: %m"); 493169689Skan mmi.offset = mmap_offset_alignment - o % mmap_offset_alignment; 494169689Skan if (mmi.offset == mmap_offset_alignment) 495132718Skan mmi.offset = 0; 496132718Skan mmi.offset += o; 497132718Skan } 498132718Skan if (fwrite (&mmi, sizeof (mmi), 1, state.f) != 1) 499132718Skan fatal_error ("can't write PCH file: %m"); 500132718Skan if (mmi.offset != 0 501132718Skan && fseek (state.f, mmi.offset, SEEK_SET) != 0) 502132718Skan fatal_error ("can't write padding to PCH file: %m"); 503132718Skan 504169689Skan ggc_pch_prepare_write (state.d, state.f); 505169689Skan 506132718Skan /* Actually write out the objects. */ 507132718Skan for (i = 0; i < state.count; i++) 508132718Skan { 509132718Skan if (this_object_size < state.ptrs[i]->size) 510132718Skan { 511132718Skan this_object_size = state.ptrs[i]->size; 512132718Skan this_object = xrealloc (this_object, this_object_size); 513132718Skan } 514132718Skan memcpy (this_object, state.ptrs[i]->obj, state.ptrs[i]->size); 515132718Skan if (state.ptrs[i]->reorder_fn != NULL) 516132718Skan state.ptrs[i]->reorder_fn (state.ptrs[i]->obj, 517132718Skan state.ptrs[i]->note_ptr_cookie, 518132718Skan relocate_ptrs, &state); 519132718Skan state.ptrs[i]->note_ptr_fn (state.ptrs[i]->obj, 520132718Skan state.ptrs[i]->note_ptr_cookie, 521132718Skan relocate_ptrs, &state); 522132718Skan ggc_pch_write_object (state.d, state.f, state.ptrs[i]->obj, 523161651Skan state.ptrs[i]->new_addr, state.ptrs[i]->size, 524161651Skan state.ptrs[i]->note_ptr_fn == gt_pch_p_S); 525132718Skan if (state.ptrs[i]->note_ptr_fn != gt_pch_p_S) 526132718Skan memcpy (state.ptrs[i]->obj, this_object, state.ptrs[i]->size); 527132718Skan } 528132718Skan ggc_pch_finish (state.d, state.f); 529132718Skan gt_pch_fixup_stringpool (); 530132718Skan 531132718Skan free (state.ptrs); 532132718Skan htab_delete (saving_htab); 53390075Sobrien} 534117395Skan 535132718Skan/* Read the state of the compiler back in from F. */ 536132718Skan 537132718Skanvoid 538132718Skangt_pch_restore (FILE *f) 539132718Skan{ 540132718Skan const struct ggc_root_tab *const *rt; 541132718Skan const struct ggc_root_tab *rti; 542132718Skan size_t i; 543132718Skan struct mmap_info mmi; 544161651Skan int result; 545132718Skan 546132718Skan /* Delete any deletable objects. This makes ggc_pch_read much 547132718Skan faster, as it can be sure that no GCable objects remain other 548132718Skan than the ones just read in. */ 549132718Skan for (rt = gt_ggc_deletable_rtab; *rt; rt++) 550132718Skan for (rti = *rt; rti->base != NULL; rti++) 551132718Skan memset (rti->base, 0, rti->stride); 552132718Skan 553132718Skan /* Read in all the scalar variables. */ 554132718Skan for (rt = gt_pch_scalar_rtab; *rt; rt++) 555132718Skan for (rti = *rt; rti->base != NULL; rti++) 556132718Skan if (fread (rti->base, rti->stride, 1, f) != 1) 557132718Skan fatal_error ("can't read PCH file: %m"); 558132718Skan 559132718Skan /* Read in all the global pointers, in 6 easy loops. */ 560132718Skan for (rt = gt_ggc_rtab; *rt; rt++) 561132718Skan for (rti = *rt; rti->base != NULL; rti++) 562132718Skan for (i = 0; i < rti->nelt; i++) 563132718Skan if (fread ((char *)rti->base + rti->stride * i, 564132718Skan sizeof (void *), 1, f) != 1) 565132718Skan fatal_error ("can't read PCH file: %m"); 566132718Skan 567132718Skan for (rt = gt_pch_cache_rtab; *rt; rt++) 568132718Skan for (rti = *rt; rti->base != NULL; rti++) 569132718Skan for (i = 0; i < rti->nelt; i++) 570132718Skan if (fread ((char *)rti->base + rti->stride * i, 571132718Skan sizeof (void *), 1, f) != 1) 572132718Skan fatal_error ("can't read PCH file: %m"); 573132718Skan 574132718Skan if (fread (&mmi, sizeof (mmi), 1, f) != 1) 575132718Skan fatal_error ("can't read PCH file: %m"); 576132718Skan 577161651Skan result = host_hooks.gt_pch_use_address (mmi.preferred_base, mmi.size, 578161651Skan fileno (f), mmi.offset); 579161651Skan if (result < 0) 580161651Skan fatal_error ("had to relocate PCH"); 581161651Skan if (result == 0) 582132718Skan { 583132718Skan if (fseek (f, mmi.offset, SEEK_SET) != 0 584161651Skan || fread (mmi.preferred_base, mmi.size, 1, f) != 1) 585132718Skan fatal_error ("can't read PCH file: %m"); 586132718Skan } 587132718Skan else if (fseek (f, mmi.offset + mmi.size, SEEK_SET) != 0) 588132718Skan fatal_error ("can't read PCH file: %m"); 589132718Skan 590161651Skan ggc_pch_read (f, mmi.preferred_base); 591132718Skan 592161651Skan gt_pch_restore_stringpool (); 593161651Skan} 594132718Skan 595161651Skan/* Default version of HOST_HOOKS_GT_PCH_GET_ADDRESS when mmap is not present. 596161651Skan Select no address whatsoever, and let gt_pch_save choose what it will with 597161651Skan malloc, presumably. */ 598132718Skan 599161651Skanvoid * 600161651Skandefault_gt_pch_get_address (size_t size ATTRIBUTE_UNUSED, 601161651Skan int fd ATTRIBUTE_UNUSED) 602161651Skan{ 603161651Skan return NULL; 604161651Skan} 605132718Skan 606161651Skan/* Default version of HOST_HOOKS_GT_PCH_USE_ADDRESS when mmap is not present. 607161651Skan Allocate SIZE bytes with malloc. Return 0 if the address we got is the 608161651Skan same as base, indicating that the memory has been allocated but needs to 609161651Skan be read in from the file. Return -1 if the address differs, to relocation 610161651Skan of the PCH file would be required. */ 611161651Skan 612161651Skanint 613161651Skandefault_gt_pch_use_address (void *base, size_t size, int fd ATTRIBUTE_UNUSED, 614161651Skan size_t offset ATTRIBUTE_UNUSED) 615161651Skan{ 616161651Skan void *addr = xmalloc (size); 617161651Skan return (addr == base) - 1; 618132718Skan} 619132718Skan 620169689Skan/* Default version of HOST_HOOKS_GT_PCH_GET_ADDRESS. Return the 621169689Skan alignment required for allocating virtual memory. Usually this is the 622169689Skan same as pagesize. */ 623169689Skan 624169689Skansize_t 625169689Skandefault_gt_pch_alloc_granularity (void) 626169689Skan{ 627169689Skan return getpagesize(); 628169689Skan} 629169689Skan 630161651Skan#if HAVE_MMAP_FILE 631161651Skan/* Default version of HOST_HOOKS_GT_PCH_GET_ADDRESS when mmap is present. 632161651Skan We temporarily allocate SIZE bytes, and let the kernel place the data 633169689Skan wherever it will. If it worked, that's our spot, if not we're likely 634161651Skan to be in trouble. */ 635169689Skan 636161651Skanvoid * 637161651Skanmmap_gt_pch_get_address (size_t size, int fd) 638161651Skan{ 639161651Skan void *ret; 640169689Skan 641161651Skan ret = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); 642161651Skan if (ret == (void *) MAP_FAILED) 643161651Skan ret = NULL; 644161651Skan else 645161651Skan munmap (ret, size); 646169689Skan 647161651Skan return ret; 648161651Skan} 649161651Skan 650161651Skan/* Default version of HOST_HOOKS_GT_PCH_USE_ADDRESS when mmap is present. 651161651Skan Map SIZE bytes of FD+OFFSET at BASE. Return 1 if we succeeded at 652161651Skan mapping the data at BASE, -1 if we couldn't. 653169689Skan 654161651Skan This version assumes that the kernel honors the START operand of mmap 655161651Skan even without MAP_FIXED if START through START+SIZE are not currently 656161651Skan mapped with something. */ 657169689Skan 658161651Skanint 659161651Skanmmap_gt_pch_use_address (void *base, size_t size, int fd, size_t offset) 660161651Skan{ 661161651Skan void *addr; 662169689Skan 663161651Skan /* We're called with size == 0 if we're not planning to load a PCH 664161651Skan file at all. This allows the hook to free any static space that 665161651Skan we might have allocated at link time. */ 666161651Skan if (size == 0) 667161651Skan return -1; 668169689Skan 669161651Skan addr = mmap (base, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, 670161651Skan fd, offset); 671161651Skan 672161651Skan return addr == base ? 1 : -1; 673169689Skan} 674161651Skan#endif /* HAVE_MMAP_FILE */ 675161651Skan 676169689Skan/* Modify the bound based on rlimits. */ 677117395Skanstatic double 678132718Skanggc_rlimit_bound (double limit) 679117395Skan{ 680117395Skan#if defined(HAVE_GETRLIMIT) 681117395Skan struct rlimit rlim; 682169689Skan# if defined (RLIMIT_AS) 683169689Skan /* RLIMIT_AS is what POSIX says is the limit on mmap. Presumably 684169689Skan any OS which has RLIMIT_AS also has a working mmap that GCC will use. */ 685169689Skan if (getrlimit (RLIMIT_AS, &rlim) == 0 686117395Skan && rlim.rlim_cur != (rlim_t) RLIM_INFINITY 687117395Skan && rlim.rlim_cur < limit) 688117395Skan limit = rlim.rlim_cur; 689169689Skan# elif defined (RLIMIT_DATA) 690169689Skan /* ... but some older OSs bound mmap based on RLIMIT_DATA, or we 691169689Skan might be on an OS that has a broken mmap. (Others don't bound 692169689Skan mmap at all, apparently.) */ 693117395Skan if (getrlimit (RLIMIT_DATA, &rlim) == 0 694117395Skan && rlim.rlim_cur != (rlim_t) RLIM_INFINITY 695169689Skan && rlim.rlim_cur < limit 696169689Skan /* Darwin has this horribly bogus default setting of 697169689Skan RLIMIT_DATA, to 6144Kb. No-one notices because RLIMIT_DATA 698169689Skan appears to be ignored. Ignore such silliness. If a limit 699169689Skan this small was actually effective for mmap, GCC wouldn't even 700169689Skan start up. */ 701169689Skan && rlim.rlim_cur >= 8 * 1024 * 1024) 702117395Skan limit = rlim.rlim_cur; 703169689Skan# endif /* RLIMIT_AS or RLIMIT_DATA */ 704117395Skan#endif /* HAVE_GETRLIMIT */ 705117395Skan 706117395Skan return limit; 707117395Skan} 708117395Skan 709117395Skan/* Heuristic to set a default for GGC_MIN_EXPAND. */ 710117395Skanint 711132718Skanggc_min_expand_heuristic (void) 712117395Skan{ 713117395Skan double min_expand = physmem_total(); 714117395Skan 715117395Skan /* Adjust for rlimits. */ 716117395Skan min_expand = ggc_rlimit_bound (min_expand); 717132718Skan 718117395Skan /* The heuristic is a percentage equal to 30% + 70%*(RAM/1GB), yielding 719117395Skan a lower bound of 30% and an upper bound of 100% (when RAM >= 1GB). */ 720117395Skan min_expand /= 1024*1024*1024; 721117395Skan min_expand *= 70; 722117395Skan min_expand = MIN (min_expand, 70); 723117395Skan min_expand += 30; 724117395Skan 725117395Skan return min_expand; 726117395Skan} 727117395Skan 728117395Skan/* Heuristic to set a default for GGC_MIN_HEAPSIZE. */ 729117395Skanint 730132718Skanggc_min_heapsize_heuristic (void) 731117395Skan{ 732169689Skan double phys_kbytes = physmem_total(); 733169689Skan double limit_kbytes = ggc_rlimit_bound (phys_kbytes * 2); 734117395Skan 735169689Skan phys_kbytes /= 1024; /* Convert to Kbytes. */ 736169689Skan limit_kbytes /= 1024; 737117395Skan 738117395Skan /* The heuristic is RAM/8, with a lower bound of 4M and an upper 739117395Skan bound of 128M (when RAM >= 1GB). */ 740169689Skan phys_kbytes /= 8; 741117395Skan 742169689Skan#if defined(HAVE_GETRLIMIT) && defined (RLIMIT_RSS) 743169689Skan /* Try not to overrun the RSS limit while doing garbage collection. 744169689Skan The RSS limit is only advisory, so no margin is subtracted. */ 745169689Skan { 746169689Skan struct rlimit rlim; 747169689Skan if (getrlimit (RLIMIT_RSS, &rlim) == 0 748169689Skan && rlim.rlim_cur != (rlim_t) RLIM_INFINITY) 749169689Skan phys_kbytes = MIN (phys_kbytes, rlim.rlim_cur / 1024); 750169689Skan } 751169689Skan# endif 752169689Skan 753169689Skan /* Don't blindly run over our data limit; do GC at least when the 754169689Skan *next* GC would be within 16Mb of the limit. If GCC does hit the 755169689Skan data limit, compilation will fail, so this tries to be 756169689Skan conservative. */ 757169689Skan limit_kbytes = MAX (0, limit_kbytes - 16 * 1024); 758169689Skan limit_kbytes = (limit_kbytes * 100) / (110 + ggc_min_expand_heuristic()); 759169689Skan phys_kbytes = MIN (phys_kbytes, limit_kbytes); 760169689Skan 761169689Skan phys_kbytes = MAX (phys_kbytes, 4 * 1024); 762169689Skan phys_kbytes = MIN (phys_kbytes, 128 * 1024); 763169689Skan 764169689Skan return phys_kbytes; 765117395Skan} 766117395Skan 767117395Skanvoid 768132718Skaninit_ggc_heuristics (void) 769117395Skan{ 770132718Skan#if !defined ENABLE_GC_CHECKING && !defined ENABLE_GC_ALWAYS_COLLECT 771117395Skan set_param_value ("ggc-min-expand", ggc_min_expand_heuristic()); 772117395Skan set_param_value ("ggc-min-heapsize", ggc_min_heapsize_heuristic()); 773117395Skan#endif 774117395Skan} 775169689Skan 776169689Skan#ifdef GATHER_STATISTICS 777169689Skan 778169689Skan/* Datastructure used to store per-call-site statistics. */ 779169689Skanstruct loc_descriptor 780169689Skan{ 781169689Skan const char *file; 782169689Skan int line; 783169689Skan const char *function; 784169689Skan int times; 785169689Skan size_t allocated; 786169689Skan size_t overhead; 787169689Skan size_t freed; 788169689Skan size_t collected; 789169689Skan}; 790169689Skan 791169689Skan/* Hashtable used for statistics. */ 792169689Skanstatic htab_t loc_hash; 793169689Skan 794169689Skan/* Hash table helpers functions. */ 795169689Skanstatic hashval_t 796169689Skanhash_descriptor (const void *p) 797169689Skan{ 798169689Skan const struct loc_descriptor *d = p; 799169689Skan 800169689Skan return htab_hash_pointer (d->function) | d->line; 801169689Skan} 802169689Skan 803169689Skanstatic int 804169689Skaneq_descriptor (const void *p1, const void *p2) 805169689Skan{ 806169689Skan const struct loc_descriptor *d = p1; 807169689Skan const struct loc_descriptor *d2 = p2; 808169689Skan 809169689Skan return (d->file == d2->file && d->line == d2->line 810169689Skan && d->function == d2->function); 811169689Skan} 812169689Skan 813169689Skan/* Hashtable converting address of allocated field to loc descriptor. */ 814169689Skanstatic htab_t ptr_hash; 815169689Skanstruct ptr_hash_entry 816169689Skan{ 817169689Skan void *ptr; 818169689Skan struct loc_descriptor *loc; 819169689Skan size_t size; 820169689Skan}; 821169689Skan 822169689Skan/* Hash table helpers functions. */ 823169689Skanstatic hashval_t 824169689Skanhash_ptr (const void *p) 825169689Skan{ 826169689Skan const struct ptr_hash_entry *d = p; 827169689Skan 828169689Skan return htab_hash_pointer (d->ptr); 829169689Skan} 830169689Skan 831169689Skanstatic int 832169689Skaneq_ptr (const void *p1, const void *p2) 833169689Skan{ 834169689Skan const struct ptr_hash_entry *p = p1; 835169689Skan 836169689Skan return (p->ptr == p2); 837169689Skan} 838169689Skan 839169689Skan/* Return descriptor for given call site, create new one if needed. */ 840169689Skanstatic struct loc_descriptor * 841169689Skanloc_descriptor (const char *name, int line, const char *function) 842169689Skan{ 843169689Skan struct loc_descriptor loc; 844169689Skan struct loc_descriptor **slot; 845169689Skan 846169689Skan loc.file = name; 847169689Skan loc.line = line; 848169689Skan loc.function = function; 849169689Skan if (!loc_hash) 850169689Skan loc_hash = htab_create (10, hash_descriptor, eq_descriptor, NULL); 851169689Skan 852169689Skan slot = (struct loc_descriptor **) htab_find_slot (loc_hash, &loc, 1); 853169689Skan if (*slot) 854169689Skan return *slot; 855169689Skan *slot = xcalloc (sizeof (**slot), 1); 856169689Skan (*slot)->file = name; 857169689Skan (*slot)->line = line; 858169689Skan (*slot)->function = function; 859169689Skan return *slot; 860169689Skan} 861169689Skan 862169689Skan/* Record ALLOCATED and OVERHEAD bytes to descriptor NAME:LINE (FUNCTION). */ 863169689Skanvoid 864169689Skanggc_record_overhead (size_t allocated, size_t overhead, void *ptr, 865169689Skan const char *name, int line, const char *function) 866169689Skan{ 867169689Skan struct loc_descriptor *loc = loc_descriptor (name, line, function); 868169689Skan struct ptr_hash_entry *p = XNEW (struct ptr_hash_entry); 869169689Skan PTR *slot; 870169689Skan 871169689Skan p->ptr = ptr; 872169689Skan p->loc = loc; 873169689Skan p->size = allocated + overhead; 874169689Skan if (!ptr_hash) 875169689Skan ptr_hash = htab_create (10, hash_ptr, eq_ptr, NULL); 876169689Skan slot = htab_find_slot_with_hash (ptr_hash, ptr, htab_hash_pointer (ptr), INSERT); 877169689Skan gcc_assert (!*slot); 878169689Skan *slot = p; 879169689Skan 880169689Skan loc->times++; 881169689Skan loc->allocated+=allocated; 882169689Skan loc->overhead+=overhead; 883169689Skan} 884169689Skan 885169689Skan/* Helper function for prune_overhead_list. See if SLOT is still marked and 886169689Skan remove it from hashtable if it is not. */ 887169689Skanstatic int 888169689Skanggc_prune_ptr (void **slot, void *b ATTRIBUTE_UNUSED) 889169689Skan{ 890169689Skan struct ptr_hash_entry *p = *slot; 891169689Skan if (!ggc_marked_p (p->ptr)) 892169689Skan { 893169689Skan p->loc->collected += p->size; 894169689Skan htab_clear_slot (ptr_hash, slot); 895169689Skan free (p); 896169689Skan } 897169689Skan return 1; 898169689Skan} 899169689Skan 900169689Skan/* After live values has been marked, walk all recorded pointers and see if 901169689Skan they are still live. */ 902169689Skanvoid 903169689Skanggc_prune_overhead_list (void) 904169689Skan{ 905169689Skan htab_traverse (ptr_hash, ggc_prune_ptr, NULL); 906169689Skan} 907169689Skan 908169689Skan/* Notice that the pointer has been freed. */ 909169689Skanvoid 910169689Skanggc_free_overhead (void *ptr) 911169689Skan{ 912169689Skan PTR *slot = htab_find_slot_with_hash (ptr_hash, ptr, htab_hash_pointer (ptr), 913169689Skan NO_INSERT); 914169689Skan struct ptr_hash_entry *p = *slot; 915169689Skan p->loc->freed += p->size; 916169689Skan htab_clear_slot (ptr_hash, slot); 917169689Skan free (p); 918169689Skan} 919169689Skan 920169689Skan/* Helper for qsort; sort descriptors by amount of memory consumed. */ 921169689Skanstatic int 922169689Skancmp_statistic (const void *loc1, const void *loc2) 923169689Skan{ 924169689Skan struct loc_descriptor *l1 = *(struct loc_descriptor **) loc1; 925169689Skan struct loc_descriptor *l2 = *(struct loc_descriptor **) loc2; 926169689Skan return ((l1->allocated + l1->overhead - l1->freed) - 927169689Skan (l2->allocated + l2->overhead - l2->freed)); 928169689Skan} 929169689Skan 930169689Skan/* Collect array of the descriptors from hashtable. */ 931169689Skanstruct loc_descriptor **loc_array; 932169689Skanstatic int 933169689Skanadd_statistics (void **slot, void *b) 934169689Skan{ 935169689Skan int *n = (int *)b; 936169689Skan loc_array[*n] = (struct loc_descriptor *) *slot; 937169689Skan (*n)++; 938169689Skan return 1; 939169689Skan} 940169689Skan 941169689Skan/* Dump per-site memory statistics. */ 942169689Skan#endif 943169689Skanvoid 944169689Skandump_ggc_loc_statistics (void) 945169689Skan{ 946169689Skan#ifdef GATHER_STATISTICS 947169689Skan int nentries = 0; 948169689Skan char s[4096]; 949169689Skan size_t collected = 0, freed = 0, allocated = 0, overhead = 0, times = 0; 950169689Skan int i; 951169689Skan 952169689Skan ggc_force_collect = true; 953169689Skan ggc_collect (); 954169689Skan 955169689Skan loc_array = xcalloc (sizeof (*loc_array), loc_hash->n_elements); 956169689Skan fprintf (stderr, "-------------------------------------------------------\n"); 957169689Skan fprintf (stderr, "\n%-48s %10s %10s %10s %10s %10s\n", 958169689Skan "source location", "Garbage", "Freed", "Leak", "Overhead", "Times"); 959169689Skan fprintf (stderr, "-------------------------------------------------------\n"); 960169689Skan htab_traverse (loc_hash, add_statistics, &nentries); 961169689Skan qsort (loc_array, nentries, sizeof (*loc_array), cmp_statistic); 962169689Skan for (i = 0; i < nentries; i++) 963169689Skan { 964169689Skan struct loc_descriptor *d = loc_array[i]; 965169689Skan allocated += d->allocated; 966169689Skan times += d->times; 967169689Skan freed += d->freed; 968169689Skan collected += d->collected; 969169689Skan overhead += d->overhead; 970169689Skan } 971169689Skan for (i = 0; i < nentries; i++) 972169689Skan { 973169689Skan struct loc_descriptor *d = loc_array[i]; 974169689Skan if (d->allocated) 975169689Skan { 976169689Skan const char *s1 = d->file; 977169689Skan const char *s2; 978169689Skan while ((s2 = strstr (s1, "gcc/"))) 979169689Skan s1 = s2 + 4; 980169689Skan sprintf (s, "%s:%i (%s)", s1, d->line, d->function); 981169689Skan s[48] = 0; 982169689Skan fprintf (stderr, "%-48s %10li:%4.1f%% %10li:%4.1f%% %10li:%4.1f%% %10li:%4.1f%% %10li\n", s, 983169689Skan (long)d->collected, 984169689Skan (d->collected) * 100.0 / collected, 985169689Skan (long)d->freed, 986169689Skan (d->freed) * 100.0 / freed, 987169689Skan (long)(d->allocated + d->overhead - d->freed - d->collected), 988169689Skan (d->allocated + d->overhead - d->freed - d->collected) * 100.0 989169689Skan / (allocated + overhead - freed - collected), 990169689Skan (long)d->overhead, 991169689Skan d->overhead * 100.0 / overhead, 992169689Skan (long)d->times); 993169689Skan } 994169689Skan } 995169689Skan fprintf (stderr, "%-48s %10ld %10ld %10ld %10ld %10ld\n", 996169689Skan "Total", (long)collected, (long)freed, 997169689Skan (long)(allocated + overhead - freed - collected), (long)overhead, 998169689Skan (long)times); 999169689Skan fprintf (stderr, "%-48s %10s %10s %10s %10s %10s\n", 1000169689Skan "source location", "Garbage", "Freed", "Leak", "Overhead", "Times"); 1001169689Skan fprintf (stderr, "-------------------------------------------------------\n"); 1002169689Skan#endif 1003169689Skan} 1004