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]

Re: [RFA] "lazily" allocate the raw content of lazy values


Tom Tromey (tromey@redhat.com):

> Jerome> Here, an elegant solution would be to manipulate lazy values instead
> Jerome> of references
> [...]
> 
> Very nice background explanation, thanks.

You are welcome ;)

Thank you for your comments. I have taken them into account, with a few
additional changes:
* rename allocate_value_content to allocate_value_contents, for consistancy;
* remove the test "value->contents == NULL" in value_contents_raw and
value_contents_all_raw, as this is done in allocate_value_contents.

The new version of the patch is in attachment, re-tested against the
testsuite. Promoting this message to RFA now. OK to apply?

Thanks,
Jerome


2008-11-25  Jerome Guitton  <guitton@adacore.com>

	* value.h (allocate_value_lazy): New function declaration.
	(value_free): Remove macro, make it a function.
	* value.c (value): Move actual content outside of the memory space
        of the struct; add a pointer to this actual content.
	(allocate_value_lazy, allocate_value_contents): New function.
	(allocate_value): Reimplement using these two new functions.
	(value_contents_raw, value_contents_all_raw): If no memory
	has been allocated yet for the actual content, allocate it.
	(value_contents_all): Resync with struct value's changes.
	(value_free): New function.
	(value_copy, value_primitive_field): Use new function
	allocate_value_lazy to allocate lazy values.
	(value_change_enclosing_type): Resync with struct value's changes.
	As the value is not reallocated, remove the special handling for
	the value chain (now obsolete).
	* valops.c (value_at_lazy): Use new function allocate_value_lazy.
	(value_fetch_lazy): Allocate value content. Use allocate_value_lazy
	to allocate lazy values.
	(value_slice): Use allocate_value_lazy to allocate lazy values.

Index: value.c
===================================================================
--- value.c	(revision 139003)
+++ value.c	(working copy)
@@ -163,21 +163,9 @@ struct value
   /* If value is a variable, is it initialized or not.  */
   int initialized;
 
-  /* Actual contents of the value.  For use of this value; setting it
-     uses the stuff above.  Not valid if lazy is nonzero.  Target
-     byte-order.  We force it to be aligned properly for any possible
-     value.  Note that a value therefore extends beyond what is
-     declared here.  */
-  union
-  {
-    gdb_byte contents[1];
-    DOUBLEST force_doublest_align;
-    LONGEST force_longest_align;
-    CORE_ADDR force_core_addr_align;
-    void *force_pointer_align;
-  } aligner;
-  /* Do not add any new members here -- contents above will trash
-     them.  */
+  /* Actual contents of the value. Target byte-order. NULL or not valid if
+     lazy is nonzero. */
+  gdb_byte *contents;
 };
 
 /* Prototypes for local functions. */
@@ -213,15 +201,18 @@ static int value_history_count;	/* Abs n
 
 static struct value *all_values;
 
-/* Allocate a  value  that has the correct length for type TYPE.  */
+/* Allocate a lazy value for type TYPE.  Its actual content is
+   "lazily" allocated too: the content field of the return value is
+   NULL; it will be allocated when it is fetched from the target.  */
 
 struct value *
-allocate_value (struct type *type)
+allocate_value_lazy (struct type *type)
 {
   struct value *val;
   struct type *atype = check_typedef (type);
 
-  val = (struct value *) xzalloc (sizeof (struct value) + TYPE_LENGTH (atype));
+  val = (struct value *) xzalloc (sizeof (struct value));
+  val->contents = NULL;
   val->next = all_values;
   all_values = val;
   val->type = type;
@@ -233,7 +224,7 @@ allocate_value (struct type *type)
   val->bitpos = 0;
   val->bitsize = 0;
   VALUE_REGNUM (val) = -1;
-  val->lazy = 0;
+  val->lazy = 1;
   val->optimized_out = 0;
   val->embedded_offset = 0;
   val->pointed_to_offset = 0;
@@ -242,6 +233,28 @@ allocate_value (struct type *type)
   return val;
 }
 
+/* Allocate the contents of the value VAL if it has not been allocated yet.  */
+
+void
+allocate_value_contents (struct value *val)
+{
+  if (!val->contents)
+    {
+      val->contents = (gdb_byte *) xzalloc (TYPE_LENGTH (val->enclosing_type));
+    }
+}
+
+/* Allocate a  value  that has the correct length for type TYPE.  */
+
+struct value *
+allocate_value (struct type *type)
+{
+  struct value *val = allocate_value_lazy (type);
+  allocate_value_contents (val);
+  val->lazy = 0;
+  return val;
+}
+
 /* Allocate a  value  that has the correct length
    for COUNT repetitions of type TYPE.  */
 
