This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[commit/Ada] Avoid global lookup when decoding XA type.


Hello,

This patch enhances GDB to take advantage of a change in the GNAT encoding
made around Jan 2009 regarding XA types which allows us to avoid a global
lookup. Global lookups are bad, because they can be very costly on
large applications.  In order to support older versions of the compiler,
we preserved the original behavior when detecting that the new form of
the encoding was not used.

2010-05-17  Joel Brobecker  <brobecker@adacore.com>

        * ada-lang.c (to_fixed_range_type): The the raw index type as
        argument instead of the raw type name.  Remove orig_type parameter.
        Update calls throughout.
        (ada_fixup_array_indexes_type): New function.
        (ada_array_bound_from_type): Add call to ada_fixup_array_indexes_type.
        * ada-lang.h (ada_fixup_array_indexes_type): Add declaration.
        * ada-typeprint.c (print_range_type): Renames print_range_type_named.
        Remove name parameter.
        (print_array_type): Add call to ada_fixup_array_indexes_type.
        Update calls to print_range_type.
        (ada_print_type): Update calls to print_range_type.

Tested on x86_64-linux. Checked in.

---
 gdb/ChangeLog       |   14 ++++++++
 gdb/ada-lang.c      |   83 ++++++++++++++++++++++++++++++++++++++++++--------
 gdb/ada-lang.h      |    2 +
 gdb/ada-typeprint.c |   29 +++++++++--------
 4 files changed, 100 insertions(+), 28 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index bf3d438..171527d 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,17 @@
