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