Index: value.c =================================================================== --- value.c (revision 138922) +++ value.c (working copy) @@ -44,6 +44,20 @@ void _initialize_values (void); +/* Actual contents of the value. For use of this value; setting it + uses the stuff defined in struct value. 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 value_aligner +{ + gdb_byte contents[1]; + DOUBLEST force_doublest_align; + LONGEST force_longest_align; + CORE_ADDR force_core_addr_align; + void *force_pointer_align; +}; + struct value { /* Type of value; either not an lval, or one of the various @@ -163,21 +177,8 @@ 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. NULL or not valid if lazy is nonzero. */ + union value_aligner *content; }; /* Prototypes for local functions. */ @@ -213,15 +214,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->content = NULL; val->next = all_values; all_values = val; val->type = type; @@ -233,7 +237,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 +246,29 @@ allocate_value (struct type *type) return val; } +/* Allocate the content of the value VAL. */ + +void +allocate_value_content (struct value *val) +{ + if (!val->content) + { + val->content = + (union value_aligner *) 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_content (val); + val->lazy = 0; + return val; +} + /* Allocate a value that has the correct length for COUNT repetitions of type TYPE. */ @@ -340,13 +367,17 @@ set_value_bitsize (struct value *value, gdb_byte * value_contents_raw (struct value *value) { - return value->aligner.contents + value->embedded_offset; + if (!value->content) + allocate_value_content (value); + return value->content->contents + value->embedded_offset; } gdb_byte * value_contents_all_raw (struct value *value) { - return value->aligner.contents; + if (!value->content) + allocate_value_content (value); + return value->content->contents; } struct type * @@ -360,7 +391,7 @@ value_contents_all (struct value *value) { if (value->lazy) value_fetch_lazy (value); - return value->aligner.contents; + return value->content->contents; } int @@ -495,6 +526,14 @@ value_mark (void) return all_values; } +void +value_free (struct value *val) +{ + if (val && val->content) + xfree (val->content); + xfree (val); +} + /* Free all values allocated since MARK was obtained by value_mark (except for those released). */ void @@ -579,7 +618,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 +1363,13 @@ 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->content = + (union value_aligner *) xrealloc (val->content, + TYPE_LENGTH (new_encl_type)); + + val->enclosing_type = new_encl_type; + return val; } /* Given a value ARG1 (offset by OFFSET bytes) @@ -1388,18 +1406,22 @@ 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 +1430,22 @@ 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: value.h =================================================================== --- value.h (revision 138922) +++ 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_content (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: valops.c =================================================================== --- valops.c (revision 138922) +++ 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_content (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,21 @@ 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 +2976,17 @@ 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;