+2010-05-17  Joel Brobecker  <brobecker@adacore.com>
+
+	* ada-lang.c (to_fixed_range_type): The the raw index type as
+	argument instead of the raw type name.  Remove orig_type parameter.
+	Update calls throughout.
+	(ada_fixup_array_indexes_type): New function.
+	(ada_array_bound_from_type): Add call to ada_fixup_array_indexes_type.
+	* ada-lang.h (ada_fixup_array_indexes_type): Add declaration.
+	* ada-typeprint.c (print_range_type): Renames print_range_type_named.
+	Remove name parameter.
+	(print_array_type): Add call to ada_fixup_array_indexes_type.
+	Update calls to print_range_type.
+	(ada_print_type): Update calls to print_range_type.
+
 2010-05-17  Pierre Muller  <muller@ics.u-strasbg.fr>
 
 	* dwarf2read.c (read_set_type): Set type length if
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 3b3894c..83f7cf3 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -165,8 +165,7 @@ static struct type *to_fixed_variant_branch_type (struct type *,
 
 static struct type *to_fixed_array_type (struct type *, struct value *, int);
 
-static struct type *to_fixed_range_type (char *, struct value *,
-                                         struct type *);
+static struct type *to_fixed_range_type (struct type *, struct value *);
 
 static struct type *to_static_fixed_type (struct type *);
 static struct type *static_unwrap_type (struct type *type);
@@ -1204,6 +1203,61 @@ ada_match_name (const char *sym_name, const char *name, int wild)
 
                                 /* Arrays */
 
+/* Assuming that INDEX_DESC_TYPE is an ___XA structure, a structure
+   generated by the GNAT compiler to describe the index type used
+   for each dimension of an array, check whether it follows the latest
+   known encoding.  If not, fix it up to conform to the latest encoding.
+   Otherwise, do nothing.  This function also does nothing if
+   INDEX_DESC_TYPE is NULL.
+
+   The GNAT encoding used to describle the array index type evolved a bit.
+   Initially, the information would be provided through the name of each
+   field of the structure type only, while the type of these fields was
+   described as unspecified and irrelevant.  The debugger was then expected
+   to perform a global type lookup using the name of that field in order
+   to get access to the full index type description.  Because these global
+   lookups can be very expensive, the encoding was later enhanced to make
+   the global lookup unnecessary by defining the field type as being
+   the full index type description.
+
+   The purpose of this routine is to allow us to support older versions
+   of the compiler by detecting the use of the older encoding, and by
+   fixing up the INDEX_DESC_TYPE to follow the new one (at this point,
+   we essentially replace each field's meaningless type by the associated
+   index subtype).  */
+
+void
+ada_fixup_array_indexes_type (struct type *index_desc_type)
+{
+  int i;
+
+  if (index_desc_type == NULL)
+    return;
+  gdb_assert (TYPE_NFIELDS (index_desc_type) > 0);
+
+  /* Check if INDEX_DESC_TYPE follows the older encoding (it is sufficient
+     to check one field only, no need to check them all).  If not, return
+     now.
+
+     If our INDEX_DESC_TYPE was generated using the older encoding,
+     the field type should be a meaningless integer type whose name
+     is not equal to the field name.  */
+  if (TYPE_NAME (TYPE_FIELD_TYPE (index_desc_type, 0)) != NULL
+      && strcmp (TYPE_NAME (TYPE_FIELD_TYPE (index_desc_type, 0)),
+                 TYPE_FIELD_NAME (index_desc_type, 0)) == 0)
+    return;
+
+  /* Fixup each field of INDEX_DESC_TYPE.  */
+  for (i = 0; i < TYPE_NFIELDS (index_desc_type); i++)
+   {
+     char *name = TYPE_FIELD_NAME (index_desc_type, i);
+     struct type *raw_type = ada_check_typedef (ada_find_any_type (name));
+
+     if (raw_type)
+       TYPE_FIELD_TYPE (index_desc_type, i) = raw_type;
+   }
+}
+
 /* Names of MAX_ADA_DIMENS bounds in P_BOUNDS fields of array descriptors.  */
 
 static char *bound_name[] = {
@@ -2530,9 +2584,10 @@ ada_array_bound_from_type (struct type * arr_type, int n, int which)
     elt_type = TYPE_TARGET_TYPE (type);
 
   index_type_desc = ada_find_parallel_type (type, "___XA");
+  ada_fixup_array_indexes_type (index_type_desc);
   if (index_type_desc != NULL)
-    index_type = to_fixed_range_type (TYPE_FIELD_NAME (index_type_desc, n - 1),
-				      NULL, TYPE_INDEX_TYPE (elt_type));
+    index_type = to_fixed_range_type (TYPE_FIELD_TYPE (index_type_desc, n - 1),
+				      NULL);
   else
     index_type = TYPE_INDEX_TYPE (elt_type);
 
@@ -7150,6 +7205,7 @@ to_fixed_array_type (struct type *type0, struct value *dval,
     type0 = decode_constrained_packed_array_type (type0);
 
   index_type_desc = ada_find_parallel_type (type0, "___XA");
+  ada_fixup_array_indexes_type (index_type_desc);
   if (index_type_desc == NULL)
     {
       struct type *elt_type0 = ada_check_typedef (TYPE_TARGET_TYPE (type0));
@@ -7202,8 +7258,7 @@ to_fixed_array_type (struct type *type0, struct value *dval,
       for (i = TYPE_NFIELDS (index_type_desc) - 1; i >= 0; i -= 1)
         {
           struct type *range_type =
-            to_fixed_range_type (TYPE_FIELD_NAME (index_type_desc, i),
-                                 dval, TYPE_INDEX_TYPE (elt_type0));
+            to_fixed_range_type (TYPE_FIELD_TYPE (index_type_desc, i), dval);
           result = create_array_type (alloc_type_copy (elt_type0),
                                       result, range_type);
 	  elt_type0 = TYPE_TARGET_TYPE (elt_type0);
@@ -9182,7 +9237,7 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
             char *name = ada_type_name (type_arg);
             range_type = NULL;
             if (name != NULL && TYPE_CODE (type_arg) != TYPE_CODE_ENUM)
-              range_type = to_fixed_range_type (name, NULL, type_arg);
+              range_type = to_fixed_range_type (type_arg, NULL);
             if (range_type == NULL)
               range_type = type_arg;
             switch (op)
@@ -9704,21 +9759,21 @@ get_int_var_value (char *name, int *flag)
    in NAME, the base type given in the named range type.  */
 
 static struct type *
-to_fixed_range_type (char *name, struct value *dval, struct type *orig_type)
+to_fixed_range_type (struct type *raw_type, struct value *dval)
 {
-  struct type *raw_type = ada_find_any_type (name);
+  char *name;
   struct type *base_type;
   char *subtype_info;
 
-  /* Fall back to the original type if symbol lookup failed.  */
-  if (raw_type == NULL)
-    raw_type = orig_type;
+  gdb_assert (raw_type != NULL);
+  gdb_assert (TYPE_NAME (raw_type) != NULL);
 
   if (TYPE_CODE (raw_type) == TYPE_CODE_RANGE)
     base_type = TYPE_TARGET_TYPE (raw_type);
   else
     base_type = raw_type;
 
+  name = TYPE_NAME (raw_type);
   subtype_info = strstr (name, "___XD");
   if (subtype_info == NULL)
     {
@@ -9727,7 +9782,7 @@ to_fixed_range_type (char *name, struct value *dval, struct type *orig_type)
       if (L < INT_MIN || U > INT_MAX)
 	return raw_type;
       else
-	return create_range_type (alloc_type_copy (orig_type), raw_type,
+	return create_range_type (alloc_type_copy (raw_type), raw_type,
 				  ada_discrete_type_low_bound (raw_type),
 				  ada_discrete_type_high_bound (raw_type));
     }
@@ -9790,7 +9845,7 @@ to_fixed_range_type (char *name, struct value *dval, struct type *orig_type)
             }
         }
 
-      type = create_range_type (alloc_type_copy (orig_type), base_type, L, U);
+      type = create_range_type (alloc_type_copy (raw_type), base_type, L, U);
       TYPE_NAME (type) = name;
       return type;
     }
diff --git a/gdb/ada-lang.h b/gdb/ada-lang.h
index 3d60f8f..f6b613f 100644
--- a/gdb/ada-lang.h
+++ b/gdb/ada-lang.h
@@ -187,6 +187,8 @@ struct value *ada_convert_actual (struct value *actual,
 extern struct value *ada_value_subscript (struct value *, int,
                                           struct value **);
 
+extern void ada_fixup_array_indexes_type (struct type *index_desc_type);
+
 extern struct type *ada_array_element_type (struct type *, int);
 
 extern int ada_array_arity (struct type *);
diff --git a/gdb/ada-typeprint.c b/gdb/ada-typeprint.c
index 17d3594..b69deab 100644
--- a/gdb/ada-typeprint.c
+++ b/gdb/ada-typeprint.c
@@ -55,7 +55,7 @@ static void
 print_dynamic_range_bound (struct type *, const char *, int,
 			   const char *, struct ui_file *);
 
-static void print_range_type_named (char *, struct type *, struct ui_file *);
+static void print_range_type (struct type *, struct ui_file *);
 
 
 
@@ -212,19 +212,19 @@ print_dynamic_range_bound (struct type *type, const char *name, int name_len,
     fprintf_filtered (stream, "?");
 }
 
-/* Print the range type named NAME.  If symbol lookup fails, fall back
-   to ORIG_TYPE as base type.  */
+/* Print RAW_TYPE as a range type, using any bound information
+   following the GNAT encoding (if available).  */
 
 static void
-print_range_type_named (char *name, struct type *orig_type,
-			struct ui_file *stream)
+print_range_type (struct type *raw_type, struct ui_file *stream)
 {
-  struct type *raw_type = ada_find_any_type (name);
+  char *name;
   struct type *base_type;
   char *subtype_info;
 
-  if (raw_type == NULL)
-    raw_type = orig_type;
+  gdb_assert (raw_type != NULL);
+  name = TYPE_NAME (raw_type);
+  gdb_assert (name != NULL);
 
   if (TYPE_CODE (raw_type) == TYPE_CODE_RANGE)
     base_type = TYPE_TARGET_TYPE (raw_type);
@@ -341,10 +341,12 @@ print_array_type (struct type *type, struct ui_file *stream, int show,
     {
       if (ada_is_simple_array_type (type))
 	{
-	  struct type *range_desc_type =
-	    ada_find_parallel_type (type, "___XA");
+	  struct type *range_desc_type;
 	  struct type *arr_type;
 
+	  range_desc_type = ada_find_parallel_type (type, "___XA");
+	  ada_fixup_array_indexes_type (range_desc_type);
+
 	  bitsize = 0;
 	  if (range_desc_type == NULL)
 	    {
@@ -368,9 +370,8 @@ print_array_type (struct type *type, struct ui_file *stream, int show,
 		{
 		  if (k > 0)
 		    fprintf_filtered (stream, ", ");
-		  print_range_type_named (TYPE_FIELD_NAME
-					  (range_desc_type, k),
-					  TYPE_INDEX_TYPE (arr_type), stream);
+		  print_range_type (TYPE_FIELD_TYPE (range_desc_type, k),
+				    stream);
 		  if (TYPE_FIELD_BITSIZE (arr_type, 0) > 0)
 		    bitsize = TYPE_FIELD_BITSIZE (arr_type, 0);
 		}
@@ -786,7 +787,7 @@ ada_print_type (struct type *type0, char *varstring, struct ui_file *stream,
 	    else
 	      {
 		fprintf_filtered (stream, "range ");
-		print_range_type_named (name, type, stream);
+		print_range_type (type, stream);
 	      }
 	  }
 	break;
-- 
1.6.3.3


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]