@@ -340,13 +353,15 @@ set_value_bitsize (struct value *value, 
 gdb_byte *
 value_contents_raw (struct value *value)
 {
-  return value->aligner.contents + value->embedded_offset;
+  allocate_value_contents (value);
+  return value->contents + value->embedded_offset;
 }
 
 gdb_byte *
 value_contents_all_raw (struct value *value)
 {
-  return value->aligner.contents;
+  allocate_value_contents (value);
+  return value->contents;
 }
 
 struct type *
@@ -360,7 +375,7 @@ value_contents_all (struct value *value)
 {
   if (value->lazy)
     value_fetch_lazy (value);
-  return value->aligner.contents;
+  return value->contents;
 }
 
 int
@@ -495,6 +510,14 @@ value_mark (void)
   return all_values;
 }
 
+void
+value_free (struct value *val)
+{
+  if (val)
+    xfree (val->contents);
+  xfree (val);
+}
+
 /* Free all values allocated since MARK was obtained by value_mark
    (except for those released).  */
 void
@@ -579,7 +602,12 @@ struct value *
 value_copy (struct value *arg)
 {
   struct type *encl_type = value_enclosing_type (arg);
-  struct value *val = allocate_value (encl_type);
+  struct value *val;
+
+  if (value_lazy (arg))
+    val = allocate_value_lazy (encl_type);
+  else
+    val = allocate_value (encl_type);
   val->type = arg->type;
   VALUE_LVAL (val) = VALUE_LVAL (arg);
   val->location = arg->location;
@@ -1319,39 +1347,12 @@ value_static_field (struct type *type, i
 struct value *
 value_change_enclosing_type (struct value *val, struct type *new_encl_type)
 {
-  if (TYPE_LENGTH (new_encl_type) <= TYPE_LENGTH (value_enclosing_type (val))) 
-    {
-      val->enclosing_type = new_encl_type;
-      return val;
-    }
-  else
-    {
-      struct value *new_val;
-      struct value *prev;
-      
-      new_val = (struct value *) xrealloc (val, sizeof (struct value) + TYPE_LENGTH (new_encl_type));
-
-      new_val->enclosing_type = new_encl_type;
- 
-      /* We have to make sure this ends up in the same place in the value
-	 chain as the original copy, so it's clean-up behavior is the same. 
-	 If the value has been released, this is a waste of time, but there
-	 is no way to tell that in advance, so... */
-      
-      if (val != all_values) 
-	{
-	  for (prev = all_values; prev != NULL; prev = prev->next)
-	    {
-	      if (prev->next == val) 
-		{
-		  prev->next = new_val;
-		  break;
-		}
-	    }
-	}
-      
-      return new_val;
-    }
+  if (TYPE_LENGTH (new_encl_type) > TYPE_LENGTH (value_enclosing_type (val))) 
+    val->contents =
+      (gdb_byte *) xrealloc (val->contents, TYPE_LENGTH (new_encl_type));
+
+  val->enclosing_type = new_encl_type;
+  return val;
 }
 
 /* Given a value ARG1 (offset by OFFSET bytes)
@@ -1388,18 +1389,20 @@ value_primitive_field (struct value *arg
       /* This field is actually a base subobject, so preserve the
          entire object's contents for later references to virtual
          bases, etc.  */
-      v = allocate_value (value_enclosing_type (arg1));
-      v->type = type;
 
       /* Lazy register values with offsets are not supported.  */
       if (VALUE_LVAL (arg1) == lval_register && value_lazy (arg1))
 	value_fetch_lazy (arg1);
 
       if (value_lazy (arg1))
-	set_value_lazy (v, 1);
+        v = allocate_value_lazy (value_enclosing_type (arg1));
       else
-	memcpy (value_contents_all_raw (v), value_contents_all_raw (arg1),
-		TYPE_LENGTH (value_enclosing_type (arg1)));
+        {
+          v = allocate_value (value_enclosing_type (arg1));
+          memcpy (value_contents_all_raw (v), value_contents_all_raw (arg1),
+                  TYPE_LENGTH (value_enclosing_type (arg1)));
+        }
+      v->type = type;
       v->offset = value_offset (arg1);
       v->embedded_offset = (offset + value_embedded_offset (arg1)
 			    + TYPE_FIELD_BITPOS (arg_type, fieldno) / 8);
@@ -1408,18 +1411,20 @@ value_primitive_field (struct value *arg
     {
       /* Plain old data member */
       offset += TYPE_FIELD_BITPOS (arg_type, fieldno) / 8;
-      v = allocate_value (type);
 
       /* Lazy register values with offsets are not supported.  */
       if (VALUE_LVAL (arg1) == lval_register && value_lazy (arg1))
 	value_fetch_lazy (arg1);
 
       if (value_lazy (arg1))
-	set_value_lazy (v, 1);
+        v = allocate_value_lazy (type);
       else
-	memcpy (value_contents_raw (v),
-		value_contents_raw (arg1) + offset,
-		TYPE_LENGTH (type));
+        {
+          v = allocate_value (type);
+          memcpy (value_contents_raw (v),
+                  value_contents_raw (arg1) + offset,
+                  TYPE_LENGTH (type));
+        }
       v->offset = (value_offset (arg1) + offset
 		   + value_embedded_offset (arg1));
     }
Index: valops.c
===================================================================
--- valops.c	(revision 139003)
+++ valops.c	(working copy)
@@ -608,11 +608,10 @@ value_at_lazy (struct type *type, CORE_A
   if (TYPE_CODE (check_typedef (type)) == TYPE_CODE_VOID)
     error (_("Attempt to dereference a generic pointer."));
 
-  val = allocate_value (type);
+  val = allocate_value_lazy (type);
 
   VALUE_LVAL (val) = lval_memory;
   VALUE_ADDRESS (val) = addr;
-  set_value_lazy (val, 1);
 
   return val;
 }
@@ -634,6 +633,8 @@ value_at_lazy (struct type *type, CORE_A
 int
 value_fetch_lazy (struct value *val)
 {
+  gdb_assert (value_lazy (val));
+  allocate_value_contents (val);
   if (VALUE_LVAL (val) == lval_memory)
     {
       CORE_ADDR addr = VALUE_ADDRESS (val) + value_offset (val);
@@ -1535,7 +1536,7 @@ search_struct_field (char *name, struct 
       if (BASETYPE_VIA_VIRTUAL (type, i))
 	{
 	  int boffset;
-	  struct value *v2 = allocate_value (basetype);
+	  struct value *v2;
 
 	  boffset = baseclass_offset (type, i,
 				      value_contents (arg1) + offset,
@@ -1553,6 +1554,7 @@ search_struct_field (char *name, struct 
 	    {
 	      CORE_ADDR base_addr;
 
+              v2  = allocate_value (basetype);
 	      base_addr = 
 		VALUE_ADDRESS (arg1) + value_offset (arg1) + boffset;
 	      if (target_read_memory (base_addr, 
@@ -1564,16 +1566,19 @@ search_struct_field (char *name, struct 
 	    }
 	  else
 	    {
+	      if (VALUE_LVAL (arg1) == lval_memory && value_lazy (arg1))
+                v2  = allocate_value_lazy (basetype);
+	      else
+                {
+                  v2  = allocate_value (basetype);
+                  memcpy (value_contents_raw (v2),
+                          value_contents_raw (arg1) + boffset,
+                          TYPE_LENGTH (basetype));
+                }
 	      VALUE_LVAL (v2) = VALUE_LVAL (arg1);
 	      VALUE_ADDRESS (v2) = VALUE_ADDRESS (arg1);
 	      VALUE_FRAME_ID (v2) = VALUE_FRAME_ID (arg1);
 	      set_value_offset (v2, value_offset (arg1) + boffset);
-	      if (VALUE_LVAL (arg1) == lval_memory && value_lazy (arg1))
-		set_value_lazy (v2, 1);
-	      else
-		memcpy (value_contents_raw (v2),
-			value_contents_raw (arg1) + boffset,
-			TYPE_LENGTH (basetype));
 	    }
 
 	  if (found_baseclass)
@@ -2969,13 +2974,15 @@ value_slice (struct value *array, int lo
 				      slice_range_type);
       TYPE_CODE (slice_type) = TYPE_CODE (array_type);
 
-      slice = allocate_value (slice_type);
       if (VALUE_LVAL (array) == lval_memory && value_lazy (array))
-	set_value_lazy (slice, 1);
+        slice = allocate_value_lazy (slice_type);
       else
-	memcpy (value_contents_writeable (slice),
-		value_contents (array) + offset,
-		TYPE_LENGTH (slice_type));
+        {
+          slice = allocate_value (slice_type);
+          memcpy (value_contents_writeable (slice),
+                  value_contents (array) + offset,
+                  TYPE_LENGTH (slice_type));
+        }
 
       if (VALUE_LVAL (array) == lval_internalvar)
 	VALUE_LVAL (slice) = lval_internalvar_component;
Index: value.h
===================================================================
--- value.h	(revision 139003)
+++ value.h	(working copy)
@@ -314,6 +314,8 @@ extern struct value *locate_var_value (s
 				       struct frame_info *frame);
 
 extern struct value *allocate_value (struct type *type);
+extern struct value *allocate_value_lazy (struct type *type);
+extern void allocate_value_contents (struct value *value);
 
 extern struct value *allocate_repeat_value (struct type *type, int count);
 
@@ -500,7 +502,7 @@ extern int unop_user_defined_p (enum exp
 
 extern int destructor_name_p (const char *name, const struct type *type);
 
-#define value_free(val) xfree (val)
+extern void value_free (struct value *val);
 
 extern void free_all_values (void);
 

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