00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "config.h"
00023 #include "system.h"
00024 #include "coretypes.h"
00025 #include "tm.h"
00026 #include "tree.h"
00027 #include "rtl.h"
00028 #include "tm_p.h"
00029 #include "toplev.h"
00030 #include "flags.h"
00031 #include "ggc.h"
00032 #include "timevar.h"
00033 #include "params.h"
00034 #include "tree-flow.h"
00035 #ifdef ENABLE_VALGRIND_CHECKING
00036 # ifdef HAVE_VALGRIND_MEMCHECK_H
00037 # include <valgrind/memcheck.h>
00038 # elif defined HAVE_MEMCHECK_H
00039 # include <memcheck.h>
00040 # else
00041 # include <valgrind.h>
00042 # endif
00043 #else
00044
00045 #define VALGRIND_DISCARD(x)
00046 #endif
00047
00048
00049
00050 #ifdef HAVE_MMAP_ANON
00051 # undef HAVE_MMAP_DEV_ZERO
00052
00053 # include <sys/mman.h>
00054 # ifndef MAP_FAILED
00055 # define MAP_FAILED -1
00056 # endif
00057 # if !defined (MAP_ANONYMOUS) && defined (MAP_ANON)
00058 # define MAP_ANONYMOUS MAP_ANON
00059 # endif
00060 # define USING_MMAP
00061
00062 #endif
00063
00064 #ifdef HAVE_MMAP_DEV_ZERO
00065
00066 # include <sys/mman.h>
00067 # ifndef MAP_FAILED
00068 # define MAP_FAILED -1
00069 # endif
00070 # define USING_MMAP
00071
00072 #endif
00073
00074 #ifndef USING_MMAP
00075 #define USING_MALLOC_PAGE_GROUPS
00076 #endif
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113 #define GGC_DEBUG_LEVEL (0)
00114
00115 #ifndef HOST_BITS_PER_PTR
00116 #define HOST_BITS_PER_PTR HOST_BITS_PER_LONG
00117 #endif
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142 #define PAGE_L1_BITS (8)
00143 #define PAGE_L2_BITS (32 - PAGE_L1_BITS - G.lg_pagesize)
00144 #define PAGE_L1_SIZE ((size_t) 1 << PAGE_L1_BITS)
00145 #define PAGE_L2_SIZE ((size_t) 1 << PAGE_L2_BITS)
00146
00147 #define LOOKUP_L1(p) \
00148 (((size_t) (p) >> (32 - PAGE_L1_BITS)) & ((1 << PAGE_L1_BITS) - 1))
00149
00150 #define LOOKUP_L2(p) \
00151 (((size_t) (p) >> G.lg_pagesize) & ((1 << PAGE_L2_BITS) - 1))
00152
00153
00154
00155 #define OBJECTS_PER_PAGE(ORDER) objects_per_page_table[ORDER]
00156
00157
00158 #define OBJECTS_IN_PAGE(P) ((P)->bytes / OBJECT_SIZE ((P)->order))
00159
00160
00161 #define OBJECT_SIZE(ORDER) object_size_table[ORDER]
00162
00163
00164
00165
00166
00167 #define DIV_MULT(ORDER) inverse_table[ORDER].mult
00168 #define DIV_SHIFT(ORDER) inverse_table[ORDER].shift
00169 #define OFFSET_TO_BIT(OFFSET, ORDER) \
00170 (((OFFSET) * DIV_MULT (ORDER)) >> DIV_SHIFT (ORDER))
00171
00172
00173
00174
00175 #define NUM_EXTRA_ORDERS ARRAY_SIZE (extra_order_size_table)
00176
00177 #define RTL_SIZE(NSLOTS) \
00178 (RTX_HDR_SIZE + (NSLOTS) * sizeof (rtunion))
00179
00180 #define TREE_EXP_SIZE(OPS) \
00181 (sizeof (struct tree_exp) + ((OPS) - 1) * sizeof (tree))
00182
00183
00184
00185
00186
00187 static const size_t extra_order_size_table[] = {
00188 sizeof (struct stmt_ann_d),
00189 sizeof (struct tree_decl),
00190 sizeof (struct tree_list),
00191 TREE_EXP_SIZE (2),
00192 RTL_SIZE (2),
00193 RTL_SIZE (9),
00194 };
00195
00196
00197
00198 #define NUM_ORDERS (HOST_BITS_PER_PTR + NUM_EXTRA_ORDERS)
00199
00200
00201
00202
00203
00204 struct max_alignment {
00205 char c;
00206 union {
00207 HOST_WIDEST_INT i;
00208 long double d;
00209 } u;
00210 };
00211
00212
00213
00214 #define MAX_ALIGNMENT (offsetof (struct max_alignment, u))
00215
00216
00217
00218
00219 #define ROUND_UP_VALUE(x, f) ((f) - 1 - ((f) - 1 + (x)) % (f))
00220
00221
00222
00223 #define ROUND_UP(x, f) (CEIL (x, f) * (f))
00224
00225
00226
00227 static unsigned objects_per_page_table[NUM_ORDERS];
00228
00229
00230
00231 static size_t object_size_table[NUM_ORDERS];
00232
00233
00234
00235
00236
00237 static struct
00238 {
00239 size_t mult;
00240 unsigned int shift;
00241 }
00242 inverse_table[NUM_ORDERS];
00243
00244
00245
00246 typedef struct page_entry
00247 {
00248
00249
00250 struct page_entry *next;
00251
00252
00253
00254
00255 struct page_entry *prev;
00256
00257
00258
00259 size_t bytes;
00260
00261
00262 char *page;
00263
00264 #ifdef USING_MALLOC_PAGE_GROUPS
00265
00266 struct page_group *group;
00267 #endif
00268
00269
00270
00271 unsigned long index_by_depth;
00272
00273
00274 unsigned short context_depth;
00275
00276
00277 unsigned short num_free_objects;
00278
00279
00280
00281 unsigned short next_bit_hint;
00282
00283
00284 unsigned char order;
00285
00286
00287
00288
00289 unsigned long in_use_p[1];
00290 } page_entry;
00291
00292 #ifdef USING_MALLOC_PAGE_GROUPS
00293
00294
00295 typedef struct page_group
00296 {
00297
00298 struct page_group *next;
00299
00300
00301 char *allocation;
00302
00303
00304 size_t alloc_size;
00305
00306
00307 unsigned int in_use;
00308 } page_group;
00309 #endif
00310
00311 #if HOST_BITS_PER_PTR <= 32
00312
00313
00314 typedef page_entry **page_table[PAGE_L1_SIZE];
00315
00316 #else
00317
00318
00319
00320
00321 typedef struct page_table_chain
00322 {
00323 struct page_table_chain *next;
00324 size_t high_bits;
00325 page_entry **table[PAGE_L1_SIZE];
00326 } *page_table;
00327
00328 #endif
00329
00330
00331 static struct globals
00332 {
00333
00334
00335
00336
00337 page_entry *pages[NUM_ORDERS];
00338
00339
00340
00341
00342 page_entry *page_tails[NUM_ORDERS];
00343
00344
00345 page_table lookup;
00346
00347
00348 size_t pagesize;
00349 size_t lg_pagesize;
00350
00351
00352 size_t allocated;
00353
00354
00355 size_t allocated_last_gc;
00356
00357
00358 size_t bytes_mapped;
00359
00360
00361 unsigned long context_depth_allocations;
00362
00363
00364 unsigned long context_depth_collections;
00365
00366
00367 unsigned short context_depth;
00368
00369
00370 #if defined (HAVE_MMAP_DEV_ZERO)
00371 int dev_zero_fd;
00372 #endif
00373
00374
00375 page_entry *free_pages;
00376
00377 #ifdef USING_MALLOC_PAGE_GROUPS
00378 page_group *page_groups;
00379 #endif
00380
00381
00382 FILE *debug_file;
00383
00384
00385 unsigned int depth_in_use;
00386
00387
00388 unsigned int depth_max;
00389
00390
00391
00392
00393 unsigned int *depth;
00394
00395
00396 unsigned int by_depth_in_use;
00397
00398
00399 unsigned int by_depth_max;
00400
00401
00402
00403
00404
00405
00406 page_entry **by_depth;
00407
00408
00409
00410
00411 unsigned long **save_in_use;
00412
00413 #ifdef ENABLE_GC_ALWAYS_COLLECT
00414
00415
00416 struct free_object
00417 {
00418 void *object;
00419 struct free_object *next;
00420 } *free_object_list;
00421 #endif
00422
00423 #ifdef GATHER_STATISTICS
00424 struct
00425 {
00426
00427 unsigned long long total_allocated;
00428
00429 unsigned long long total_overhead;
00430
00431
00432
00433
00434
00435 unsigned long long total_allocated_under32;
00436 unsigned long long total_overhead_under32;
00437
00438 unsigned long long total_allocated_under64;
00439 unsigned long long total_overhead_under64;
00440
00441 unsigned long long total_allocated_under128;
00442 unsigned long long total_overhead_under128;
00443
00444
00445 unsigned long long total_allocated_per_order[NUM_ORDERS];
00446
00447
00448 unsigned long long total_overhead_per_order[NUM_ORDERS];
00449 } stats;
00450 #endif
00451 } G;
00452
00453
00454
00455 #define BITMAP_SIZE(Num_objects) \
00456 (CEIL ((Num_objects), HOST_BITS_PER_LONG) * sizeof(long))
00457
00458
00459
00460
00461
00462
00463 #ifndef GGC_QUIRE_SIZE
00464 # ifdef USING_MMAP
00465 # define GGC_QUIRE_SIZE 256
00466 # else
00467 # define GGC_QUIRE_SIZE 16
00468 # endif
00469 #endif
00470
00471
00472 #define INITIAL_PTE_COUNT 128
00473
00474 static int ggc_allocated_p (const void *);
00475 static page_entry *lookup_page_table_entry (const void *);
00476 static void set_page_table_entry (void *, page_entry *);
00477 #ifdef USING_MMAP
00478 static char *alloc_anon (char *, size_t);
00479 #endif
00480 #ifdef USING_MALLOC_PAGE_GROUPS
00481 static size_t page_group_index (char *, char *);
00482 static void set_page_group_in_use (page_group *, char *);
00483 static void clear_page_group_in_use (page_group *, char *);
00484 #endif
00485 static struct page_entry * alloc_page (unsigned);
00486 static void free_page (struct page_entry *);
00487 static void release_pages (void);
00488 static void clear_marks (void);
00489 static void sweep_pages (void);
00490 static void ggc_recalculate_in_use_p (page_entry *);
00491 static void compute_inverse (unsigned);
00492 static inline void adjust_depth (void);
00493 static void move_ptes_to_front (int, int);
00494
00495 void debug_print_page_list (int);
00496 static void push_depth (unsigned int);
00497 static void push_by_depth (page_entry *, unsigned long *);
00498 struct alloc_zone *rtl_zone = NULL;
00499 struct alloc_zone *tree_zone = NULL;
00500 struct alloc_zone *garbage_zone = NULL;
00501
00502
00503
00504 inline static void
00505 push_depth (unsigned int i)
00506 {
00507 if (G.depth_in_use >= G.depth_max)
00508 {
00509 G.depth_max *= 2;
00510 G.depth = xrealloc (G.depth, G.depth_max * sizeof (unsigned int));
00511 }
00512 G.depth[G.depth_in_use++] = i;
00513 }
00514
00515
00516
00517 inline static void
00518 push_by_depth (page_entry *p, unsigned long *s)
00519 {
00520 if (G.by_depth_in_use >= G.by_depth_max)
00521 {
00522 G.by_depth_max *= 2;
00523 G.by_depth = xrealloc (G.by_depth,
00524 G.by_depth_max * sizeof (page_entry *));
00525 G.save_in_use = xrealloc (G.save_in_use,
00526 G.by_depth_max * sizeof (unsigned long *));
00527 }
00528 G.by_depth[G.by_depth_in_use] = p;
00529 G.save_in_use[G.by_depth_in_use++] = s;
00530 }
00531
00532 #if (GCC_VERSION < 3001)
00533 #define prefetch(X) ((void) X)
00534 #else
00535 #define prefetch(X) __builtin_prefetch (X)
00536 #endif
00537
00538 #define save_in_use_p_i(__i) \
00539 (G.save_in_use[__i])
00540 #define save_in_use_p(__p) \
00541 (save_in_use_p_i (__p->index_by_depth))
00542
00543
00544
00545 static inline int
00546 ggc_allocated_p (const void *p)
00547 {
00548 page_entry ***base;
00549 size_t L1, L2;
00550
00551 #if HOST_BITS_PER_PTR <= 32
00552 base = &G.lookup[0];
00553 #else
00554 page_table table = G.lookup;
00555 size_t high_bits = (size_t) p & ~ (size_t) 0xffffffff;
00556 while (1)
00557 {
00558 if (table == NULL)
00559 return 0;
00560 if (table->high_bits == high_bits)
00561 break;
00562 table = table->next;
00563 }
00564 base = &table->table[0];
00565 #endif
00566
00567
00568 L1 = LOOKUP_L1 (p);
00569 L2 = LOOKUP_L2 (p);
00570
00571 return base[L1] && base[L1][L2];
00572 }
00573
00574
00575
00576
00577 static inline page_entry *
00578 lookup_page_table_entry (const void *p)
00579 {
00580 page_entry ***base;
00581 size_t L1, L2;
00582
00583 #if HOST_BITS_PER_PTR <= 32
00584 base = &G.lookup[0];
00585 #else
00586 page_table table = G.lookup;
00587 size_t high_bits = (size_t) p & ~ (size_t) 0xffffffff;
00588 while (table->high_bits != high_bits)
00589 table = table->next;
00590 base = &table->table[0];
00591 #endif
00592
00593
00594 L1 = LOOKUP_L1 (p);
00595 L2 = LOOKUP_L2 (p);
00596
00597 return base[L1][L2];
00598 }
00599
00600
00601
00602 static void
00603 set_page_table_entry (void *p, page_entry *entry)
00604 {
00605 page_entry ***base;
00606 size_t L1, L2;
00607
00608 #if HOST_BITS_PER_PTR <= 32
00609 base = &G.lookup[0];
00610 #else
00611 page_table table;
00612 size_t high_bits = (size_t) p & ~ (size_t) 0xffffffff;
00613 for (table = G.lookup; table; table = table->next)
00614 if (table->high_bits == high_bits)
00615 goto found;
00616
00617
00618 table = xcalloc (1, sizeof(*table));
00619 table->next = G.lookup;
00620 table->high_bits = high_bits;
00621 G.lookup = table;
00622 found:
00623 base = &table->table[0];
00624 #endif
00625
00626
00627 L1 = LOOKUP_L1 (p);
00628 L2 = LOOKUP_L2 (p);
00629
00630 if (base[L1] == NULL)
00631 base[L1] = xcalloc (PAGE_L2_SIZE, sizeof (page_entry *));
00632
00633 base[L1][L2] = entry;
00634 }
00635
00636
00637
00638 void
00639 debug_print_page_list (int order)
00640 {
00641 page_entry *p;
00642 printf ("Head=%p, Tail=%p:\n", (void *) G.pages[order],
00643 (void *) G.page_tails[order]);
00644 p = G.pages[order];
00645 while (p != NULL)
00646 {
00647 printf ("%p(%1d|%3d) -> ", (void *) p, p->context_depth,
00648 p->num_free_objects);
00649 p = p->next;
00650 }
00651 printf ("NULL\n");
00652 fflush (stdout);
00653 }
00654
00655 #ifdef USING_MMAP
00656
00657
00658
00659
00660 static inline char *
00661 alloc_anon (char *pref ATTRIBUTE_UNUSED, size_t size)
00662 {
00663 #ifdef HAVE_MMAP_ANON
00664 char *page = mmap (pref, size, PROT_READ | PROT_WRITE,
00665 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
00666 #endif
00667 #ifdef HAVE_MMAP_DEV_ZERO
00668 char *page = mmap (pref, size, PROT_READ | PROT_WRITE,
00669 MAP_PRIVATE, G.dev_zero_fd, 0);
00670 #endif
00671
00672 if (page == (char *) MAP_FAILED)
00673 {
00674 perror ("virtual memory exhausted");
00675 exit (FATAL_EXIT_CODE);
00676 }
00677
00678
00679 G.bytes_mapped += size;
00680
00681
00682
00683
00684 VALGRIND_DISCARD (VALGRIND_MAKE_NOACCESS (page, size));
00685
00686 return page;
00687 }
00688 #endif
00689 #ifdef USING_MALLOC_PAGE_GROUPS
00690
00691
00692 static inline size_t
00693 page_group_index (char *allocation, char *page)
00694 {
00695 return (size_t) (page - allocation) >> G.lg_pagesize;
00696 }
00697
00698
00699
00700 static inline void
00701 set_page_group_in_use (page_group *group, char *page)
00702 {
00703 group->in_use |= 1 << page_group_index (group->allocation, page);
00704 }
00705
00706 static inline void
00707 clear_page_group_in_use (page_group *group, char *page)
00708 {
00709 group->in_use &= ~(1 << page_group_index (group->allocation, page));
00710 }
00711 #endif
00712
00713
00714
00715
00716
00717 static inline struct page_entry *
00718 alloc_page (unsigned order)
00719 {
00720 struct page_entry *entry, *p, **pp;
00721 char *page;
00722 size_t num_objects;
00723 size_t bitmap_size;
00724 size_t page_entry_size;
00725 size_t entry_size;
00726 #ifdef USING_MALLOC_PAGE_GROUPS
00727 page_group *group;
00728 #endif
00729
00730 num_objects = OBJECTS_PER_PAGE (order);
00731 bitmap_size = BITMAP_SIZE (num_objects + 1);
00732 page_entry_size = sizeof (page_entry) - sizeof (long) + bitmap_size;
00733 entry_size = num_objects * OBJECT_SIZE (order);
00734 if (entry_size < G.pagesize)
00735 entry_size = G.pagesize;
00736
00737 entry = NULL;
00738 page = NULL;
00739
00740
00741 for (pp = &G.free_pages, p = *pp; p; pp = &p->next, p = *pp)
00742 if (p->bytes == entry_size)
00743 break;
00744
00745 if (p != NULL)
00746 {
00747
00748 *pp = p->next;
00749 page = p->page;
00750
00751 #ifdef USING_MALLOC_PAGE_GROUPS
00752 group = p->group;
00753 #endif
00754
00755
00756 if (p->order == order)
00757 {
00758 entry = p;
00759 memset (entry, 0, page_entry_size);
00760 }
00761 else
00762 free (p);
00763 }
00764 #ifdef USING_MMAP
00765 else if (entry_size == G.pagesize)
00766 {
00767
00768
00769
00770 struct page_entry *e, *f = G.free_pages;
00771 int i;
00772
00773 page = alloc_anon (NULL, G.pagesize * GGC_QUIRE_SIZE);
00774
00775
00776
00777 for (i = GGC_QUIRE_SIZE - 1; i >= 1; i--)
00778 {
00779 e = xcalloc (1, page_entry_size);
00780 e->order = order;
00781 e->bytes = G.pagesize;
00782 e->page = page + (i << G.lg_pagesize);
00783 e->next = f;
00784 f = e;
00785 }
00786
00787 G.free_pages = f;
00788 }
00789 else
00790 page = alloc_anon (NULL, entry_size);
00791 #endif
00792 #ifdef USING_MALLOC_PAGE_GROUPS
00793 else
00794 {
00795
00796
00797
00798
00799 char *allocation, *a, *enda;
00800 size_t alloc_size, head_slop, tail_slop;
00801 int multiple_pages = (entry_size == G.pagesize);
00802
00803 if (multiple_pages)
00804 alloc_size = GGC_QUIRE_SIZE * G.pagesize;
00805 else
00806 alloc_size = entry_size + G.pagesize - 1;
00807 allocation = xmalloc (alloc_size);
00808
00809 page = (char *) (((size_t) allocation + G.pagesize - 1) & -G.pagesize);
00810 head_slop = page - allocation;
00811 if (multiple_pages)
00812 tail_slop = ((size_t) allocation + alloc_size) & (G.pagesize - 1);
00813 else
00814 tail_slop = alloc_size - entry_size - head_slop;
00815 enda = allocation + alloc_size - tail_slop;
00816
00817
00818
00819
00820 if (head_slop >= sizeof (page_group))
00821 group = (page_group *)page - 1;
00822 else
00823 {
00824
00825
00826 if (tail_slop == 0)
00827 {
00828 enda -= G.pagesize;
00829 tail_slop += G.pagesize;
00830 }
00831 gcc_assert (tail_slop >= sizeof (page_group));
00832 group = (page_group *)enda;
00833 tail_slop -= sizeof (page_group);
00834 }
00835
00836
00837 group->next = G.page_groups;
00838 group->allocation = allocation;
00839 group->alloc_size = alloc_size;
00840 group->in_use = 0;
00841 G.page_groups = group;
00842 G.bytes_mapped += alloc_size;
00843
00844
00845 if (multiple_pages)
00846 {
00847 struct page_entry *e, *f = G.free_pages;
00848 for (a = enda - G.pagesize; a != page; a -= G.pagesize)
00849 {
00850 e = xcalloc (1, page_entry_size);
00851 e->order = order;
00852 e->bytes = G.pagesize;
00853 e->page = a;
00854 e->group = group;
00855 e->next = f;
00856 f = e;
00857 }
00858 G.free_pages = f;
00859 }
00860 }
00861 #endif
00862
00863 if (entry == NULL)
00864 entry = xcalloc (1, page_entry_size);
00865
00866 entry->bytes = entry_size;
00867 entry->page = page;
00868 entry->context_depth = G.context_depth;
00869 entry->order = order;
00870 entry->num_free_objects = num_objects;
00871 entry->next_bit_hint = 1;
00872
00873 G.context_depth_allocations |= (unsigned long)1 << G.context_depth;
00874
00875 #ifdef USING_MALLOC_PAGE_GROUPS
00876 entry->group = group;
00877 set_page_group_in_use (group, page);
00878 #endif
00879
00880
00881
00882 entry->in_use_p[num_objects / HOST_BITS_PER_LONG]
00883 = (unsigned long) 1 << (num_objects % HOST_BITS_PER_LONG);
00884
00885 set_page_table_entry (page, entry);
00886
00887 if (GGC_DEBUG_LEVEL >= 2)
00888 fprintf (G.debug_file,
00889 "Allocating page at %p, object size=%lu, data %p-%p\n",
00890 (void *) entry, (unsigned long) OBJECT_SIZE (order), page,
00891 page + entry_size - 1);
00892
00893 return entry;
00894 }
00895
00896
00897
00898
00899 static inline void
00900 adjust_depth (void)
00901 {
00902 page_entry *top;
00903
00904 if (G.by_depth_in_use)
00905 {
00906 top = G.by_depth[G.by_depth_in_use-1];
00907
00908
00909
00910
00911 while (G.depth_in_use > (size_t)top->context_depth+1)
00912 --G.depth_in_use;
00913 }
00914 }
00915
00916
00917
00918 static void
00919 free_page (page_entry *entry)
00920 {
00921 if (GGC_DEBUG_LEVEL >= 2)
00922 fprintf (G.debug_file,
00923 "Deallocating page at %p, data %p-%p\n", (void *) entry,
00924 entry->page, entry->page + entry->bytes - 1);
00925
00926
00927
00928 VALGRIND_DISCARD (VALGRIND_MAKE_NOACCESS (entry->page, entry->bytes));
00929
00930 set_page_table_entry (entry->page, NULL);
00931
00932 #ifdef USING_MALLOC_PAGE_GROUPS
00933 clear_page_group_in_use (entry->group, entry->page);
00934 #endif
00935
00936 if (G.by_depth_in_use > 1)
00937 {
00938 page_entry *top = G.by_depth[G.by_depth_in_use-1];
00939 int i = entry->index_by_depth;
00940
00941
00942
00943 gcc_assert (entry->context_depth == top->context_depth);
00944
00945
00946 G.by_depth[i] = top;
00947 G.save_in_use[i] = G.save_in_use[G.by_depth_in_use-1];
00948 top->index_by_depth = i;
00949 }
00950 --G.by_depth_in_use;
00951
00952 adjust_depth ();
00953
00954 entry->next = G.free_pages;
00955 G.free_pages = entry;
00956 }
00957
00958
00959
00960 static void
00961 release_pages (void)
00962 {
00963 #ifdef USING_MMAP
00964 page_entry *p, *next;
00965 char *start;
00966 size_t len;
00967
00968
00969 p = G.free_pages;
00970
00971 while (p)
00972 {
00973 start = p->page;
00974 next = p->next;
00975 len = p->bytes;
00976 free (p);
00977 p = next;
00978
00979 while (p && p->page == start + len)
00980 {
00981 next = p->next;
00982 len += p->bytes;
00983 free (p);
00984 p = next;
00985 }
00986
00987 munmap (start, len);
00988 G.bytes_mapped -= len;
00989 }
00990
00991 G.free_pages = NULL;
00992 #endif
00993 #ifdef USING_MALLOC_PAGE_GROUPS
00994 page_entry **pp, *p;
00995 page_group **gp, *g;
00996
00997
00998 pp = &G.free_pages;
00999 while ((p = *pp) != NULL)
01000 if (p->group->in_use == 0)
01001 {
01002 *pp = p->next;
01003 free (p);
01004 }
01005 else
01006 pp = &p->next;
01007
01008
01009 gp = &G.page_groups;
01010 while ((g = *gp) != NULL)
01011 if (g->in_use == 0)
01012 {
01013 *gp = g->next;
01014 G.bytes_mapped -= g->alloc_size;
01015 free (g->allocation);
01016 }
01017 else
01018 gp = &g->next;
01019 #endif
01020 }
01021
01022
01023
01024
01025 static unsigned char size_lookup[257] =
01026 {
01027 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4,
01028 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
01029 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
01030 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
01031 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
01032 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
01033 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
01034 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
01035 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
01036 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
01037 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
01038 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
01039 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
01040 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
01041 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
01042 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
01043 8
01044 };
01045
01046
01047
01048 void *
01049 ggc_alloc_typed_stat (enum gt_types_enum type ATTRIBUTE_UNUSED, size_t size
01050 MEM_STAT_DECL)
01051 {
01052 return ggc_alloc_stat (size PASS_MEM_STAT);
01053 }
01054
01055
01056
01057 void *
01058 ggc_alloc_zone_stat (size_t size, struct alloc_zone *zone ATTRIBUTE_UNUSED
01059 MEM_STAT_DECL)
01060 {
01061 return ggc_alloc_stat (size PASS_MEM_STAT);
01062 }
01063
01064
01065
01066 void *
01067 ggc_alloc_stat (size_t size MEM_STAT_DECL)
01068 {
01069 size_t order, word, bit, object_offset, object_size;
01070 struct page_entry *entry;
01071 void *result;
01072
01073 if (size <= 256)
01074 {
01075 order = size_lookup[size];
01076 object_size = OBJECT_SIZE (order);
01077 }
01078 else
01079 {
01080 order = 9;
01081 while (size > (object_size = OBJECT_SIZE (order)))
01082 order++;
01083 }
01084
01085
01086
01087 entry = G.pages[order];
01088
01089
01090
01091 if (entry == NULL || entry->num_free_objects == 0)
01092 {
01093 struct page_entry *new_entry;
01094 new_entry = alloc_page (order);
01095
01096 new_entry->index_by_depth = G.by_depth_in_use;
01097 push_by_depth (new_entry, 0);
01098
01099
01100
01101 while (new_entry->context_depth >= G.depth_in_use)
01102 push_depth (G.by_depth_in_use-1);
01103
01104
01105
01106
01107 if (entry == NULL)
01108 G.page_tails[order] = new_entry;
01109 else
01110 entry->prev = new_entry;
01111
01112
01113
01114 new_entry->next = entry;
01115 new_entry->prev = NULL;
01116 entry = new_entry;
01117 G.pages[order] = new_entry;
01118
01119
01120
01121 new_entry->next_bit_hint = 1;
01122 word = 0;
01123 bit = 0;
01124 object_offset = 0;
01125 }
01126 else
01127 {
01128
01129
01130
01131
01132 unsigned hint = entry->next_bit_hint;
01133 word = hint / HOST_BITS_PER_LONG;
01134 bit = hint % HOST_BITS_PER_LONG;
01135
01136
01137 if ((entry->in_use_p[word] >> bit) & 1)
01138 {
01139 word = bit = 0;
01140 while (~entry->in_use_p[word] == 0)
01141 ++word;
01142
01143 #if GCC_VERSION >= 3004
01144 bit = __builtin_ctzl (~entry->in_use_p[word]);
01145 #else
01146 while ((entry->in_use_p[word] >> bit) & 1)
01147 ++bit;
01148 #endif
01149
01150 hint = word * HOST_BITS_PER_LONG + bit;
01151 }
01152
01153
01154 entry->next_bit_hint = hint + 1;
01155
01156 object_offset = hint * object_size;
01157 }
01158
01159
01160 entry->in_use_p[word] |= ((unsigned long) 1 << bit);
01161
01162
01163
01164
01165
01166 if (--entry->num_free_objects == 0
01167 && entry->next != NULL
01168 && entry->next->num_free_objects > 0)
01169 {
01170
01171 G.pages[order] = entry->next;
01172
01173
01174
01175
01176 entry->next->prev = NULL;
01177 entry->next = NULL;
01178
01179
01180 entry->prev = G.page_tails[order];
01181 G.page_tails[order]->next = entry;
01182 G.page_tails[order] = entry;
01183 }
01184
01185
01186 result = entry->page + object_offset;
01187 #ifdef GATHER_STATISTICS
01188 ggc_record_overhead (OBJECT_SIZE (order), OBJECT_SIZE (order) - size,
01189 result PASS_MEM_STAT);
01190 #endif
01191
01192 #ifdef ENABLE_GC_CHECKING
01193
01194
01195
01196
01197 VALGRIND_DISCARD (VALGRIND_MAKE_WRITABLE (result, object_size));
01198
01199
01200
01201 memset (result, 0xaf, object_size);
01202
01203
01204
01205 VALGRIND_DISCARD (VALGRIND_MAKE_NOACCESS ((char *) result + size,
01206 object_size - size));
01207 #endif
01208
01209
01210
01211
01212 VALGRIND_DISCARD (VALGRIND_MAKE_WRITABLE (result, size));
01213
01214
01215
01216 G.allocated += object_size;
01217
01218 #ifdef GATHER_STATISTICS
01219 {
01220 size_t overhead = object_size - size;
01221
01222 G.stats.total_overhead += overhead;
01223 G.stats.total_allocated += object_size;
01224 G.stats.total_overhead_per_order[order] += overhead;
01225 G.stats.total_allocated_per_order[order] += object_size;
01226
01227 if (size <= 32)
01228 {
01229 G.stats.total_overhead_under32 += overhead;
01230 G.stats.total_allocated_under32 += object_size;
01231 }
01232 if (size <= 64)
01233 {
01234 G.stats.total_overhead_under64 += overhead;
01235 G.stats.total_allocated_under64 += object_size;
01236 }
01237 if (size <= 128)
01238 {
01239 G.stats.total_overhead_under128 += overhead;
01240 G.stats.total_allocated_under128 += object_size;
01241 }
01242 }
01243 #endif
01244
01245 if (GGC_DEBUG_LEVEL >= 3)
01246 fprintf (G.debug_file,
01247 "Allocating object, requested size=%lu, actual=%lu at %p on %p\n",
01248 (unsigned long) size, (unsigned long) object_size, result,
01249 (void *) entry);
01250
01251 return result;
01252 }
01253
01254
01255
01256
01257
01258 int
01259 ggc_set_mark (const void *p)
01260 {
01261 page_entry *entry;
01262 unsigned bit, word;
01263 unsigned long mask;
01264
01265
01266
01267 entry = lookup_page_table_entry (p);
01268 gcc_assert (entry);
01269
01270
01271
01272 bit = OFFSET_TO_BIT (((const char *) p) - entry->page, entry->order);
01273 word = bit / HOST_BITS_PER_LONG;
01274 mask = (unsigned long) 1 << (bit % HOST_BITS_PER_LONG);
01275
01276
01277 if (entry->in_use_p[word] & mask)
01278 return 1;
01279
01280
01281 entry->in_use_p[word] |= mask;
01282 entry->num_free_objects -= 1;
01283
01284 if (GGC_DEBUG_LEVEL >= 4)
01285 fprintf (G.debug_file, "Marking %p\n", p);
01286
01287 return 0;
01288 }
01289
01290
01291
01292
01293
01294 int
01295 ggc_marked_p (const void *p)
01296 {
01297 page_entry *entry;
01298 unsigned bit, word;
01299 unsigned long mask;
01300
01301
01302
01303 entry = lookup_page_table_entry (p);
01304 gcc_assert (entry);
01305
01306
01307
01308 bit = OFFSET_TO_BIT (((const char *) p) - entry->page, entry->order);
01309 word = bit / HOST_BITS_PER_LONG;
01310 mask = (unsigned long) 1 << (bit % HOST_BITS_PER_LONG);
01311
01312 return (entry->in_use_p[word] & mask) != 0;
01313 }
01314
01315
01316
01317 size_t
01318 ggc_get_size (const void *p)
01319 {
01320 page_entry *pe = lookup_page_table_entry (p);
01321 return OBJECT_SIZE (pe->order);
01322 }
01323
01324
01325
01326 void
01327 ggc_free (void *p)
01328 {
01329 page_entry *pe = lookup_page_table_entry (p);
01330 size_t order = pe->order;
01331 size_t size = OBJECT_SIZE (order);
01332
01333 #ifdef GATHER_STATISTICS
01334 ggc_free_overhead (p);
01335 #endif
01336
01337 if (GGC_DEBUG_LEVEL >= 3)
01338 fprintf (G.debug_file,
01339 "Freeing object, actual size=%lu, at %p on %p\n",
01340 (unsigned long) size, p, (void *) pe);
01341
01342 #ifdef ENABLE_GC_CHECKING
01343
01344 VALGRIND_DISCARD (VALGRIND_MAKE_WRITABLE (p, size));
01345 memset (p, 0xa5, size);
01346 #endif
01347
01348 VALGRIND_DISCARD (VALGRIND_MAKE_NOACCESS (p, size));
01349
01350 #ifdef ENABLE_GC_ALWAYS_COLLECT
01351
01352
01353
01354 {
01355 struct free_object *fo = xmalloc (sizeof (struct free_object));
01356 fo->object = p;
01357 fo->next = G.free_object_list;
01358 G.free_object_list = fo;
01359 }
01360 #else
01361 {
01362 unsigned int bit_offset, word, bit;
01363
01364 G.allocated -= size;
01365
01366
01367 bit_offset = OFFSET_TO_BIT (((const char *) p) - pe->page, order);
01368 word = bit_offset / HOST_BITS_PER_LONG;
01369 bit = bit_offset % HOST_BITS_PER_LONG;
01370 pe->in_use_p[word] &= ~(1UL << bit);
01371
01372 if (pe->num_free_objects++ == 0)
01373 {
01374 page_entry *p, *q;
01375
01376
01377
01378
01379
01380
01381
01382
01383 q = pe->prev;
01384 if (q && q->num_free_objects == 0)
01385 {
01386 p = pe->next;
01387
01388 q->next = p;
01389
01390
01391
01392
01393 if (!p)
01394 G.page_tails[order] = q;
01395 else
01396 p->prev = q;
01397
01398
01399 pe->next = G.pages[order];
01400 pe->prev = NULL;
01401 G.pages[order]->prev = pe;
01402 G.pages[order] = pe;
01403 }
01404
01405
01406 pe->next_bit_hint = bit_offset;
01407 }
01408 }
01409 #endif
01410 }
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420 static void
01421 compute_inverse (unsigned order)
01422 {
01423 size_t size, inv;
01424 unsigned int e;
01425
01426 size = OBJECT_SIZE (order);
01427 e = 0;
01428 while (size % 2 == 0)
01429 {
01430 e++;
01431 size >>= 1;
01432 }
01433
01434 inv = size;
01435 while (inv * size != 1)
01436 inv = inv * (2 - inv*size);
01437
01438 DIV_MULT (order) = inv;
01439 DIV_SHIFT (order) = e;
01440 }
01441
01442
01443 void
01444 init_ggc (void)
01445 {
01446 unsigned order;
01447
01448 G.pagesize = getpagesize();
01449 G.lg_pagesize = exact_log2 (G.pagesize);
01450
01451 #ifdef HAVE_MMAP_DEV_ZERO
01452 G.dev_zero_fd = open ("/dev/zero", O_RDONLY);
01453 if (G.dev_zero_fd == -1)
01454 internal_error ("open /dev/zero: %m");
01455 #endif
01456
01457 #if 0
01458 G.debug_file = fopen ("ggc-mmap.debug", "w");
01459 #else
01460 G.debug_file = stdout;
01461 #endif
01462
01463 #ifdef USING_MMAP
01464
01465
01466
01467
01468 {
01469 char *p = alloc_anon (NULL, G.pagesize);
01470 struct page_entry *e;
01471 if ((size_t)p & (G.pagesize - 1))
01472 {
01473
01474
01475
01476 p = alloc_anon (NULL, G.pagesize);
01477 gcc_assert (!((size_t)p & (G.pagesize - 1)));
01478 }
01479
01480
01481 e = xcalloc (1, sizeof (struct page_entry));
01482 e->bytes = G.pagesize;
01483 e->page = p;
01484 e->next = G.free_pages;
01485 G.free_pages = e;
01486 }
01487 #endif
01488
01489
01490 for (order = 0; order < HOST_BITS_PER_PTR; ++order)
01491 object_size_table[order] = (size_t) 1 << order;
01492 for (order = HOST_BITS_PER_PTR; order < NUM_ORDERS; ++order)
01493 {
01494 size_t s = extra_order_size_table[order - HOST_BITS_PER_PTR];
01495
01496
01497
01498 s = ROUND_UP (s, MAX_ALIGNMENT);
01499 object_size_table[order] = s;
01500 }
01501
01502
01503 for (order = 0; order < NUM_ORDERS; ++order)
01504 {
01505 objects_per_page_table[order] = G.pagesize / OBJECT_SIZE (order);
01506 if (objects_per_page_table[order] == 0)
01507 objects_per_page_table[order] = 1;
01508 compute_inverse (order);
01509 }
01510
01511
01512
01513
01514
01515 for (order = HOST_BITS_PER_PTR; order < NUM_ORDERS; ++order)
01516 {
01517 int o;
01518 int i;
01519
01520 o = size_lookup[OBJECT_SIZE (order)];
01521 for (i = OBJECT_SIZE (order); size_lookup [i] == o; --i)
01522 size_lookup[i] = order;
01523 }
01524
01525 G.depth_in_use = 0;
01526 G.depth_max = 10;
01527 G.depth = xmalloc (G.depth_max * sizeof (unsigned int));
01528
01529 G.by_depth_in_use = 0;
01530 G.by_depth_max = INITIAL_PTE_COUNT;
01531 G.by_depth = xmalloc (G.by_depth_max * sizeof (page_entry *));
01532 G.save_in_use = xmalloc (G.by_depth_max * sizeof (unsigned long *));
01533 }
01534
01535
01536
01537 struct alloc_zone *
01538 new_ggc_zone (const char *name ATTRIBUTE_UNUSED)
01539 {
01540 return NULL;
01541 }
01542
01543
01544 void
01545 destroy_ggc_zone (struct alloc_zone *zone ATTRIBUTE_UNUSED)
01546 {
01547 }
01548
01549
01550
01551
01552 void
01553 ggc_push_context (void)
01554 {
01555 ++G.context_depth;
01556
01557
01558 gcc_assert (G.context_depth < HOST_BITS_PER_LONG);
01559 }
01560
01561
01562
01563
01564 static void
01565 ggc_recalculate_in_use_p (page_entry *p)
01566 {
01567 unsigned int i;
01568 size_t num_objects;
01569
01570
01571
01572 num_objects = OBJECTS_IN_PAGE (p) + 1;
01573
01574
01575 p->num_free_objects = num_objects;
01576
01577
01578 for (i = 0;
01579 i < CEIL (BITMAP_SIZE (num_objects),
01580 sizeof (*p->in_use_p));
01581 ++i)
01582 {
01583 unsigned long j;
01584
01585
01586
01587 p->in_use_p[i] |= save_in_use_p (p)[i];
01588
01589
01590 for (j = p->in_use_p[i]; j; j >>= 1)
01591 p->num_free_objects -= (j & 1);
01592 }
01593
01594 gcc_assert (p->num_free_objects < num_objects);
01595 }
01596
01597
01598
01599
01600 void
01601 ggc_pop_context (void)
01602 {
01603 unsigned long omask;
01604 unsigned int depth, i, e;
01605 #ifdef ENABLE_CHECKING
01606 unsigned int order;
01607 #endif
01608
01609 depth = --G.context_depth;
01610 omask = (unsigned long)1 << (depth + 1);
01611
01612 if (!((G.context_depth_allocations | G.context_depth_collections) & omask))
01613 return;
01614
01615 G.context_depth_allocations |= (G.context_depth_allocations & omask) >> 1;
01616 G.context_depth_allocations &= omask - 1;
01617 G.context_depth_collections &= omask - 1;
01618
01619
01620
01621 if (depth+1 < G.depth_in_use)
01622 e = G.depth[depth+1];
01623 else
01624 e = G.by_depth_in_use;
01625
01626
01627 if (depth < G.depth_in_use)
01628 {
01629
01630
01631
01632 for (i = G.depth[depth]; i < e; ++i)
01633 {
01634 page_entry *p = G.by_depth[i];
01635
01636
01637
01638 gcc_assert (p->context_depth == depth);
01639 gcc_assert (p->index_by_depth == i);
01640
01641 prefetch (&save_in_use_p_i (i+8));
01642 prefetch (&save_in_use_p_i (i+16));
01643 if (save_in_use_p_i (i))
01644 {
01645 p = G.by_depth[i];
01646 ggc_recalculate_in_use_p (p);
01647 free (save_in_use_p_i (i));
01648 save_in_use_p_i (i) = 0;
01649 }
01650 }
01651 }
01652
01653
01654
01655 for (i = e; i < G.by_depth_in_use; ++i)
01656 {
01657 page_entry *p = G.by_depth[i];
01658
01659
01660
01661 gcc_assert (p->context_depth > depth);
01662 gcc_assert (p->index_by_depth == i);
01663 p->context_depth = depth;
01664 }
01665
01666 adjust_depth ();
01667
01668 #ifdef ENABLE_CHECKING
01669 for (order = 2; order < NUM_ORDERS; order++)
01670 {
01671 page_entry *p;
01672
01673 for (p = G.pages[order]; p != NULL; p = p->next)
01674 gcc_assert (p->context_depth < depth ||
01675 (p->context_depth == depth && !save_in_use_p (p)));
01676 }
01677 #endif
01678 }
01679
01680
01681
01682 static void
01683 clear_marks (void)
01684 {
01685 unsigned order;
01686
01687 for (order = 2; order < NUM_ORDERS; order++)
01688 {
01689 page_entry *p;
01690
01691 for (p = G.pages[order]; p != NULL; p = p->next)
01692 {
01693 size_t num_objects = OBJECTS_IN_PAGE (p);
01694 size_t bitmap_size = BITMAP_SIZE (num_objects + 1);
01695
01696
01697 gcc_assert (!((size_t) p->page & (G.pagesize - 1)));
01698
01699
01700
01701
01702 if (p->context_depth < G.context_depth)
01703 {
01704 if (! save_in_use_p (p))
01705 save_in_use_p (p) = xmalloc (bitmap_size);
01706 memcpy (save_in_use_p (p), p->in_use_p, bitmap_size);
01707 }
01708
01709
01710
01711 p->num_free_objects = num_objects;
01712 memset (p->in_use_p, 0, bitmap_size);
01713
01714
01715 p->in_use_p[num_objects / HOST_BITS_PER_LONG]
01716 = ((unsigned long) 1 << (num_objects % HOST_BITS_PER_LONG));
01717 }
01718 }
01719 }
01720
01721
01722
01723
01724 static void
01725 sweep_pages (void)
01726 {
01727 unsigned order;
01728
01729 for (order = 2; order < NUM_ORDERS; order++)
01730 {
01731
01732
01733 page_entry * const last = G.page_tails[order];
01734
01735 size_t num_objects;
01736 size_t live_objects;
01737 page_entry *p, *previous;
01738 int done;
01739
01740 p = G.pages[order];
01741 if (p == NULL)
01742 continue;
01743
01744 previous = NULL;
01745 do
01746 {
01747 page_entry *next = p->next;
01748
01749
01750 done = (p == last);
01751
01752 num_objects = OBJECTS_IN_PAGE (p);
01753
01754
01755
01756 live_objects = num_objects - p->num_free_objects;
01757
01758 G.allocated += OBJECT_SIZE (order) * live_objects;
01759
01760
01761
01762 if (p->context_depth < G.context_depth)
01763 ;
01764
01765
01766 else if (live_objects == 0)
01767 {
01768
01769
01770
01771 if (! previous)
01772 G.pages[order] = next;
01773 else
01774 previous->next = next;
01775
01776
01777 if (next)
01778 next->prev = previous;
01779
01780
01781 if (p == G.page_tails[order])
01782 G.page_tails[order] = previous;
01783 free_page (p);
01784 p = previous;
01785 }
01786
01787
01788 else if (p->num_free_objects == 0)
01789 {
01790
01791 if (p != G.page_tails[order])
01792 {
01793
01794 p->next = NULL;
01795 p->prev = G.page_tails[order];
01796 G.page_tails[order]->next = p;
01797
01798
01799 G.page_tails[order] = p;
01800
01801
01802 if (! previous)
01803 G.pages[order] = next;
01804 else
01805 previous->next = next;
01806
01807
01808 if (next)
01809 next->prev = previous;
01810
01811 p = previous;
01812 }
01813 }
01814
01815
01816
01817
01818
01819 else if (p != G.pages[order])
01820 {
01821 previous->next = p->next;
01822
01823
01824 if (p->next)
01825 p->next->prev = previous;
01826
01827
01828 p->next = G.pages[order];
01829 p->prev = NULL;
01830 G.pages[order]->prev = p;
01831
01832
01833 G.pages[order] = p;
01834
01835
01836 if (G.page_tails[order] == p)
01837 G.page_tails[order] = previous;
01838 p = previous;
01839 }
01840
01841 previous = p;
01842 p = next;
01843 }
01844 while (! done);
01845
01846
01847
01848 for (p = G.pages[order]; p; p = p->next)
01849 if (p->context_depth != G.context_depth)
01850 ggc_recalculate_in_use_p (p);
01851 }
01852 }
01853
01854 #ifdef ENABLE_GC_CHECKING
01855
01856
01857 static void
01858 poison_pages (void)
01859 {
01860 unsigned order;
01861
01862 for (order = 2; order < NUM_ORDERS; order++)
01863 {
01864 size_t size = OBJECT_SIZE (order);
01865 page_entry *p;
01866
01867 for (p = G.pages[order]; p != NULL; p = p->next)
01868 {
01869 size_t num_objects;
01870 size_t i;
01871
01872 if (p->context_depth != G.context_depth)
01873
01874
01875
01876
01877 continue;
01878
01879 num_objects = OBJECTS_IN_PAGE (p);
01880 for (i = 0; i < num_objects; i++)
01881 {
01882 size_t word, bit;
01883 word = i / HOST_BITS_PER_LONG;
01884 bit = i % HOST_BITS_PER_LONG;
01885 if (((p->in_use_p[word] >> bit) & 1) == 0)
01886 {
01887 char *object = p->page + i * size;
01888
01889
01890
01891
01892
01893 VALGRIND_DISCARD (VALGRIND_MAKE_WRITABLE (object, size));
01894 memset (object, 0xa5, size);
01895
01896
01897 VALGRIND_DISCARD (VALGRIND_MAKE_NOACCESS (object, size));
01898 }
01899 }
01900 }
01901 }
01902 }
01903 #else
01904 #define poison_pages()
01905 #endif
01906
01907 #ifdef ENABLE_GC_ALWAYS_COLLECT
01908
01909
01910 static void
01911 validate_free_objects (void)
01912 {
01913 struct free_object *f, *next, *still_free = NULL;
01914
01915 for (f = G.free_object_list; f ; f = next)
01916 {
01917 page_entry *pe = lookup_page_table_entry (f->object);
01918 size_t bit, word;
01919
01920 bit = OFFSET_TO_BIT ((char *)f->object - pe->page, pe->order);
01921 word = bit / HOST_BITS_PER_LONG;
01922 bit = bit % HOST_BITS_PER_LONG;
01923 next = f->next;
01924
01925
01926
01927 gcc_assert (!(pe->in_use_p[word] & (1UL << bit)));
01928
01929
01930
01931
01932 if (pe->context_depth != G.context_depth)
01933 {
01934 f->next = still_free;
01935 still_free = f;
01936 }
01937 else
01938 free (f);
01939 }
01940
01941 G.free_object_list = still_free;
01942 }
01943 #else
01944 #define validate_free_objects()
01945 #endif
01946
01947
01948
01949 void
01950 ggc_collect (void)
01951 {
01952
01953
01954
01955 float allocated_last_gc =
01956 MAX (G.allocated_last_gc, (size_t)PARAM_VALUE (GGC_MIN_HEAPSIZE) * 1024);
01957
01958 float min_expand = allocated_last_gc * PARAM_VALUE (GGC_MIN_EXPAND) / 100;
01959
01960 if (G.allocated < allocated_last_gc + min_expand && !ggc_force_collect)
01961 return;
01962
01963 timevar_push (TV_GC);
01964 if (!quiet_flag)
01965 fprintf (stderr, " {GC %luk -> ", (unsigned long) G.allocated / 1024);
01966 if (GGC_DEBUG_LEVEL >= 2)
01967 fprintf (G.debug_file, "BEGIN COLLECTING\n");
01968
01969
01970
01971 G.allocated = 0;
01972
01973
01974
01975 release_pages ();
01976
01977
01978 G.context_depth_collections = ((unsigned long)1 << (G.context_depth + 1)) - 1;
01979
01980 clear_marks ();
01981 ggc_mark_roots ();
01982 #ifdef GATHER_STATISTICS
01983 ggc_prune_overhead_list ();
01984 #endif
01985 poison_pages ();
01986 validate_free_objects ();
01987 sweep_pages ();
01988
01989 G.allocated_last_gc = G.allocated;
01990
01991 timevar_pop (TV_GC);
01992
01993 if (!quiet_flag)
01994 fprintf (stderr, "%luk}", (unsigned long) G.allocated / 1024);
01995 if (GGC_DEBUG_LEVEL >= 2)
01996 fprintf (G.debug_file, "END COLLECTING\n");
01997 }
01998
01999
02000 #define SCALE(x) ((unsigned long) ((x) < 1024*10 \
02001 ? (x) \
02002 : ((x) < 1024*1024*10 \
02003 ? (x) / 1024 \
02004 : (x) / (1024*1024))))
02005 #define STAT_LABEL(x) ((x) < 1024*10 ? ' ' : ((x) < 1024*1024*10 ? 'k' : 'M'))
02006
02007 void
02008 ggc_print_statistics (void)
02009 {
02010 struct ggc_statistics stats;
02011 unsigned int i;
02012 size_t total_overhead = 0;
02013
02014
02015 memset (&stats, 0, sizeof (stats));
02016
02017
02018 G.allocated_last_gc = 0;
02019
02020
02021 ggc_print_common_statistics (stderr, &stats);
02022
02023
02024
02025 release_pages ();
02026
02027
02028
02029 fprintf (stderr,
02030 "Memory still allocated at the end of the compilation process\n");
02031 fprintf (stderr, "%-5s %10s %10s %10s\n",
02032 "Size", "Allocated", "Used", "Overhead");
02033 for (i = 0; i < NUM_ORDERS; ++i)
02034 {
02035 page_entry *p;
02036 size_t allocated;
02037 size_t in_use;
02038 size_t overhead;
02039
02040
02041 if (!G.pages[i])
02042 continue;
02043
02044 overhead = allocated = in_use = 0;
02045
02046
02047
02048
02049 for (p = G.pages[i]; p; p = p->next)
02050 {
02051 allocated += p->bytes;
02052 in_use +=
02053 (OBJECTS_IN_PAGE (p) - p->num_free_objects) * OBJECT_SIZE (i);
02054
02055 overhead += (sizeof (page_entry) - sizeof (long)
02056 + BITMAP_SIZE (OBJECTS_IN_PAGE (p) + 1));
02057 }
02058 fprintf (stderr, "%-5lu %10lu%c %10lu%c %10lu%c\n",
02059 (unsigned long) OBJECT_SIZE (i),
02060 SCALE (allocated), STAT_LABEL (allocated),
02061 SCALE (in_use), STAT_LABEL (in_use),
02062 SCALE (overhead), STAT_LABEL (overhead));
02063 total_overhead += overhead;
02064 }
02065 fprintf (stderr, "%-5s %10lu%c %10lu%c %10lu%c\n", "Total",
02066 SCALE (G.bytes_mapped), STAT_LABEL (G.bytes_mapped),
02067 SCALE (G.allocated), STAT_LABEL(G.allocated),
02068 SCALE (total_overhead), STAT_LABEL (total_overhead));
02069
02070 #ifdef GATHER_STATISTICS
02071 {
02072 fprintf (stderr, "\nTotal allocations and overheads during the compilation process\n");
02073
02074 fprintf (stderr, "Total Overhead: %10lld\n",
02075 G.stats.total_overhead);
02076 fprintf (stderr, "Total Allocated: %10lld\n",
02077 G.stats.total_allocated);
02078
02079 fprintf (stderr, "Total Overhead under 32B: %10lld\n",
02080 G.stats.total_overhead_under32);
02081 fprintf (stderr, "Total Allocated under 32B: %10lld\n",
02082 G.stats.total_allocated_under32);
02083 fprintf (stderr, "Total Overhead under 64B: %10lld\n",
02084 G.stats.total_overhead_under64);
02085 fprintf (stderr, "Total Allocated under 64B: %10lld\n",
02086 G.stats.total_allocated_under64);
02087 fprintf (stderr, "Total Overhead under 128B: %10lld\n",
02088 G.stats.total_overhead_under128);
02089 fprintf (stderr, "Total Allocated under 128B: %10lld\n",
02090 G.stats.total_allocated_under128);
02091
02092 for (i = 0; i < NUM_ORDERS; i++)
02093 if (G.stats.total_allocated_per_order[i])
02094 {
02095 fprintf (stderr, "Total Overhead page size %7d: %10lld\n",
02096 OBJECT_SIZE (i), G.stats.total_overhead_per_order[i]);
02097 fprintf (stderr, "Total Allocated page size %7d: %10lld\n",
02098 OBJECT_SIZE (i), G.stats.total_allocated_per_order[i]);
02099 }
02100 }
02101 #endif
02102 }
02103
02104 struct ggc_pch_data
02105 {
02106 struct ggc_pch_ondisk
02107 {
02108 unsigned totals[NUM_ORDERS];
02109 } d;
02110 size_t base[NUM_ORDERS];
02111 size_t written[NUM_ORDERS];
02112 };
02113
02114 struct ggc_pch_data *
02115 init_ggc_pch (void)
02116 {
02117 return xcalloc (sizeof (struct ggc_pch_data), 1);
02118 }
02119
02120 void
02121 ggc_pch_count_object (struct ggc_pch_data *d, void *x ATTRIBUTE_UNUSED,
02122 size_t size, bool is_string ATTRIBUTE_UNUSED)
02123 {
02124 unsigned order;
02125
02126 if (size <= 256)
02127 order = size_lookup[size];
02128 else
02129 {
02130 order = 9;
02131 while (size > OBJECT_SIZE (order))
02132 order++;
02133 }
02134
02135 d->d.totals[order]++;
02136 }
02137
02138 size_t
02139 ggc_pch_total_size (struct ggc_pch_data *d)
02140 {
02141 size_t a = 0;
02142 unsigned i;
02143
02144 for (i = 0; i < NUM_ORDERS; i++)
02145 a += ROUND_UP (d->d.totals[i] * OBJECT_SIZE (i), G.pagesize);
02146 return a;
02147 }
02148
02149 void
02150 ggc_pch_this_base (struct ggc_pch_data *d, void *base)
02151 {
02152 size_t a = (size_t) base;
02153 unsigned i;
02154
02155 for (i = 0; i < NUM_ORDERS; i++)
02156 {
02157 d->base[i] = a;
02158 a += ROUND_UP (d->d.totals[i] * OBJECT_SIZE (i), G.pagesize);
02159 }
02160 }
02161
02162
02163 char *
02164 ggc_pch_alloc_object (struct ggc_pch_data *d, void *x ATTRIBUTE_UNUSED,
02165 size_t size, bool is_string ATTRIBUTE_UNUSED)
02166 {
02167 unsigned order;
02168 char *result;
02169
02170 if (size <= 256)
02171 order = size_lookup[size];
02172 else
02173 {
02174 order = 9;
02175 while (size > OBJECT_SIZE (order))
02176 order++;
02177 }
02178
02179 result = (char *) d->base[order];
02180 d->base[order] += OBJECT_SIZE (order);
02181 return result;
02182 }
02183
02184 void
02185 ggc_pch_prepare_write (struct ggc_pch_data *d ATTRIBUTE_UNUSED,
02186 FILE *f ATTRIBUTE_UNUSED)
02187 {
02188
02189 }
02190
02191 void
02192 ggc_pch_write_object (struct ggc_pch_data *d ATTRIBUTE_UNUSED,
02193 FILE *f, void *x, void *newx ATTRIBUTE_UNUSED,
02194 size_t size, bool is_string ATTRIBUTE_UNUSED)
02195 {
02196 unsigned order;
02197 static const char emptyBytes[256];
02198
02199 if (size <= 256)
02200 order = size_lookup[size];
02201 else
02202 {
02203 order = 9;
02204 while (size > OBJECT_SIZE (order))
02205 order++;
02206 }
02207
02208 if (fwrite (x, size, 1, f) != 1)
02209 fatal_error ("can't write PCH file: %m");
02210
02211
02212
02213
02214 if (size != OBJECT_SIZE (order))
02215 {
02216 unsigned padding = OBJECT_SIZE(order) - size;
02217
02218
02219
02220
02221
02222 if (padding <= sizeof(emptyBytes))
02223 {
02224 if (fwrite (emptyBytes, 1, padding, f) != padding)
02225 fatal_error ("can't write PCH file");
02226 }
02227 else
02228 {
02229
02230 if (fseek (f, padding, SEEK_CUR) != 0)
02231 fatal_error ("can't write PCH file");
02232 }
02233 }
02234
02235 d->written[order]++;
02236 if (d->written[order] == d->d.totals[order]
02237 && fseek (f, ROUND_UP_VALUE (d->d.totals[order] * OBJECT_SIZE (order),
02238 G.pagesize),
02239 SEEK_CUR) != 0)
02240 fatal_error ("can't write PCH file: %m");
02241 }
02242
02243 void
02244 ggc_pch_finish (struct ggc_pch_data *d, FILE *f)
02245 {
02246 if (fwrite (&d->d, sizeof (d->d), 1, f) != 1)
02247 fatal_error ("can't write PCH file: %m");
02248 free (d);
02249 }
02250
02251
02252
02253
02254 static void
02255 move_ptes_to_front (int count_old_page_tables, int count_new_page_tables)
02256 {
02257 unsigned i;
02258
02259
02260 page_entry **new_by_depth;
02261 unsigned long **new_save_in_use;
02262
02263 new_by_depth = xmalloc (G.by_depth_max * sizeof (page_entry *));
02264 new_save_in_use = xmalloc (G.by_depth_max * sizeof (unsigned long *));
02265
02266 memcpy (&new_by_depth[0],
02267 &G.by_depth[count_old_page_tables],
02268 count_new_page_tables * sizeof (void *));
02269 memcpy (&new_by_depth[count_new_page_tables],
02270 &G.by_depth[0],
02271 count_old_page_tables * sizeof (void *));
02272 memcpy (&new_save_in_use[0],
02273 &G.save_in_use[count_old_page_tables],
02274 count_new_page_tables * sizeof (void *));
02275 memcpy (&new_save_in_use[count_new_page_tables],
02276 &G.save_in_use[0],
02277 count_old_page_tables * sizeof (void *));
02278
02279 free (G.by_depth);
02280 free (G.save_in_use);
02281
02282 G.by_depth = new_by_depth;
02283 G.save_in_use = new_save_in_use;
02284
02285
02286 for (i = G.by_depth_in_use; i > 0; --i)
02287 {
02288 page_entry *p = G.by_depth[i-1];
02289 p->index_by_depth = i-1;
02290 }
02291
02292
02293
02294
02295
02296
02297 if (count_old_page_tables)
02298 push_depth (count_new_page_tables);
02299 }
02300
02301 void
02302 ggc_pch_read (FILE *f, void *addr)
02303 {
02304 struct ggc_pch_ondisk d;
02305 unsigned i;
02306 char *offs = addr;
02307 unsigned long count_old_page_tables;
02308 unsigned long count_new_page_tables;
02309
02310 count_old_page_tables = G.by_depth_in_use;
02311
02312
02313
02314 clear_marks ();
02315 #ifdef ENABLE_GC_CHECKING
02316 poison_pages ();
02317 #endif
02318
02319
02320
02321
02322 gcc_assert (!G.context_depth);
02323 G.context_depth = 1;
02324 for (i = 0; i < NUM_ORDERS; i++)
02325 {
02326 page_entry *p;
02327 for (p = G.pages[i]; p != NULL; p = p->next)
02328 p->context_depth = G.context_depth;
02329 }
02330
02331
02332
02333 if (fread (&d, sizeof (d), 1, f) != 1)
02334 fatal_error ("can't read PCH file: %m");
02335
02336 for (i = 0; i < NUM_ORDERS; i++)
02337 {
02338 struct page_entry *entry;
02339 char *pte;
02340 size_t bytes;
02341 size_t num_objs;
02342 size_t j;
02343
02344 if (d.totals[i] == 0)
02345 continue;
02346
02347 bytes = ROUND_UP (d.totals[i] * OBJECT_SIZE (i), G.pagesize);
02348 num_objs = bytes / OBJECT_SIZE (i);
02349 entry = xcalloc (1, (sizeof (struct page_entry)
02350 - sizeof (long)
02351 + BITMAP_SIZE (num_objs + 1)));
02352 entry->bytes = bytes;
02353 entry->page = offs;
02354 entry->context_depth = 0;
02355 offs += bytes;
02356 entry->num_free_objects = 0;
02357 entry->order = i;
02358
02359 for (j = 0;
02360 j + HOST_BITS_PER_LONG <= num_objs + 1;
02361 j += HOST_BITS_PER_LONG)
02362 entry->in_use_p[j / HOST_BITS_PER_LONG] = -1;
02363 for (; j < num_objs + 1; j++)
02364 entry->in_use_p[j / HOST_BITS_PER_LONG]
02365 |= 1L << (j % HOST_BITS_PER_LONG);
02366
02367 for (pte = entry->page;
02368 pte < entry->page + entry->bytes;
02369 pte += G.pagesize)
02370 set_page_table_entry (pte, entry);
02371
02372 if (G.page_tails[i] != NULL)
02373 G.page_tails[i]->next = entry;
02374 else
02375 G.pages[i] = entry;
02376 G.page_tails[i] = entry;
02377
02378
02379
02380
02381
02382 push_by_depth (entry, 0);
02383 }
02384
02385
02386
02387 count_new_page_tables = G.by_depth_in_use - count_old_page_tables;
02388
02389 move_ptes_to_front (count_old_page_tables, count_new_page_tables);
02390
02391
02392 G.allocated = G.allocated_last_gc = offs - (char *)addr;
02393 }