Index: c-typeck.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/c-typeck.c,v retrieving revision 1.238 diff -u -d -b -w -u -p -r1.238 c-typeck.c --- c-typeck.c 5 May 2003 20:31:42 -0000 1.238 +++ c-typeck.c 30 May 2003 21:01:36 -0000 @@ -1038,11 +1038,11 @@ lookup_field (decl, component) if (TYPE_LANG_SPECIFIC (type)) { int bot, top, half; - tree *field_array = &TYPE_LANG_SPECIFIC (type)->elts[0]; + tree *field_array = &TYPE_LANG_SPECIFIC (type)->s->elts[0]; field = TYPE_FIELDS (type); bot = 0; - top = TYPE_LANG_SPECIFIC (type)->len; + top = TYPE_LANG_SPECIFIC (type)->s->len; while (top - bot > 1) { half = (top - bot + 1) >> 1; Index: c-decl.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/c-decl.c,v retrieving revision 1.390 diff -u -d -b -w -u -p -r1.390 c-decl.c --- c-decl.c 22 May 2003 19:39:13 -0000 1.390 +++ c-decl.c 30 May 2003 21:01:38 -0000 @@ -5162,6 +5164,56 @@ finish_struct (t, fieldlist, attributes) TYPE_FIELDS (t) = fieldlist; + /* If there are lots of fields, sort so we can look through them fast. + We arbitrarily consider 16 or more elts to be "a lot". */ + + { + int len = 0; + + for (x = fieldlist; x; x = TREE_CHAIN (x)) + { + if (len > 15 || DECL_NAME (x) == NULL) + break; + len += 1; + } + + if (len > 15) + { + tree *field_array; + struct lang_type *space; + struct sorted_fields_type *space2; + + len += list_length (x); + + /* Use the same allocation policy here that make_node uses, to + ensure that this lives as long as the rest of the struct decl. + All decls in an inline function need to be saved. */ + + space = ggc_alloc (sizeof (struct lang_type)); + space2 = ggc_alloc (sizeof (struct sorted_fields_type) + len * sizeof (tree)); + + len = 0; + space->s = space2; + field_array = &space2->elts[0]; + for (x = fieldlist; x; x = TREE_CHAIN (x)) + { + field_array[len++] = x; + + /* if there is anonymous struct or union break out of the loop */ + if (DECL_NAME (x) == NULL) + break; + } + /* found no anonymous struct/union add the TYPE_LANG_SPECIFIC. */ + if (x == NULL) + { + TYPE_LANG_SPECIFIC (t) = space; + TYPE_LANG_SPECIFIC (t)->s->len = len; + field_array = TYPE_LANG_SPECIFIC (t)->s->elts; + qsort (field_array, len, sizeof (tree), field_decl_cmp); + } + } + } + for (x = TYPE_MAIN_VARIANT (t); x; x = TYPE_NEXT_VARIANT (x)) { TYPE_FIELDS (x) = TYPE_FIELDS (t); Index: c-common.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/c-common.c,v retrieving revision 1.417 diff -u -d -b -w -u -p -r1.417 c-common.c --- c-common.c 19 May 2003 19:19:42 -0000 1.417 +++ c-common.c 30 May 2003 21:01:39 -0000 @@ -800,6 +800,7 @@ static void check_nonnull_arg PARAMS (( static bool nonnull_check_p PARAMS ((tree, unsigned HOST_WIDE_INT)); static bool get_nonnull_operand PARAMS ((tree, unsigned HOST_WIDE_INT *)); +static int resort_field_decl_cmp (const void *, const void *); /* Table of machine-independent attributes common to all C-like languages. */ const struct attribute_spec c_common_attribute_table[] = @@ -6195,6 +6196,72 @@ check_function_arguments_recurse (callba } (*callback) (ctx, param, param_num); +} + +/* Function to help qsort sort FIELD_DECLs by name order. */ + +int +field_decl_cmp (const void *x_p, const void *y_p) +{ + const tree *const x = x_p; + const tree *const y = y_p; + if (DECL_NAME (*x) == DECL_NAME (*y)) + /* A nontype is "greater" than a type. */ + return (TREE_CODE (*y) == TYPE_DECL) - (TREE_CODE (*x) == TYPE_DECL); + if (DECL_NAME (*x) == NULL_TREE) + return -1; + if (DECL_NAME (*y) == NULL_TREE) + return 1; + if (DECL_NAME (*x) < DECL_NAME (*y)) + return -1; + return 1; +} + +static struct { + gt_pointer_operator new_value; + void *cookie; +} resort_data; + +/* This routine compares two fields like field_decl_cmp but using the +pointer operator in resort_data. */ + +static int +resort_field_decl_cmp (const void *x_p, const void *y_p) +{ + const tree *const x = x_p; + const tree *const y = y_p; + + if (DECL_NAME (*x) == DECL_NAME (*y)) + /* A nontype is "greater" than a type. */ + return (TREE_CODE (*y) == TYPE_DECL) - (TREE_CODE (*x) == TYPE_DECL); + if (DECL_NAME (*x) == NULL_TREE) + return -1; + if (DECL_NAME (*y) == NULL_TREE) + return 1; + { + tree d1 = DECL_NAME (*x); + tree d2 = DECL_NAME (*y); + resort_data.new_value (&d1, resort_data.cookie); + resort_data.new_value (&d2, resort_data.cookie); + if (d1 < d2) + return -1; + } + return 1; +} + +/* Resort DECL_SORTED_FIELDS because pointers have been reordered. */ + +void +resort_sorted_fields (void *obj, + void *orig_obj ATTRIBUTE_UNUSED , + gt_pointer_operator new_value, + void *cookie) +{ + struct sorted_fields_type *sf = obj; + resort_data.new_value = new_value; + resort_data.cookie = cookie; + qsort (&sf->elts[0], sf->len, sizeof (tree), + resort_field_decl_cmp); } #include "gt-c-common.h" Index: c-common.h =================================================================== RCS file: /cvs/gcc/gcc/gcc/c-common.h,v retrieving revision 1.181 diff -u -d -b -w -u -p -r1.181 c-common.h --- c-common.h 21 May 2003 11:13:17 -0000 1.181 +++ c-common.h 30 May 2003 21:01:40 -0000 @@ -24,6 +24,7 @@ Software Foundation, 59 Temple Place - S #include "splay-tree.h" #include "cpplib.h" +#include "ggc.h" /* Usage of TREE_LANG_FLAG_?: 0: COMPOUND_STMT_NO_SCOPE (in COMPOUND_STMT). @@ -223,6 +224,13 @@ struct c_common_identifier GTY(()) extern GTY(()) tree c_global_trees[CTI_MAX]; +/* In a RECORD_TYPE, a sorted array of the fields of the type, not a tree for size reasons. */ +struct sorted_fields_type GTY(()) +{ + int len; + tree GTY((length ("%h.len"))) elts[1]; +}; + /* Mark which labels are explicitly declared. These may be shadowed, and may be referenced from nested functions. */ #define C_DECLARED_LABEL_FLAG(label) TREE_LANG_FLAG_1 (label) @@ -337,6 +345,9 @@ extern void c_finish_while_stmt_cond PA enum sw_kind { SW_PARAM = 0, SW_LOCAL, SW_GLOBAL }; extern void shadow_warning PARAMS ((enum sw_kind, const char *, tree)); +extern int field_decl_cmp (const void *, const void *); +extern void resort_sorted_fields + (void *, void *, gt_pointer_operator, void *); /* Extra information associated with a DECL. Other C dialects extend this structure in various ways. The C front-end only uses this Index: ggc.h =================================================================== RCS file: /cvs/gcc/gcc/gcc/ggc.h,v retrieving revision 1.50 diff -u -d -b -w -u -p -r1.50 ggc.h --- ggc.h 3 Apr 2003 21:00:56 -0000 1.50 +++ ggc.h 30 May 2003 21:01:40 -0000 @@ -18,6 +18,9 @@ along with GCC; see the file COPYING. I Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#ifndef GCC_GGC_H +#define GCC_GGC_H + /* Symbols are marked with `ggc' for `gcc gc' so as not to interfere with an external gc library that might be linked in. */ @@ -268,3 +271,4 @@ extern void stringpool_statistics PARAMS extern int ggc_min_expand_heuristic PARAMS ((void)); extern int ggc_min_heapsize_heuristic PARAMS ((void)); extern void init_ggc_heuristics PARAMS ((void)); +#endif Index: c-tree.h =================================================================== RCS file: /cvs/gcc/gcc/gcc/c-tree.h,v retrieving revision 1.113 diff -u -d -b -w -u -p -r1.113 c-tree.h --- c-tree.h 11 Apr 2003 04:26:49 -0000 1.113 +++ c-tree.h 30 May 2003 21:01:40 -0000 @@ -109,8 +109,7 @@ struct lang_decl GTY(()) /* In a RECORD_TYPE, a sorted array of the fields of the type. */ struct lang_type GTY(()) { - int len; - tree GTY((length ("%h.len"))) elts[1]; + struct sorted_fields_type * GTY ((reorder ("resort_sorted_fields"))) s; }; /* Record whether a type or decl was written with nonconstant size. Index: cp/class.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v retrieving revision 1.541 diff -u -d -b -w -u -p -r1.541 class.c --- cp/class.c 20 May 2003 20:52:33 -0000 1.541 +++ cp/class.c 30 May 2003 21:01:42 -0000 @@ -124,8 +124,6 @@ static tree modify_all_vtables (tree, tr static void determine_primary_base (tree); static void finish_struct_methods (tree); static void maybe_warn_about_overly_private_class (tree); -static int field_decl_cmp (const void *, const void *); -static int resort_field_decl_cmp (const void *, const void *); static int method_name_cmp (const void *, const void *); static int resort_method_name_cmp (const void *, const void *); static void add_implicitly_declared_members (tree, int, int, int); @@ -136,7 +134,7 @@ static tree build_vtable_entry_ref (tree static tree build_vtbl_ref_1 (tree, tree); static tree build_vtbl_initializer (tree, tree, tree, tree, int *); static int count_fields (tree); -static int add_fields_to_vec (tree, tree, int); +static int add_fields_to_record_type (tree, struct sorted_field_type*, int); static void check_bitfield_decl (tree); static void check_field_decl (tree, tree, int *, int *, int *, int *); static void check_field_decls (tree, tree *, int *, int *, int *); @@ -1712,72 +1710,11 @@ maybe_warn_about_overly_private_class (t } } -/* Function to help qsort sort FIELD_DECLs by name order. */ - -static int -field_decl_cmp (const void* x_p, const void* y_p) -{ - const tree *const x = x_p; - const tree *const y = y_p; - if (DECL_NAME (*x) == DECL_NAME (*y)) - /* A nontype is "greater" than a type. */ - return DECL_DECLARES_TYPE_P (*y) - DECL_DECLARES_TYPE_P (*x); - if (DECL_NAME (*x) == NULL_TREE) - return -1; - if (DECL_NAME (*y) == NULL_TREE) - return 1; - if (DECL_NAME (*x) < DECL_NAME (*y)) - return -1; - return 1; -} - static struct { gt_pointer_operator new_value; void *cookie; } resort_data; -/* This routine compares two fields like field_decl_cmp but using the - pointer operator in resort_data. */ - -static int -resort_field_decl_cmp (const void* x_p, const void* y_p) -{ - const tree *const x = x_p; - const tree *const y = y_p; - - if (DECL_NAME (*x) == DECL_NAME (*y)) - /* A nontype is "greater" than a type. */ - return DECL_DECLARES_TYPE_P (*y) - DECL_DECLARES_TYPE_P (*x); - if (DECL_NAME (*x) == NULL_TREE) - return -1; - if (DECL_NAME (*y) == NULL_TREE) - return 1; - { - tree d1 = DECL_NAME (*x); - tree d2 = DECL_NAME (*y); - resort_data.new_value (&d1, resort_data.cookie); - resort_data.new_value (&d2, resort_data.cookie); - if (d1 < d2) - return -1; - } - return 1; -} - -/* Resort DECL_SORTED_FIELDS because pointers have been reordered. */ - -void -resort_sorted_fields (void* obj, - void* orig_obj ATTRIBUTE_UNUSED , - gt_pointer_operator new_value, - void* cookie) -{ - tree sf = obj; - resort_data.new_value = new_value; - resort_data.cookie = cookie; - qsort (&TREE_VEC_ELT (sf, 0), TREE_VEC_LENGTH (sf), sizeof (tree), - resort_field_decl_cmp); -} - /* Comparison function to compare two TYPE_METHOD_VEC entries by name. */ static int @@ -2787,18 +2724,18 @@ count_fields (tree fields) } /* Subroutine of finish_struct_1. Recursively add all the fields in the - TREE_LIST FIELDS to the TREE_VEC FIELD_VEC, starting at offset IDX. */ + TREE_LIST FIELDS to the SORTED_FIELDS_TYPE elts, starting at offset IDX. */ static int -add_fields_to_vec (tree fields, tree field_vec, int idx) +add_fields_to_record_type (tree fields, struct sorted_fields_type *field_vec, int idx) { tree x; for (x = fields; x; x = TREE_CHAIN (x)) { if (TREE_CODE (x) == FIELD_DECL && ANON_AGGR_TYPE_P (TREE_TYPE (x))) - idx = add_fields_to_vec (TYPE_FIELDS (TREE_TYPE (x)), field_vec, idx); + idx = add_fields_to_record_type (TYPE_FIELDS (TREE_TYPE (x)), field_vec, idx); else - TREE_VEC_ELT (field_vec, idx++) = x; + field_vec->elts[idx++] = x; } return idx; } @@ -5167,9 +5104,11 @@ finish_struct_1 (tree t) n_fields = count_fields (TYPE_FIELDS (t)); if (n_fields > 7) { - tree field_vec = make_tree_vec (n_fields); - add_fields_to_vec (TYPE_FIELDS (t), field_vec, 0); - qsort (&TREE_VEC_ELT (field_vec, 0), n_fields, sizeof (tree), + struct sorted_fields_type *field_vec = ggc_alloc (sizeof (struct sorted_fields_type) + + n_fields * sizeof (tree)); + field_vec->len = n_fields; + add_fields_to_record_type (TYPE_FIELDS (t), field_vec, 0); + qsort (field_vec->elts, n_fields, sizeof (tree), field_decl_cmp); if (! DECL_LANG_SPECIFIC (TYPE_MAIN_DECL (t))) retrofit_lang_decl (TYPE_MAIN_DECL (t)); Index: cp/cp-tree.h =================================================================== RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v retrieving revision 1.847 diff -u -d -b -w -u -p -r1.847 cp-tree.h --- cp/cp-tree.h 18 May 2003 13:40:52 -0000 1.847 +++ cp/cp-tree.h 30 May 2003 21:01:44 -0000 @@ -1709,7 +1709,7 @@ struct lang_decl GTY(()) union lang_decl_u3 { - tree GTY ((tag ("0"), reorder ("resort_sorted_fields"))) + struct sorted_fields_type * GTY ((tag ("0"), reorder ("resort_sorted_fields"))) sorted_fields; struct cp_token_cache * GTY ((tag ("2"))) pending_inline_info; struct language_function * GTY ((tag ("1"))) @@ -3522,8 +3522,6 @@ extern tree convert_to_base extern tree build_vtbl_ref (tree, tree); extern tree build_vfn_ref (tree, tree); extern tree get_vtable_decl (tree, int); -extern void resort_sorted_fields - (void *, void *, gt_pointer_operator, void *); extern void resort_type_method_vec (void *, void *, gt_pointer_operator, void *); extern void add_method (tree, tree, int); Index: cp/search.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/cp/search.c,v retrieving revision 1.263 diff -u -d -b -w -u -p -r1.263 search.c --- cp/search.c 18 May 2003 13:40:54 -0000 1.263 +++ cp/search.c 30 May 2003 21:01:45 -0000 @@ -449,8 +449,8 @@ lookup_field_1 (tree type, tree name, bo && DECL_LANG_SPECIFIC (TYPE_NAME (type)) && DECL_SORTED_FIELDS (TYPE_NAME (type))) { - tree *fields = &TREE_VEC_ELT (DECL_SORTED_FIELDS (TYPE_NAME (type)), 0); - int lo = 0, hi = TREE_VEC_LENGTH (DECL_SORTED_FIELDS (TYPE_NAME (type))); + tree *fields = &DECL_SORTED_FIELDS (TYPE_NAME (type))->elts[0]; + int lo = 0, hi = DECL_SORTED_FIELDS (TYPE_NAME (type))->len; int i; while (lo < hi)