ggc-common.c revision 96489
12089Ssos/* Simple garbage collection for the GNU compiler. 216565Ssos Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. 32089Ssos 42089SsosThis file is part of GCC. 52089Ssos 62089SsosGCC is free software; you can redistribute it and/or modify it under 72089Ssosthe terms of the GNU General Public License as published by the Free 82089SsosSoftware Foundation; either version 2, or (at your option) any later 95994Ssosversion. 105994Ssos 112089SsosGCC is distributed in the hope that it will be useful, but WITHOUT ANY 122089SsosWARRANTY; without even the implied warranty of MERCHANTABILITY or 132089SsosFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 142089Ssosfor more details. 1597748Sschweikh 162089SsosYou should have received a copy of the GNU General Public License 172089Ssosalong with GCC; see the file COPYING. If not, write to the Free 182089SsosSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA 192089Ssos02111-1307, USA. */ 202089Ssos 212089Ssos/* Generic garbage collection (GC) functions and data, not specific to 222089Ssos any particular GC implementation. */ 232089Ssos 242089Ssos#include "config.h" 252089Ssos#include "system.h" 262089Ssos#include "rtl.h" 272089Ssos#include "tree.h" 282089Ssos#include "tm_p.h" 2930764Scharnier#include "hash.h" 3030764Scharnier#include "hashtab.h" 3150479Speter#include "varray.h" 3230764Scharnier#include "ggc.h" 3330764Scharnier 342089Ssos/* Statistics about the allocation. */ 3530764Scharnierstatic ggc_statistics *ggc_stats; 3655849Syokota 372089Ssos/* The FALSE_LABEL_STACK, declared in except.h, has language-dependent 3823457Sbrian semantics. If a front-end needs to mark the false label stack, it 3930764Scharnier should set this pointer to a non-NULL value. Otherwise, no marking 4023702Speter will be done. */ 4166834Sphkvoid (*lang_mark_false_label_stack) PARAMS ((struct label_node *)); 4266834Sphk 432089Ssos/* Trees that have been marked, but whose children still need marking. */ 4475344Ssobomaxvarray_type ggc_pending_trees; 4575344Ssobomax 462089Ssosstatic void ggc_mark_rtx_children_1 PARAMS ((rtx)); 4723457Sbrianstatic void ggc_mark_rtx_ptr PARAMS ((void *)); 482089Ssosstatic void ggc_mark_tree_ptr PARAMS ((void *)); 4971642Ssobomaxstatic void ggc_mark_rtx_varray_ptr PARAMS ((void *)); 5071642Ssobomaxstatic void ggc_mark_tree_varray_ptr PARAMS ((void *)); 5171642Ssobomaxstatic void ggc_mark_tree_hash_table_ptr PARAMS ((void *)); 5271642Ssobomaxstatic int ggc_htab_delete PARAMS ((void **, void *)); 5376845Ssobomaxstatic void ggc_mark_trees PARAMS ((void)); 5476845Ssobomaxstatic bool ggc_mark_tree_hash_table_entry PARAMS ((struct hash_entry *, 5576845Ssobomax hash_table_key)); 5676845Ssobomax 5776845Ssobomax/* Maintain global roots that are preserved during GC. */ 582089Ssos 592089Ssos/* Global roots that are preserved during calls to gc. */ 602089Ssos 612089Ssosstruct ggc_root 622089Ssos{ 636628Ssos struct ggc_root *next; 642089Ssos void *base; 656047Ssos int nelt; 6671642Ssobomax int size; 6771642Ssobomax void (*cb) PARAMS ((void *)); 682089Ssos}; 692089Ssos 702089Ssosstatic struct ggc_root *roots; 712089Ssos 7230764Scharnier/* Add BASE as a new garbage collection root. It is an array of 736628Ssos length NELT with each element SIZE bytes long. CB is a 746628Ssos function that will be called with a pointer to each element 7555849Syokota of the array; it is the intention that CB call the appropriate 7677329Sdes routine to mark gc-able memory for that element. */ 7777329Sdes 7877329Sdesvoid 7977329Sdesggc_add_root (base, nelt, size, cb) 8030764Scharnier void *base; 816628Ssos int nelt, size; 826628Ssos void (*cb) PARAMS ((void *)); 832089Ssos{ 8475344Ssobomax struct ggc_root *x = (struct ggc_root *) xmalloc (sizeof (*x)); 852089Ssos 862089Ssos x->next = roots; 872089Ssos x->base = base; 8875344Ssobomax x->nelt = nelt; 8975344Ssobomax x->size = size; 9075344Ssobomax x->cb = cb; 912089Ssos 922089Ssos roots = x; 9392460Ssobomax} 9492460Ssobomax 952089Ssos/* Register an array of rtx as a GC root. */ 9692460Ssobomax 9792460Ssobomaxvoid 982089Ssosggc_add_rtx_root (base, nelt) 9992460Ssobomax rtx *base; 10092460Ssobomax int nelt; 10192460Ssobomax{ 10292460Ssobomax ggc_add_root (base, nelt, sizeof (rtx), ggc_mark_rtx_ptr); 10392460Ssobomax} 10492460Ssobomax 10592460Ssobomax/* Register an array of trees as a GC root. */ 10692460Ssobomax 10792460Ssobomaxvoid 10892460Ssobomaxggc_add_tree_root (base, nelt) 10992460Ssobomax tree *base; 11092460Ssobomax int nelt; 11192460Ssobomax{ 11252262Sbillf ggc_add_root (base, nelt, sizeof (tree), ggc_mark_tree_ptr); 11392460Ssobomax} 1142089Ssos 1152089Ssos/* Register a varray of rtxs as a GC root. */ 1162089Ssos 1172089Ssosvoid 1182089Ssosggc_add_rtx_varray_root (base, nelt) 11992460Ssobomax varray_type *base; 12092460Ssobomax int nelt; 1212089Ssos{ 1222089Ssos ggc_add_root (base, nelt, sizeof (varray_type), 12392460Ssobomax ggc_mark_rtx_varray_ptr); 12492460Ssobomax} 12592460Ssobomax 12692460Ssobomax/* Register a varray of trees as a GC root. */ 1272089Ssos 12892460Ssobomaxvoid 1292089Ssosggc_add_tree_varray_root (base, nelt) 13030764Scharnier varray_type *base; 1312089Ssos int nelt; 1322089Ssos{ 1332089Ssos ggc_add_root (base, nelt, sizeof (varray_type), 13475344Ssobomax ggc_mark_tree_varray_ptr); 1352089Ssos} 1362089Ssos 13730764Scharnier/* Register a hash table of trees as a GC root. */ 13823457Sbrian 1392089Ssosvoid 1402089Ssosggc_add_tree_hash_table_root (base, nelt) 1412089Ssos struct hash_table **base; 1422089Ssos int nelt; 14330764Scharnier{ 14423457Sbrian ggc_add_root (base, nelt, sizeof (struct hash_table *), 1452089Ssos ggc_mark_tree_hash_table_ptr); 1462089Ssos} 1472089Ssos 1482089Ssos/* Remove the previously registered GC root at BASE. */ 1492089Ssos 1506628Ssosvoid 1512089Ssosggc_del_root (base) 1522089Ssos void *base; 1532089Ssos{ 1542089Ssos struct ggc_root *x, **p; 1552089Ssos 15630764Scharnier p = &roots, x = roots; 1572089Ssos while (x) 1582089Ssos { 1592089Ssos if (x->base == base) 1602089Ssos { 1612089Ssos *p = x->next; 1622089Ssos free (x); 1632089Ssos return; 1642089Ssos } 1652089Ssos p = &x->next; 16630764Scharnier x = x->next; 1672089Ssos } 1682089Ssos 1692089Ssos abort (); 1702089Ssos} 1712089Ssos 1722089Ssos/* Add a hash table to be scanned when all roots have been processed. We 1738857Srgrimes delete any entry in the table that has not been marked. */ 1742089Ssos 1752089Ssosstruct d_htab_root 1762089Ssos{ 1772089Ssos struct d_htab_root *next; 1782089Ssos htab_t htab; 1792089Ssos ggc_htab_marked_p marked_p; 1802089Ssos ggc_htab_mark mark; 18175344Ssobomax}; 18275344Ssobomax 18375344Ssobomaxstatic struct d_htab_root *d_htab_roots; 18475344Ssobomax 18575344Ssobomax/* Add X, an htab, to a list of htabs that contain objects which are allocated 18675344Ssobomax from GC memory. Once all other roots are marked, we check each object in 18775344Ssobomax the htab to see if it has already been marked. If not, it is deleted. 18875344Ssobomax 18975344Ssobomax MARKED_P, if specified, is a function that returns 1 if the entry is to 19075344Ssobomax be considered as "marked". If not present, the data structure pointed to 19175344Ssobomax by the htab slot is tested. This function should be supplied if some 19275344Ssobomax other object (such as something pointed to by that object) should be tested 19375344Ssobomax in which case the function tests whether that object (or objects) are 1948857Srgrimes marked (using ggc_marked_p) and returns nonzero if it is. 1952089Ssos 1962089Ssos MARK, if specified, is a function that is passed the contents of a slot 19792460Ssobomax that has been determined to have been "marked" (via the above function) 19875344Ssobomax and marks any other objects pointed to by that object. For example, 19975344Ssobomax we might have a hash table of memory attribute blocks, which are pointed 20092460Ssobomax to by a MEM RTL but have a pointer to a DECL. MARKED_P in that case will 20192460Ssobomax not be specified because we want to know if the attribute block is pointed 20292460Ssobomax to by the MEM, but MARK must be specified because if the block has been 20392460Ssobomax marked, we need to mark the DECL. */ 20492460Ssobomax 20592460Ssobomaxvoid 2062089Ssosggc_add_deletable_htab (x, marked_p, mark) 20775344Ssobomax PTR x; 20875344Ssobomax ggc_htab_marked_p marked_p; 20975344Ssobomax ggc_htab_mark mark; 21075344Ssobomax{ 21175344Ssobomax struct d_htab_root *r 21275344Ssobomax = (struct d_htab_root *) xmalloc (sizeof (struct d_htab_root)); 21375344Ssobomax 21475344Ssobomax r->next = d_htab_roots; 21575344Ssobomax r->htab = (htab_t) x; 21692460Ssobomax r->marked_p = marked_p ? marked_p : ggc_marked_p; 21792460Ssobomax r->mark = mark; 21892460Ssobomax d_htab_roots = r; 21992460Ssobomax} 2202089Ssos 22192460Ssobomax/* Process a slot of an htab by deleting it if it has not been marked. */ 22292460Ssobomax 2232089Ssosstatic int 22475344Ssobomaxggc_htab_delete (slot, info) 2252089Ssos void **slot; 2262089Ssos void *info; 22775344Ssobomax{ 22875344Ssobomax struct d_htab_root *r = (struct d_htab_root *) info; 22975344Ssobomax 23075344Ssobomax if (! (*r->marked_p) (*slot)) 23175344Ssobomax htab_clear_slot (r->htab, slot); 23275344Ssobomax else if (r->mark) 23375344Ssobomax (*r->mark) (*slot); 23475344Ssobomax 23575344Ssobomax return 1; 23675344Ssobomax} 23775344Ssobomax 23875344Ssobomax/* Iterate through all registered roots and mark each element. */ 23975344Ssobomax 24075344Ssobomaxvoid 24175344Ssobomaxggc_mark_roots () 24275344Ssobomax{ 24375344Ssobomax struct ggc_root *x; 24475344Ssobomax struct d_htab_root *y; 24575344Ssobomax 24675344Ssobomax VARRAY_TREE_INIT (ggc_pending_trees, 4096, "ggc_pending_trees"); 24775344Ssobomax 24875344Ssobomax for (x = roots; x != NULL; x = x->next) 24975344Ssobomax { 25075344Ssobomax char *elt = x->base; 25175344Ssobomax int s = x->size, n = x->nelt; 25275344Ssobomax void (*cb) PARAMS ((void *)) = x->cb; 25375344Ssobomax int i; 25475344Ssobomax 25575344Ssobomax for (i = 0; i < n; ++i, elt += s) 25675344Ssobomax (*cb)(elt); 25775344Ssobomax } 25875344Ssobomax 25975344Ssobomax /* Mark all the queued up trees, and their children. */ 26075344Ssobomax ggc_mark_trees (); 26175344Ssobomax VARRAY_FREE (ggc_pending_trees); 26275344Ssobomax 26375344Ssobomax /* Now scan all hash tables that have objects which are to be deleted if 26475344Ssobomax they are not already marked. Since these may mark more trees, we need 26575344Ssobomax to reinitialize that varray. */ 26675344Ssobomax VARRAY_TREE_INIT (ggc_pending_trees, 1024, "ggc_pending_trees"); 26775344Ssobomax 2682089Ssos for (y = d_htab_roots; y != NULL; y = y->next) 26975344Ssobomax htab_traverse (y->htab, ggc_htab_delete, (PTR) y); 2702089Ssos ggc_mark_trees (); 27175344Ssobomax VARRAY_FREE (ggc_pending_trees); 2722089Ssos} 27375344Ssobomax 27475344Ssobomax/* R had not been previously marked, but has now been marked via 27523457Sbrian ggc_set_mark. Now recurse and process the children. */ 2762089Ssos 2772089Ssosvoid 2782089Ssosggc_mark_rtx_children (r) 2792089Ssos rtx r; 2802089Ssos{ 28130764Scharnier rtx i, last; 28223457Sbrian 2832089Ssos /* Special case the instruction chain. This is a data structure whose 2842089Ssos chain length is potentially unbounded, and which contain references 2852089Ssos within the chain (e.g. label_ref and insn_list). If do nothing here, 2862089Ssos we risk blowing the stack recursing through a long chain of insns. 2872089Ssos 2882089Ssos Combat this by marking all of the instructions in the chain before 2892089Ssos marking the contents of those instructions. */ 2902089Ssos 2912089Ssos switch (GET_CODE (r)) 2922089Ssos { 2932089Ssos case INSN: 2942089Ssos case JUMP_INSN: 2952089Ssos case CALL_INSN: 29630764Scharnier case NOTE: 2972089Ssos case CODE_LABEL: 2982089Ssos case BARRIER: 2992089Ssos for (i = NEXT_INSN (r); ; i = NEXT_INSN (i)) 3002089Ssos if (! ggc_test_and_set_mark (i)) 30130764Scharnier break; 3022089Ssos last = i; 3032089Ssos 3042089Ssos for (i = NEXT_INSN (r); i != last; i = NEXT_INSN (i)) 3055536Ssos ggc_mark_rtx_children_1 (i); 3062089Ssos 3075536Ssos default: 3082089Ssos break; 3096230Ssos } 3106230Ssos 3116230Ssos ggc_mark_rtx_children_1 (r); 3125536Ssos} 3136230Ssos 3146230Ssosstatic void 3155536Ssosggc_mark_rtx_children_1 (r) 31630764Scharnier rtx r; 3172089Ssos{ 3182089Ssos const char *fmt; 3195536Ssos int i; 3202089Ssos rtx next_rtx; 3212089Ssos 32223457Sbrian do 3232089Ssos { 3242089Ssos enum rtx_code code = GET_CODE (r); 32539592Syokota /* This gets set to a child rtx to eliminate tail recursion. */ 32639592Syokota next_rtx = NULL; 32739592Syokota 32839592Syokota /* Collect statistics, if appropriate. */ 32939592Syokota if (ggc_stats) 33039592Syokota { 33139592Syokota ++ggc_stats->num_rtxs[(int) code]; 33239592Syokota ggc_stats->size_rtxs[(int) code] += ggc_get_size (r); 33339592Syokota } 33439592Syokota 33539592Syokota /* ??? If (some of) these are really pass-dependent info, do we 33639592Syokota have any right poking our noses in? */ 33739592Syokota switch (code) 33839592Syokota { 33939592Syokota case MEM: 34039592Syokota ggc_mark (MEM_ATTRS (r)); 34139592Syokota break; 34239592Syokota case JUMP_INSN: 34339592Syokota ggc_mark_rtx (JUMP_LABEL (r)); 34448105Syokota break; 34548105Syokota case CODE_LABEL: 34648105Syokota ggc_mark_rtx (LABEL_REFS (r)); 34748105Syokota break; 34848105Syokota case LABEL_REF: 34948105Syokota ggc_mark_rtx (LABEL_NEXTREF (r)); 35048105Syokota ggc_mark_rtx (CONTAINING_INSN (r)); 35139592Syokota break; 35239592Syokota case ADDRESSOF: 35339592Syokota ggc_mark_tree (ADDRESSOF_DECL (r)); 35439592Syokota break; 35539592Syokota case CONST_DOUBLE: 35639592Syokota ggc_mark_rtx (CONST_DOUBLE_CHAIN (r)); 35739592Syokota break; 35839592Syokota case NOTE: 35939592Syokota switch (NOTE_LINE_NUMBER (r)) 36039592Syokota { 36142605Smjacob case NOTE_INSN_RANGE_BEG: 36248105Syokota case NOTE_INSN_RANGE_END: 36348105Syokota case NOTE_INSN_LIVE: 36439287Ssos case NOTE_INSN_EXPECTED_VALUE: 36539592Syokota ggc_mark_rtx (NOTE_RANGE_INFO (r)); 3662089Ssos break; 36748105Syokota 36848105Syokota case NOTE_INSN_BLOCK_BEG: 3692089Ssos case NOTE_INSN_BLOCK_END: 37039592Syokota ggc_mark_tree (NOTE_BLOCK (r)); 37139592Syokota break; 37239592Syokota 37339592Syokota default: 37439592Syokota break; 37539592Syokota } 37639592Syokota break; 3772089Ssos 3782089Ssos default: 37930764Scharnier break; 38039287Ssos } 38171642Ssobomax 38271642Ssobomax for (fmt = GET_RTX_FORMAT (GET_CODE (r)), i = 0; *fmt ; ++fmt, ++i) 38371642Ssobomax { 38471642Ssobomax rtx exp; 38571642Ssobomax switch (*fmt) 38671642Ssobomax { 38771642Ssobomax case 'e': case 'u': 38871642Ssobomax exp = XEXP (r, i); 38971642Ssobomax if (ggc_test_and_set_mark (exp)) 39071642Ssobomax { 39171642Ssobomax if (next_rtx == NULL) 39271642Ssobomax next_rtx = exp; 39371642Ssobomax else 39471642Ssobomax ggc_mark_rtx_children (exp); 39571642Ssobomax } 39671642Ssobomax break; 39771642Ssobomax case 'V': case 'E': 39871642Ssobomax ggc_mark_rtvec (XVEC (r, i)); 39971642Ssobomax break; 40048105Syokota } 40148105Syokota } 40248105Syokota } 40380148Syokota while ((r = next_rtx) != NULL); 40480148Syokota} 40580148Syokota 40648105Syokota/* V had not been previously marked, but has now been marked via 40748105Syokota ggc_set_mark. Now recurse and process the children. */ 40848105Syokota 40948105Syokotavoid 41039287Ssosggc_mark_rtvec_children (v) 4112089Ssos rtvec v; 4122089Ssos{ 4132089Ssos int i; 4142089Ssos 4158857Srgrimes i = GET_NUM_ELEM (v); 4162089Ssos while (--i >= 0) 4172089Ssos ggc_mark_rtx (RTVEC_ELT (v, i)); 4182089Ssos} 4192089Ssos 4202089Ssos/* Recursively set marks on all of the children of the 4212089Ssos GCC_PENDING_TREES. */ 4222089Ssos 4232089Ssosstatic void 4242089Ssosggc_mark_trees () 4252089Ssos{ 4262089Ssos while (ggc_pending_trees->elements_used) 42723457Sbrian { 4282089Ssos tree t; 4292089Ssos enum tree_code code; 4302089Ssos 4312089Ssos t = VARRAY_TOP_TREE (ggc_pending_trees); 4322089Ssos VARRAY_POP (ggc_pending_trees); 4332089Ssos code = TREE_CODE (t); 4342089Ssos 4358857Srgrimes /* Collect statistics, if appropriate. */ 4368857Srgrimes if (ggc_stats) 4372089Ssos { 4382089Ssos ++ggc_stats->num_trees[(int) code]; 4392089Ssos ggc_stats->size_trees[(int) code] += ggc_get_size (t); 4402089Ssos } 4412089Ssos 4422089Ssos /* Bits from common. */ 4432089Ssos ggc_mark_tree (TREE_TYPE (t)); 44423457Sbrian ggc_mark_tree (TREE_CHAIN (t)); 4452089Ssos 4462089Ssos /* Some nodes require special handling. */ 4472089Ssos switch (code) 4482089Ssos { 4492089Ssos case TREE_LIST: 4502089Ssos ggc_mark_tree (TREE_PURPOSE (t)); 4518857Srgrimes ggc_mark_tree (TREE_VALUE (t)); 4528857Srgrimes continue; 4532089Ssos 4542089Ssos case TREE_VEC: 4552089Ssos { 4562089Ssos int i = TREE_VEC_LENGTH (t); 4572089Ssos 4582089Ssos while (--i >= 0) 4592089Ssos ggc_mark_tree (TREE_VEC_ELT (t, i)); 46023457Sbrian continue; 46123457Sbrian } 46223457Sbrian 46323457Sbrian case COMPLEX_CST: 46423457Sbrian ggc_mark_tree (TREE_REALPART (t)); 46523457Sbrian ggc_mark_tree (TREE_IMAGPART (t)); 46630764Scharnier break; 46723457Sbrian 46823457Sbrian case PARM_DECL: 46923457Sbrian ggc_mark_rtx (DECL_INCOMING_RTL (t)); 47023457Sbrian break; 47151393Syokota 47230764Scharnier case FIELD_DECL: 47342605Smjacob ggc_mark_tree (DECL_FIELD_BIT_OFFSET (t)); 47430764Scharnier break; 47523457Sbrian 47623457Sbrian case IDENTIFIER_NODE: 47723457Sbrian lang_mark_tree (t); 4782089Ssos continue; 4792089Ssos 4802089Ssos default: 4812089Ssos break; 4822089Ssos } 4832089Ssos 4842089Ssos /* But in general we can handle them by class. */ 4852089Ssos switch (TREE_CODE_CLASS (code)) 4868857Srgrimes { 4872089Ssos case 'd': /* A decl node. */ 4882089Ssos ggc_mark_tree (DECL_SIZE (t)); 48916565Ssos ggc_mark_tree (DECL_SIZE_UNIT (t)); 49055849Syokota ggc_mark_tree (DECL_NAME (t)); 49155849Syokota ggc_mark_tree (DECL_CONTEXT (t)); 49255849Syokota ggc_mark_tree (DECL_ARGUMENTS (t)); 49355849Syokota ggc_mark_tree (DECL_RESULT_FLD (t)); 49455849Syokota ggc_mark_tree (DECL_INITIAL (t)); 49555849Syokota ggc_mark_tree (DECL_ABSTRACT_ORIGIN (t)); 49675788Sache ggc_mark_tree (DECL_SECTION_NAME (t)); 49775788Sache ggc_mark_tree (DECL_ATTRIBUTES (t)); 49855849Syokota if (DECL_RTL_SET_P (t)) 49955849Syokota ggc_mark_rtx (DECL_RTL (t)); 50055849Syokota ggc_mark_rtx (DECL_LIVE_RANGE_RTL (t)); 50155849Syokota ggc_mark_tree (DECL_VINDEX (t)); 50255849Syokota if (DECL_ASSEMBLER_NAME_SET_P (t)) 50355849Syokota ggc_mark_tree (DECL_ASSEMBLER_NAME (t)); 50455849Syokota if (TREE_CODE (t) == FUNCTION_DECL) 50555849Syokota { 50616565Ssos ggc_mark_tree (DECL_SAVED_TREE (t)); 50716565Ssos ggc_mark_tree (DECL_INLINED_FNS (t)); 50816565Ssos if (DECL_SAVED_INSNS (t)) 50916565Ssos ggc_mark_struct_function (DECL_SAVED_INSNS (t)); 51016565Ssos } 51116565Ssos lang_mark_tree (t); 51216565Ssos break; 51316565Ssos 51416565Ssos case 't': /* A type node. */ 51530764Scharnier ggc_mark_tree (TYPE_SIZE (t)); 51616565Ssos ggc_mark_tree (TYPE_SIZE_UNIT (t)); 51716565Ssos ggc_mark_tree (TYPE_ATTRIBUTES (t)); 51816565Ssos ggc_mark_tree (TYPE_VALUES (t)); 51916565Ssos ggc_mark_tree (TYPE_POINTER_TO (t)); 52016565Ssos ggc_mark_tree (TYPE_REFERENCE_TO (t)); 52139287Ssos ggc_mark_tree (TYPE_NAME (t)); 52239287Ssos ggc_mark_tree (TYPE_MIN_VALUE (t)); 52339287Ssos ggc_mark_tree (TYPE_MAX_VALUE (t)); 52439287Ssos ggc_mark_tree (TYPE_NEXT_VARIANT (t)); 52539287Ssos ggc_mark_tree (TYPE_MAIN_VARIANT (t)); 52639287Ssos ggc_mark_tree (TYPE_BINFO (t)); 52739287Ssos ggc_mark_tree (TYPE_CONTEXT (t)); 52839287Ssos lang_mark_tree (t); 52939287Ssos break; 53039287Ssos 53139287Ssos case 'b': /* A lexical block. */ 53239287Ssos ggc_mark_tree (BLOCK_VARS (t)); 53339287Ssos ggc_mark_tree (BLOCK_SUBBLOCKS (t)); 53448105Syokota ggc_mark_tree (BLOCK_SUPERCONTEXT (t)); 53539287Ssos ggc_mark_tree (BLOCK_ABSTRACT_ORIGIN (t)); 53639287Ssos break; 53739287Ssos 53839287Ssos case 'c': /* A constant. */ 53939287Ssos ggc_mark_rtx (TREE_CST_RTL (t)); 54039287Ssos break; 54139287Ssos 54239287Ssos case 'r': case '<': case '1': 54339287Ssos case '2': case 'e': case 's': /* Expressions. */ 54439287Ssos { 54523457Sbrian int i = TREE_CODE_LENGTH (TREE_CODE (t)); 54639287Ssos int first_rtl = first_rtl_op (TREE_CODE (t)); 54739287Ssos 54842505Syokota while (--i >= 0) 54939287Ssos { 55039287Ssos if (i >= first_rtl) 55139287Ssos ggc_mark_rtx ((rtx) TREE_OPERAND (t, i)); 55239287Ssos else 55339287Ssos ggc_mark_tree (TREE_OPERAND (t, i)); 55439287Ssos } 55539287Ssos break; 55642505Syokota } 55742505Syokota 55842505Syokota case 'x': 55939287Ssos lang_mark_tree (t); 56042505Syokota break; 56139287Ssos } 56239287Ssos } 56348105Syokota} 56448105Syokota 56548105Syokota/* Mark all the elements of the varray V, which contains rtxs. */ 56648105Syokota 56748105Syokotavoid 56848105Syokotaggc_mark_rtx_varray (v) 56948105Syokota varray_type v; 57039287Ssos{ 57139287Ssos int i; 57239287Ssos 57339287Ssos if (v) 57439287Ssos for (i = v->num_elements - 1; i >= 0; --i) 57539287Ssos ggc_mark_rtx (VARRAY_RTX (v, i)); 57639287Ssos} 57739287Ssos 57839287Ssos/* Mark all the elements of the varray V, which contains trees. */ 57939287Ssos 58039287Ssosvoid 58139287Ssosggc_mark_tree_varray (v) 58239287Ssos varray_type v; 58339287Ssos{ 58439287Ssos int i; 58539287Ssos 58639287Ssos if (v) 58739287Ssos for (i = v->num_elements - 1; i >= 0; --i) 58848105Syokota ggc_mark_tree (VARRAY_TREE (v, i)); 58948105Syokota} 59039287Ssos 59139287Ssos/* Mark the hash table-entry HE. Its key field is really a tree. */ 59239287Ssos 59339287Ssosstatic bool 59439287Ssosggc_mark_tree_hash_table_entry (he, k) 59539287Ssos struct hash_entry *he; 59639287Ssos hash_table_key k ATTRIBUTE_UNUSED; 59739287Ssos{ 59839287Ssos ggc_mark_tree ((tree) he->key); 59939287Ssos return true; 60039287Ssos} 60139287Ssos 60239287Ssos/* Mark all the elements of the hash-table H, which contains trees. */ 60339287Ssos 60439287Ssosvoid 60539287Ssosggc_mark_tree_hash_table (ht) 60639287Ssos struct hash_table *ht; 60739287Ssos{ 60843186Sdfr hash_traverse (ht, ggc_mark_tree_hash_table_entry, /*info=*/0); 60943186Sdfr} 61048105Syokota 61143186Sdfr/* Type-correct function to pass to ggc_add_root. It just forwards 61239287Ssos *ELT (which is an rtx) to ggc_mark_rtx. */ 61339287Ssos 61439287Ssosstatic void 61539287Ssosggc_mark_rtx_ptr (elt) 61639287Ssos void *elt; 61739287Ssos{ 61839287Ssos ggc_mark_rtx (*(rtx *) elt); 61939287Ssos} 62039287Ssos 62139287Ssos/* Type-correct function to pass to ggc_add_root. It just forwards 62239287Ssos *ELT (which is a tree) to ggc_mark_tree. */ 62339287Ssos 62439287Ssosstatic void 62539287Ssosggc_mark_tree_ptr (elt) 62639287Ssos void *elt; 62739287Ssos{ 62839287Ssos ggc_mark_tree (*(tree *) elt); 6292089Ssos} 6302089Ssos 6312089Ssos/* Type-correct function to pass to ggc_add_root. It just forwards 6322089Ssos ELT (which is really a varray_type *) to ggc_mark_rtx_varray. */ 6332089Ssos 6342089Ssosstatic void 6352089Ssosggc_mark_rtx_varray_ptr (elt) 6362089Ssos void *elt; 6372089Ssos{ 6388857Srgrimes ggc_mark_rtx_varray (*(varray_type *) elt); 6398857Srgrimes} 6402089Ssos 6412089Ssos/* Type-correct function to pass to ggc_add_root. It just forwards 6428857Srgrimes ELT (which is really a varray_type *) to ggc_mark_tree_varray. */ 6432089Ssos 6442089Ssosstatic void 6452089Ssosggc_mark_tree_varray_ptr (elt) 64676845Ssobomax void *elt; 64776845Ssobomax{ 64876845Ssobomax ggc_mark_tree_varray (*(varray_type *) elt); 64976845Ssobomax} 65076845Ssobomax 65176845Ssobomax/* Type-correct function to pass to ggc_add_root. It just forwards 65276845Ssobomax ELT (which is really a struct hash_table **) to 65376845Ssobomax ggc_mark_tree_hash_table. */ 65476845Ssobomax 65576845Ssobomaxstatic void 65676845Ssobomaxggc_mark_tree_hash_table_ptr (elt) 65776845Ssobomax void *elt; 65876845Ssobomax{ 65976845Ssobomax ggc_mark_tree_hash_table (*(struct hash_table **) elt); 66076845Ssobomax} 66176845Ssobomax 66276845Ssobomax/* Allocate a block of memory, then clear it. */ 66376845Ssobomaxvoid * 66476845Ssobomaxggc_alloc_cleared (size) 66576845Ssobomax size_t size; 66676845Ssobomax{ 66776845Ssobomax void *buf = ggc_alloc (size); 66876845Ssobomax memset (buf, 0, size); 66976845Ssobomax return buf; 67076845Ssobomax} 67176845Ssobomax 67276845Ssobomax/* Print statistics that are independent of the collector in use. */ 67376845Ssobomax#define SCALE(x) ((unsigned long) ((x) < 1024*10 \ 67476845Ssobomax ? (x) \ 67576845Ssobomax : ((x) < 1024*1024*10 \ 67676845Ssobomax ? (x) / 1024 \ 67776845Ssobomax : (x) / (1024*1024)))) 67876845Ssobomax#define LABEL(x) ((x) < 1024*10 ? ' ' : ((x) < 1024*1024*10 ? 'k' : 'M')) 67976845Ssobomax 68076845Ssobomaxvoid 68176845Ssobomaxggc_print_common_statistics (stream, stats) 68276845Ssobomax FILE *stream; 68376845Ssobomax ggc_statistics *stats; 68476845Ssobomax{ 68576845Ssobomax int code; 68676845Ssobomax 68776845Ssobomax /* Set the pointer so that during collection we will actually gather 68876845Ssobomax the statistics. */ 68976845Ssobomax ggc_stats = stats; 69076845Ssobomax 69176845Ssobomax /* Then do one collection to fill in the statistics. */ 69276845Ssobomax ggc_collect (); 69376845Ssobomax 69476845Ssobomax /* Total the statistics. */ 69576845Ssobomax for (code = 0; code < MAX_TREE_CODES; ++code) 69676845Ssobomax { 69776845Ssobomax stats->total_num_trees += stats->num_trees[code]; 69876845Ssobomax stats->total_size_trees += stats->size_trees[code]; 69976845Ssobomax } 70076845Ssobomax for (code = 0; code < NUM_RTX_CODE; ++code) 70176845Ssobomax { 70276845Ssobomax stats->total_num_rtxs += stats->num_rtxs[code]; 70376845Ssobomax stats->total_size_rtxs += stats->size_rtxs[code]; 70476845Ssobomax } 70576845Ssobomax 70676845Ssobomax /* Print the statistics for trees. */ 70776845Ssobomax fprintf (stream, "\n%-17s%10s %16s %10s\n", "Tree", 70876845Ssobomax "Number", "Bytes", "% Total"); 70976845Ssobomax for (code = 0; code < MAX_TREE_CODES; ++code) 71076845Ssobomax if (ggc_stats->num_trees[code]) 71176845Ssobomax { 71276845Ssobomax fprintf (stream, "%-17s%10u%16ld%c %10.3f\n", 71376845Ssobomax tree_code_name[code], 71476845Ssobomax ggc_stats->num_trees[code], 71576845Ssobomax SCALE (ggc_stats->size_trees[code]), 71676845Ssobomax LABEL (ggc_stats->size_trees[code]), 71777329Sdes (100 * ((double) ggc_stats->size_trees[code]) 71877329Sdes / ggc_stats->total_size_trees)); 71977329Sdes } 72077329Sdes fprintf (stream, 72177329Sdes "%-17s%10u%16ld%c\n", "Total", 72277329Sdes ggc_stats->total_num_trees, 72377329Sdes SCALE (ggc_stats->total_size_trees), 72477329Sdes LABEL (ggc_stats->total_size_trees)); 72577329Sdes 72677329Sdes /* Print the statistics for RTL. */ 72777329Sdes fprintf (stream, "\n%-17s%10s %16s %10s\n", "RTX", 72877329Sdes "Number", "Bytes", "% Total"); 72977329Sdes for (code = 0; code < NUM_RTX_CODE; ++code) 73077329Sdes if (ggc_stats->num_rtxs[code]) 73177329Sdes { 73277329Sdes fprintf (stream, "%-17s%10u%16ld%c %10.3f\n", 73377329Sdes rtx_name[code], 73477329Sdes ggc_stats->num_rtxs[code], 73577329Sdes SCALE (ggc_stats->size_rtxs[code]), 73677329Sdes LABEL (ggc_stats->size_rtxs[code]), 73777329Sdes (100 * ((double) ggc_stats->size_rtxs[code]) 73877329Sdes / ggc_stats->total_size_rtxs)); 73923457Sbrian } 7402089Ssos fprintf (stream, 7412089Ssos "%-17s%10u%16ld%c\n", "Total", 74275344Ssobomax ggc_stats->total_num_rtxs, 74375344Ssobomax SCALE (ggc_stats->total_size_rtxs), 7442089Ssos LABEL (ggc_stats->total_size_rtxs)); 7458857Srgrimes 7462089Ssos /* Don't gather statistics any more. */ 74776897Ssobomax ggc_stats = NULL; 74876897Ssobomax} 74976897Ssobomax