ggc-common.c revision 90075
190075Sobrien/* Simple garbage collection for the GNU compiler. 290075Sobrien Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. 390075Sobrien 490075SobrienThis file is part of GCC. 590075Sobrien 690075SobrienGCC is free software; you can redistribute it and/or modify it under 790075Sobrienthe terms of the GNU General Public License as published by the Free 890075SobrienSoftware Foundation; either version 2, or (at your option) any later 990075Sobrienversion. 1090075Sobrien 1190075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY 1290075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or 1390075SobrienFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1490075Sobrienfor more details. 1590075Sobrien 1690075SobrienYou should have received a copy of the GNU General Public License 1790075Sobrienalong with GCC; see the file COPYING. If not, write to the Free 1890075SobrienSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA 1990075Sobrien02111-1307, USA. */ 2090075Sobrien 2190075Sobrien/* Generic garbage collection (GC) functions and data, not specific to 2290075Sobrien any particular GC implementation. */ 2390075Sobrien 2490075Sobrien#include "config.h" 2590075Sobrien#include "system.h" 2690075Sobrien#include "rtl.h" 2790075Sobrien#include "tree.h" 2890075Sobrien#include "tm_p.h" 2990075Sobrien#include "hash.h" 3090075Sobrien#include "hashtab.h" 3190075Sobrien#include "varray.h" 3290075Sobrien#include "ggc.h" 3390075Sobrien 3490075Sobrien/* Statistics about the allocation. */ 3590075Sobrienstatic ggc_statistics *ggc_stats; 3690075Sobrien 3790075Sobrien/* The FALSE_LABEL_STACK, declared in except.h, has language-dependent 3890075Sobrien semantics. If a front-end needs to mark the false label stack, it 3990075Sobrien should set this pointer to a non-NULL value. Otherwise, no marking 4090075Sobrien will be done. */ 4190075Sobrienvoid (*lang_mark_false_label_stack) PARAMS ((struct label_node *)); 4290075Sobrien 4390075Sobrien/* Trees that have been marked, but whose children still need marking. */ 4490075Sobrienvarray_type ggc_pending_trees; 4590075Sobrien 4690075Sobrienstatic void ggc_mark_rtx_ptr PARAMS ((void *)); 4790075Sobrienstatic void ggc_mark_tree_ptr PARAMS ((void *)); 4890075Sobrienstatic void ggc_mark_rtx_varray_ptr PARAMS ((void *)); 4990075Sobrienstatic void ggc_mark_tree_varray_ptr PARAMS ((void *)); 5090075Sobrienstatic void ggc_mark_tree_hash_table_ptr PARAMS ((void *)); 5190075Sobrienstatic int ggc_htab_delete PARAMS ((void **, void *)); 5290075Sobrienstatic void ggc_mark_trees PARAMS ((void)); 5390075Sobrienstatic bool ggc_mark_tree_hash_table_entry PARAMS ((struct hash_entry *, 5490075Sobrien hash_table_key)); 5590075Sobrien 5690075Sobrien/* Maintain global roots that are preserved during GC. */ 5790075Sobrien 5890075Sobrien/* Global roots that are preserved during calls to gc. */ 5990075Sobrien 6090075Sobrienstruct ggc_root 6190075Sobrien{ 6290075Sobrien struct ggc_root *next; 6390075Sobrien void *base; 6490075Sobrien int nelt; 6590075Sobrien int size; 6690075Sobrien void (*cb) PARAMS ((void *)); 6790075Sobrien}; 6890075Sobrien 6990075Sobrienstatic struct ggc_root *roots; 7090075Sobrien 7190075Sobrien/* Add BASE as a new garbage collection root. It is an array of 7290075Sobrien length NELT with each element SIZE bytes long. CB is a 7390075Sobrien function that will be called with a pointer to each element 7490075Sobrien of the array; it is the intention that CB call the appropriate 7590075Sobrien routine to mark gc-able memory for that element. */ 7690075Sobrien 7790075Sobrienvoid 7890075Sobrienggc_add_root (base, nelt, size, cb) 7990075Sobrien void *base; 8090075Sobrien int nelt, size; 8190075Sobrien void (*cb) PARAMS ((void *)); 8290075Sobrien{ 8390075Sobrien struct ggc_root *x = (struct ggc_root *) xmalloc (sizeof (*x)); 8490075Sobrien 8590075Sobrien x->next = roots; 8690075Sobrien x->base = base; 8790075Sobrien x->nelt = nelt; 8890075Sobrien x->size = size; 8990075Sobrien x->cb = cb; 9090075Sobrien 9190075Sobrien roots = x; 9290075Sobrien} 9390075Sobrien 9490075Sobrien/* Register an array of rtx as a GC root. */ 9590075Sobrien 9690075Sobrienvoid 9790075Sobrienggc_add_rtx_root (base, nelt) 9890075Sobrien rtx *base; 9990075Sobrien int nelt; 10090075Sobrien{ 10190075Sobrien ggc_add_root (base, nelt, sizeof (rtx), ggc_mark_rtx_ptr); 10290075Sobrien} 10390075Sobrien 10490075Sobrien/* Register an array of trees as a GC root. */ 10590075Sobrien 10690075Sobrienvoid 10790075Sobrienggc_add_tree_root (base, nelt) 10890075Sobrien tree *base; 10990075Sobrien int nelt; 11090075Sobrien{ 11190075Sobrien ggc_add_root (base, nelt, sizeof (tree), ggc_mark_tree_ptr); 11290075Sobrien} 11390075Sobrien 11490075Sobrien/* Register a varray of rtxs as a GC root. */ 11590075Sobrien 11690075Sobrienvoid 11790075Sobrienggc_add_rtx_varray_root (base, nelt) 11890075Sobrien varray_type *base; 11990075Sobrien int nelt; 12090075Sobrien{ 12190075Sobrien ggc_add_root (base, nelt, sizeof (varray_type), 12290075Sobrien ggc_mark_rtx_varray_ptr); 12390075Sobrien} 12490075Sobrien 12590075Sobrien/* Register a varray of trees as a GC root. */ 12690075Sobrien 12790075Sobrienvoid 12890075Sobrienggc_add_tree_varray_root (base, nelt) 12990075Sobrien varray_type *base; 13090075Sobrien int nelt; 13190075Sobrien{ 13290075Sobrien ggc_add_root (base, nelt, sizeof (varray_type), 13390075Sobrien ggc_mark_tree_varray_ptr); 13490075Sobrien} 13590075Sobrien 13690075Sobrien/* Register a hash table of trees as a GC root. */ 13790075Sobrien 13890075Sobrienvoid 13990075Sobrienggc_add_tree_hash_table_root (base, nelt) 14090075Sobrien struct hash_table **base; 14190075Sobrien int nelt; 14290075Sobrien{ 14390075Sobrien ggc_add_root (base, nelt, sizeof (struct hash_table *), 14490075Sobrien ggc_mark_tree_hash_table_ptr); 14590075Sobrien} 14690075Sobrien 14790075Sobrien/* Remove the previously registered GC root at BASE. */ 14890075Sobrien 14990075Sobrienvoid 15090075Sobrienggc_del_root (base) 15190075Sobrien void *base; 15290075Sobrien{ 15390075Sobrien struct ggc_root *x, **p; 15490075Sobrien 15590075Sobrien p = &roots, x = roots; 15690075Sobrien while (x) 15790075Sobrien { 15890075Sobrien if (x->base == base) 15990075Sobrien { 16090075Sobrien *p = x->next; 16190075Sobrien free (x); 16290075Sobrien return; 16390075Sobrien } 16490075Sobrien p = &x->next; 16590075Sobrien x = x->next; 16690075Sobrien } 16790075Sobrien 16890075Sobrien abort (); 16990075Sobrien} 17090075Sobrien 17190075Sobrien/* Add a hash table to be scanned when all roots have been processed. We 17290075Sobrien delete any entry in the table that has not been marked. */ 17390075Sobrien 17490075Sobrienstruct d_htab_root 17590075Sobrien{ 17690075Sobrien struct d_htab_root *next; 17790075Sobrien htab_t htab; 17890075Sobrien ggc_htab_marked_p marked_p; 17990075Sobrien ggc_htab_mark mark; 18090075Sobrien}; 18190075Sobrien 18290075Sobrienstatic struct d_htab_root *d_htab_roots; 18390075Sobrien 18490075Sobrien/* Add X, an htab, to a list of htabs that contain objects which are allocated 18590075Sobrien from GC memory. Once all other roots are marked, we check each object in 18690075Sobrien the htab to see if it has already been marked. If not, it is deleted. 18790075Sobrien 18890075Sobrien MARKED_P, if specified, is a function that returns 1 if the entry is to 18990075Sobrien be considered as "marked". If not present, the data structure pointed to 19090075Sobrien by the htab slot is tested. This function should be supplied if some 19190075Sobrien other object (such as something pointed to by that object) should be tested 19290075Sobrien in which case the function tests whether that object (or objects) are 19390075Sobrien marked (using ggc_marked_p) and returns nonzero if it is. 19490075Sobrien 19590075Sobrien MARK, if specified, is a function that is passed the contents of a slot 19690075Sobrien that has been determined to have been "marked" (via the above function) 19790075Sobrien and marks any other objects pointed to by that object. For example, 19890075Sobrien we might have a hash table of memory attribute blocks, which are pointed 19990075Sobrien to by a MEM RTL but have a pointer to a DECL. MARKED_P in that case will 20090075Sobrien not be specified because we want to know if the attribute block is pointed 20190075Sobrien to by the MEM, but MARK must be specified because if the block has been 20290075Sobrien marked, we need to mark the DECL. */ 20390075Sobrien 20490075Sobrienvoid 20590075Sobrienggc_add_deletable_htab (x, marked_p, mark) 20690075Sobrien PTR x; 20790075Sobrien ggc_htab_marked_p marked_p; 20890075Sobrien ggc_htab_mark mark; 20990075Sobrien{ 21090075Sobrien struct d_htab_root *r 21190075Sobrien = (struct d_htab_root *) xmalloc (sizeof (struct d_htab_root)); 21290075Sobrien 21390075Sobrien r->next = d_htab_roots; 21490075Sobrien r->htab = (htab_t) x; 21590075Sobrien r->marked_p = marked_p ? marked_p : ggc_marked_p; 21690075Sobrien r->mark = mark; 21790075Sobrien d_htab_roots = r; 21890075Sobrien} 21990075Sobrien 22090075Sobrien/* Process a slot of an htab by deleting it if it has not been marked. */ 22190075Sobrien 22290075Sobrienstatic int 22390075Sobrienggc_htab_delete (slot, info) 22490075Sobrien void **slot; 22590075Sobrien void *info; 22690075Sobrien{ 22790075Sobrien struct d_htab_root *r = (struct d_htab_root *) info; 22890075Sobrien 22990075Sobrien if (! (*r->marked_p) (*slot)) 23090075Sobrien htab_clear_slot (r->htab, slot); 23190075Sobrien else if (r->mark) 23290075Sobrien (*r->mark) (*slot); 23390075Sobrien 23490075Sobrien return 1; 23590075Sobrien} 23690075Sobrien 23790075Sobrien/* Iterate through all registered roots and mark each element. */ 23890075Sobrien 23990075Sobrienvoid 24090075Sobrienggc_mark_roots () 24190075Sobrien{ 24290075Sobrien struct ggc_root *x; 24390075Sobrien struct d_htab_root *y; 24490075Sobrien 24590075Sobrien VARRAY_TREE_INIT (ggc_pending_trees, 4096, "ggc_pending_trees"); 24690075Sobrien 24790075Sobrien for (x = roots; x != NULL; x = x->next) 24890075Sobrien { 24990075Sobrien char *elt = x->base; 25090075Sobrien int s = x->size, n = x->nelt; 25190075Sobrien void (*cb) PARAMS ((void *)) = x->cb; 25290075Sobrien int i; 25390075Sobrien 25490075Sobrien for (i = 0; i < n; ++i, elt += s) 25590075Sobrien (*cb)(elt); 25690075Sobrien } 25790075Sobrien 25890075Sobrien /* Mark all the queued up trees, and their children. */ 25990075Sobrien ggc_mark_trees (); 26090075Sobrien VARRAY_FREE (ggc_pending_trees); 26190075Sobrien 26290075Sobrien /* Now scan all hash tables that have objects which are to be deleted if 26390075Sobrien they are not already marked. Since these may mark more trees, we need 26490075Sobrien to reinitialize that varray. */ 26590075Sobrien VARRAY_TREE_INIT (ggc_pending_trees, 1024, "ggc_pending_trees"); 26690075Sobrien 26790075Sobrien for (y = d_htab_roots; y != NULL; y = y->next) 26890075Sobrien htab_traverse (y->htab, ggc_htab_delete, (PTR) y); 26990075Sobrien ggc_mark_trees (); 27090075Sobrien VARRAY_FREE (ggc_pending_trees); 27190075Sobrien} 27290075Sobrien 27390075Sobrien/* R had not been previously marked, but has now been marked via 27490075Sobrien ggc_set_mark. Now recurse and process the children. */ 27590075Sobrien 27690075Sobrienvoid 27790075Sobrienggc_mark_rtx_children (r) 27890075Sobrien rtx r; 27990075Sobrien{ 28090075Sobrien const char *fmt; 28190075Sobrien int i; 28290075Sobrien rtx next_rtx; 28390075Sobrien 28490075Sobrien do 28590075Sobrien { 28690075Sobrien enum rtx_code code = GET_CODE (r); 28790075Sobrien /* This gets set to a child rtx to eliminate tail recursion. */ 28890075Sobrien next_rtx = NULL; 28990075Sobrien 29090075Sobrien /* Collect statistics, if appropriate. */ 29190075Sobrien if (ggc_stats) 29290075Sobrien { 29390075Sobrien ++ggc_stats->num_rtxs[(int) code]; 29490075Sobrien ggc_stats->size_rtxs[(int) code] += ggc_get_size (r); 29590075Sobrien } 29690075Sobrien 29790075Sobrien /* ??? If (some of) these are really pass-dependent info, do we 29890075Sobrien have any right poking our noses in? */ 29990075Sobrien switch (code) 30090075Sobrien { 30190075Sobrien case MEM: 30290075Sobrien ggc_mark (MEM_ATTRS (r)); 30390075Sobrien break; 30490075Sobrien case JUMP_INSN: 30590075Sobrien ggc_mark_rtx (JUMP_LABEL (r)); 30690075Sobrien break; 30790075Sobrien case CODE_LABEL: 30890075Sobrien ggc_mark_rtx (LABEL_REFS (r)); 30990075Sobrien break; 31090075Sobrien case LABEL_REF: 31190075Sobrien ggc_mark_rtx (LABEL_NEXTREF (r)); 31290075Sobrien ggc_mark_rtx (CONTAINING_INSN (r)); 31390075Sobrien break; 31490075Sobrien case ADDRESSOF: 31590075Sobrien ggc_mark_tree (ADDRESSOF_DECL (r)); 31690075Sobrien break; 31790075Sobrien case CONST_DOUBLE: 31890075Sobrien ggc_mark_rtx (CONST_DOUBLE_CHAIN (r)); 31990075Sobrien break; 32090075Sobrien case NOTE: 32190075Sobrien switch (NOTE_LINE_NUMBER (r)) 32290075Sobrien { 32390075Sobrien case NOTE_INSN_RANGE_BEG: 32490075Sobrien case NOTE_INSN_RANGE_END: 32590075Sobrien case NOTE_INSN_LIVE: 32690075Sobrien case NOTE_INSN_EXPECTED_VALUE: 32790075Sobrien ggc_mark_rtx (NOTE_RANGE_INFO (r)); 32890075Sobrien break; 32990075Sobrien 33090075Sobrien case NOTE_INSN_BLOCK_BEG: 33190075Sobrien case NOTE_INSN_BLOCK_END: 33290075Sobrien ggc_mark_tree (NOTE_BLOCK (r)); 33390075Sobrien break; 33490075Sobrien 33590075Sobrien default: 33690075Sobrien break; 33790075Sobrien } 33890075Sobrien break; 33990075Sobrien 34090075Sobrien default: 34190075Sobrien break; 34290075Sobrien } 34390075Sobrien 34490075Sobrien for (fmt = GET_RTX_FORMAT (GET_CODE (r)), i = 0; *fmt ; ++fmt, ++i) 34590075Sobrien { 34690075Sobrien rtx exp; 34790075Sobrien switch (*fmt) 34890075Sobrien { 34990075Sobrien case 'e': case 'u': 35090075Sobrien exp = XEXP (r, i); 35190075Sobrien if (ggc_test_and_set_mark (exp)) 35290075Sobrien { 35390075Sobrien if (next_rtx == NULL) 35490075Sobrien next_rtx = exp; 35590075Sobrien else 35690075Sobrien ggc_mark_rtx_children (exp); 35790075Sobrien } 35890075Sobrien break; 35990075Sobrien case 'V': case 'E': 36090075Sobrien ggc_mark_rtvec (XVEC (r, i)); 36190075Sobrien break; 36290075Sobrien } 36390075Sobrien } 36490075Sobrien } 36590075Sobrien while ((r = next_rtx) != NULL); 36690075Sobrien} 36790075Sobrien 36890075Sobrien/* V had not been previously marked, but has now been marked via 36990075Sobrien ggc_set_mark. Now recurse and process the children. */ 37090075Sobrien 37190075Sobrienvoid 37290075Sobrienggc_mark_rtvec_children (v) 37390075Sobrien rtvec v; 37490075Sobrien{ 37590075Sobrien int i; 37690075Sobrien 37790075Sobrien i = GET_NUM_ELEM (v); 37890075Sobrien while (--i >= 0) 37990075Sobrien ggc_mark_rtx (RTVEC_ELT (v, i)); 38090075Sobrien} 38190075Sobrien 38290075Sobrien/* Recursively set marks on all of the children of the 38390075Sobrien GCC_PENDING_TREES. */ 38490075Sobrien 38590075Sobrienstatic void 38690075Sobrienggc_mark_trees () 38790075Sobrien{ 38890075Sobrien while (ggc_pending_trees->elements_used) 38990075Sobrien { 39090075Sobrien tree t; 39190075Sobrien enum tree_code code; 39290075Sobrien 39390075Sobrien t = VARRAY_TOP_TREE (ggc_pending_trees); 39490075Sobrien VARRAY_POP (ggc_pending_trees); 39590075Sobrien code = TREE_CODE (t); 39690075Sobrien 39790075Sobrien /* Collect statistics, if appropriate. */ 39890075Sobrien if (ggc_stats) 39990075Sobrien { 40090075Sobrien ++ggc_stats->num_trees[(int) code]; 40190075Sobrien ggc_stats->size_trees[(int) code] += ggc_get_size (t); 40290075Sobrien } 40390075Sobrien 40490075Sobrien /* Bits from common. */ 40590075Sobrien ggc_mark_tree (TREE_TYPE (t)); 40690075Sobrien ggc_mark_tree (TREE_CHAIN (t)); 40790075Sobrien 40890075Sobrien /* Some nodes require special handling. */ 40990075Sobrien switch (code) 41090075Sobrien { 41190075Sobrien case TREE_LIST: 41290075Sobrien ggc_mark_tree (TREE_PURPOSE (t)); 41390075Sobrien ggc_mark_tree (TREE_VALUE (t)); 41490075Sobrien continue; 41590075Sobrien 41690075Sobrien case TREE_VEC: 41790075Sobrien { 41890075Sobrien int i = TREE_VEC_LENGTH (t); 41990075Sobrien 42090075Sobrien while (--i >= 0) 42190075Sobrien ggc_mark_tree (TREE_VEC_ELT (t, i)); 42290075Sobrien continue; 42390075Sobrien } 42490075Sobrien 42590075Sobrien case COMPLEX_CST: 42690075Sobrien ggc_mark_tree (TREE_REALPART (t)); 42790075Sobrien ggc_mark_tree (TREE_IMAGPART (t)); 42890075Sobrien break; 42990075Sobrien 43090075Sobrien case PARM_DECL: 43190075Sobrien ggc_mark_rtx (DECL_INCOMING_RTL (t)); 43290075Sobrien break; 43390075Sobrien 43490075Sobrien case FIELD_DECL: 43590075Sobrien ggc_mark_tree (DECL_FIELD_BIT_OFFSET (t)); 43690075Sobrien break; 43790075Sobrien 43890075Sobrien case IDENTIFIER_NODE: 43990075Sobrien lang_mark_tree (t); 44090075Sobrien continue; 44190075Sobrien 44290075Sobrien default: 44390075Sobrien break; 44490075Sobrien } 44590075Sobrien 44690075Sobrien /* But in general we can handle them by class. */ 44790075Sobrien switch (TREE_CODE_CLASS (code)) 44890075Sobrien { 44990075Sobrien case 'd': /* A decl node. */ 45090075Sobrien ggc_mark_tree (DECL_SIZE (t)); 45190075Sobrien ggc_mark_tree (DECL_SIZE_UNIT (t)); 45290075Sobrien ggc_mark_tree (DECL_NAME (t)); 45390075Sobrien ggc_mark_tree (DECL_CONTEXT (t)); 45490075Sobrien ggc_mark_tree (DECL_ARGUMENTS (t)); 45590075Sobrien ggc_mark_tree (DECL_RESULT_FLD (t)); 45690075Sobrien ggc_mark_tree (DECL_INITIAL (t)); 45790075Sobrien ggc_mark_tree (DECL_ABSTRACT_ORIGIN (t)); 45890075Sobrien ggc_mark_tree (DECL_SECTION_NAME (t)); 45990075Sobrien ggc_mark_tree (DECL_ATTRIBUTES (t)); 46090075Sobrien if (DECL_RTL_SET_P (t)) 46190075Sobrien ggc_mark_rtx (DECL_RTL (t)); 46290075Sobrien ggc_mark_rtx (DECL_LIVE_RANGE_RTL (t)); 46390075Sobrien ggc_mark_tree (DECL_VINDEX (t)); 46490075Sobrien if (DECL_ASSEMBLER_NAME_SET_P (t)) 46590075Sobrien ggc_mark_tree (DECL_ASSEMBLER_NAME (t)); 46690075Sobrien if (TREE_CODE (t) == FUNCTION_DECL) 46790075Sobrien { 46890075Sobrien ggc_mark_tree (DECL_SAVED_TREE (t)); 46990075Sobrien ggc_mark_tree (DECL_INLINED_FNS (t)); 47090075Sobrien if (DECL_SAVED_INSNS (t)) 47190075Sobrien ggc_mark_struct_function (DECL_SAVED_INSNS (t)); 47290075Sobrien } 47390075Sobrien lang_mark_tree (t); 47490075Sobrien break; 47590075Sobrien 47690075Sobrien case 't': /* A type node. */ 47790075Sobrien ggc_mark_tree (TYPE_SIZE (t)); 47890075Sobrien ggc_mark_tree (TYPE_SIZE_UNIT (t)); 47990075Sobrien ggc_mark_tree (TYPE_ATTRIBUTES (t)); 48090075Sobrien ggc_mark_tree (TYPE_VALUES (t)); 48190075Sobrien ggc_mark_tree (TYPE_POINTER_TO (t)); 48290075Sobrien ggc_mark_tree (TYPE_REFERENCE_TO (t)); 48390075Sobrien ggc_mark_tree (TYPE_NAME (t)); 48490075Sobrien ggc_mark_tree (TYPE_MIN_VALUE (t)); 48590075Sobrien ggc_mark_tree (TYPE_MAX_VALUE (t)); 48690075Sobrien ggc_mark_tree (TYPE_NEXT_VARIANT (t)); 48790075Sobrien ggc_mark_tree (TYPE_MAIN_VARIANT (t)); 48890075Sobrien ggc_mark_tree (TYPE_BINFO (t)); 48990075Sobrien ggc_mark_tree (TYPE_CONTEXT (t)); 49090075Sobrien lang_mark_tree (t); 49190075Sobrien break; 49290075Sobrien 49390075Sobrien case 'b': /* A lexical block. */ 49490075Sobrien ggc_mark_tree (BLOCK_VARS (t)); 49590075Sobrien ggc_mark_tree (BLOCK_SUBBLOCKS (t)); 49690075Sobrien ggc_mark_tree (BLOCK_SUPERCONTEXT (t)); 49790075Sobrien ggc_mark_tree (BLOCK_ABSTRACT_ORIGIN (t)); 49890075Sobrien break; 49990075Sobrien 50090075Sobrien case 'c': /* A constant. */ 50190075Sobrien ggc_mark_rtx (TREE_CST_RTL (t)); 50290075Sobrien break; 50390075Sobrien 50490075Sobrien case 'r': case '<': case '1': 50590075Sobrien case '2': case 'e': case 's': /* Expressions. */ 50690075Sobrien { 50790075Sobrien int i = TREE_CODE_LENGTH (TREE_CODE (t)); 50890075Sobrien int first_rtl = first_rtl_op (TREE_CODE (t)); 50990075Sobrien 51090075Sobrien while (--i >= 0) 51190075Sobrien { 51290075Sobrien if (i >= first_rtl) 51390075Sobrien ggc_mark_rtx ((rtx) TREE_OPERAND (t, i)); 51490075Sobrien else 51590075Sobrien ggc_mark_tree (TREE_OPERAND (t, i)); 51690075Sobrien } 51790075Sobrien break; 51890075Sobrien } 51990075Sobrien 52090075Sobrien case 'x': 52190075Sobrien lang_mark_tree (t); 52290075Sobrien break; 52390075Sobrien } 52490075Sobrien } 52590075Sobrien} 52690075Sobrien 52790075Sobrien/* Mark all the elements of the varray V, which contains rtxs. */ 52890075Sobrien 52990075Sobrienvoid 53090075Sobrienggc_mark_rtx_varray (v) 53190075Sobrien varray_type v; 53290075Sobrien{ 53390075Sobrien int i; 53490075Sobrien 53590075Sobrien if (v) 53690075Sobrien for (i = v->num_elements - 1; i >= 0; --i) 53790075Sobrien ggc_mark_rtx (VARRAY_RTX (v, i)); 53890075Sobrien} 53990075Sobrien 54090075Sobrien/* Mark all the elements of the varray V, which contains trees. */ 54190075Sobrien 54290075Sobrienvoid 54390075Sobrienggc_mark_tree_varray (v) 54490075Sobrien varray_type v; 54590075Sobrien{ 54690075Sobrien int i; 54790075Sobrien 54890075Sobrien if (v) 54990075Sobrien for (i = v->num_elements - 1; i >= 0; --i) 55090075Sobrien ggc_mark_tree (VARRAY_TREE (v, i)); 55190075Sobrien} 55290075Sobrien 55390075Sobrien/* Mark the hash table-entry HE. Its key field is really a tree. */ 55490075Sobrien 55590075Sobrienstatic bool 55690075Sobrienggc_mark_tree_hash_table_entry (he, k) 55790075Sobrien struct hash_entry *he; 55890075Sobrien hash_table_key k ATTRIBUTE_UNUSED; 55990075Sobrien{ 56090075Sobrien ggc_mark_tree ((tree) he->key); 56190075Sobrien return true; 56290075Sobrien} 56390075Sobrien 56490075Sobrien/* Mark all the elements of the hash-table H, which contains trees. */ 56590075Sobrien 56690075Sobrienvoid 56790075Sobrienggc_mark_tree_hash_table (ht) 56890075Sobrien struct hash_table *ht; 56990075Sobrien{ 57090075Sobrien hash_traverse (ht, ggc_mark_tree_hash_table_entry, /*info=*/0); 57190075Sobrien} 57290075Sobrien 57390075Sobrien/* Type-correct function to pass to ggc_add_root. It just forwards 57490075Sobrien *ELT (which is an rtx) to ggc_mark_rtx. */ 57590075Sobrien 57690075Sobrienstatic void 57790075Sobrienggc_mark_rtx_ptr (elt) 57890075Sobrien void *elt; 57990075Sobrien{ 58090075Sobrien ggc_mark_rtx (*(rtx *) elt); 58190075Sobrien} 58290075Sobrien 58390075Sobrien/* Type-correct function to pass to ggc_add_root. It just forwards 58490075Sobrien *ELT (which is a tree) to ggc_mark_tree. */ 58590075Sobrien 58690075Sobrienstatic void 58790075Sobrienggc_mark_tree_ptr (elt) 58890075Sobrien void *elt; 58990075Sobrien{ 59090075Sobrien ggc_mark_tree (*(tree *) elt); 59190075Sobrien} 59290075Sobrien 59390075Sobrien/* Type-correct function to pass to ggc_add_root. It just forwards 59490075Sobrien ELT (which is really a varray_type *) to ggc_mark_rtx_varray. */ 59590075Sobrien 59690075Sobrienstatic void 59790075Sobrienggc_mark_rtx_varray_ptr (elt) 59890075Sobrien void *elt; 59990075Sobrien{ 60090075Sobrien ggc_mark_rtx_varray (*(varray_type *) elt); 60190075Sobrien} 60290075Sobrien 60390075Sobrien/* Type-correct function to pass to ggc_add_root. It just forwards 60490075Sobrien ELT (which is really a varray_type *) to ggc_mark_tree_varray. */ 60590075Sobrien 60690075Sobrienstatic void 60790075Sobrienggc_mark_tree_varray_ptr (elt) 60890075Sobrien void *elt; 60990075Sobrien{ 61090075Sobrien ggc_mark_tree_varray (*(varray_type *) elt); 61190075Sobrien} 61290075Sobrien 61390075Sobrien/* Type-correct function to pass to ggc_add_root. It just forwards 61490075Sobrien ELT (which is really a struct hash_table **) to 61590075Sobrien ggc_mark_tree_hash_table. */ 61690075Sobrien 61790075Sobrienstatic void 61890075Sobrienggc_mark_tree_hash_table_ptr (elt) 61990075Sobrien void *elt; 62090075Sobrien{ 62190075Sobrien ggc_mark_tree_hash_table (*(struct hash_table **) elt); 62290075Sobrien} 62390075Sobrien 62490075Sobrien/* Allocate a block of memory, then clear it. */ 62590075Sobrienvoid * 62690075Sobrienggc_alloc_cleared (size) 62790075Sobrien size_t size; 62890075Sobrien{ 62990075Sobrien void *buf = ggc_alloc (size); 63090075Sobrien memset (buf, 0, size); 63190075Sobrien return buf; 63290075Sobrien} 63390075Sobrien 63490075Sobrien/* Print statistics that are independent of the collector in use. */ 63590075Sobrien#define SCALE(x) ((unsigned long) ((x) < 1024*10 \ 63690075Sobrien ? (x) \ 63790075Sobrien : ((x) < 1024*1024*10 \ 63890075Sobrien ? (x) / 1024 \ 63990075Sobrien : (x) / (1024*1024)))) 64090075Sobrien#define LABEL(x) ((x) < 1024*10 ? ' ' : ((x) < 1024*1024*10 ? 'k' : 'M')) 64190075Sobrien 64290075Sobrienvoid 64390075Sobrienggc_print_common_statistics (stream, stats) 64490075Sobrien FILE *stream; 64590075Sobrien ggc_statistics *stats; 64690075Sobrien{ 64790075Sobrien int code; 64890075Sobrien 64990075Sobrien /* Set the pointer so that during collection we will actually gather 65090075Sobrien the statistics. */ 65190075Sobrien ggc_stats = stats; 65290075Sobrien 65390075Sobrien /* Then do one collection to fill in the statistics. */ 65490075Sobrien ggc_collect (); 65590075Sobrien 65690075Sobrien /* Total the statistics. */ 65790075Sobrien for (code = 0; code < MAX_TREE_CODES; ++code) 65890075Sobrien { 65990075Sobrien stats->total_num_trees += stats->num_trees[code]; 66090075Sobrien stats->total_size_trees += stats->size_trees[code]; 66190075Sobrien } 66290075Sobrien for (code = 0; code < NUM_RTX_CODE; ++code) 66390075Sobrien { 66490075Sobrien stats->total_num_rtxs += stats->num_rtxs[code]; 66590075Sobrien stats->total_size_rtxs += stats->size_rtxs[code]; 66690075Sobrien } 66790075Sobrien 66890075Sobrien /* Print the statistics for trees. */ 66990075Sobrien fprintf (stream, "\n%-17s%10s %16s %10s\n", "Tree", 67090075Sobrien "Number", "Bytes", "% Total"); 67190075Sobrien for (code = 0; code < MAX_TREE_CODES; ++code) 67290075Sobrien if (ggc_stats->num_trees[code]) 67390075Sobrien { 67490075Sobrien fprintf (stream, "%-17s%10u%16ld%c %10.3f\n", 67590075Sobrien tree_code_name[code], 67690075Sobrien ggc_stats->num_trees[code], 67790075Sobrien SCALE (ggc_stats->size_trees[code]), 67890075Sobrien LABEL (ggc_stats->size_trees[code]), 67990075Sobrien (100 * ((double) ggc_stats->size_trees[code]) 68090075Sobrien / ggc_stats->total_size_trees)); 68190075Sobrien } 68290075Sobrien fprintf (stream, 68390075Sobrien "%-17s%10u%16ld%c\n", "Total", 68490075Sobrien ggc_stats->total_num_trees, 68590075Sobrien SCALE (ggc_stats->total_size_trees), 68690075Sobrien LABEL (ggc_stats->total_size_trees)); 68790075Sobrien 68890075Sobrien /* Print the statistics for RTL. */ 68990075Sobrien fprintf (stream, "\n%-17s%10s %16s %10s\n", "RTX", 69090075Sobrien "Number", "Bytes", "% Total"); 69190075Sobrien for (code = 0; code < NUM_RTX_CODE; ++code) 69290075Sobrien if (ggc_stats->num_rtxs[code]) 69390075Sobrien { 69490075Sobrien fprintf (stream, "%-17s%10u%16ld%c %10.3f\n", 69590075Sobrien rtx_name[code], 69690075Sobrien ggc_stats->num_rtxs[code], 69790075Sobrien SCALE (ggc_stats->size_rtxs[code]), 69890075Sobrien LABEL (ggc_stats->size_rtxs[code]), 69990075Sobrien (100 * ((double) ggc_stats->size_rtxs[code]) 70090075Sobrien / ggc_stats->total_size_rtxs)); 70190075Sobrien } 70290075Sobrien fprintf (stream, 70390075Sobrien "%-17s%10u%16ld%c\n", "Total", 70490075Sobrien ggc_stats->total_num_rtxs, 70590075Sobrien SCALE (ggc_stats->total_size_rtxs), 70690075Sobrien LABEL (ggc_stats->total_size_rtxs)); 70790075Sobrien 70890075Sobrien /* Don't gather statistics any more. */ 70990075Sobrien ggc_stats = NULL; 71090075Sobrien} 711