From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 14445 invoked by alias); 25 Nov 2008 11:27:33 -0000 Received: (qmail 14258 invoked by uid 22791); 25 Nov 2008 11:27:30 -0000 X-Spam-Check-By: sourceware.org Received: from mel.act-europe.fr (HELO mel.act-europe.fr) (212.99.106.210) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 25 Nov 2008 11:26:51 +0000 Received: from localhost (localhost [127.0.0.1]) by filtered-smtp.eu.adacore.com (Postfix) with ESMTP id BB2D0290005; Tue, 25 Nov 2008 12:26:39 +0100 (CET) Received: from mel.act-europe.fr ([127.0.0.1]) by localhost (smtp.eu.adacore.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id gN6VfNtbhsqo; Tue, 25 Nov 2008 12:26:38 +0100 (CET) Received: from province.act-europe.fr (province.act-europe.fr [10.10.0.214]) by mel.act-europe.fr (Postfix) with ESMTP id B79C4290001; Tue, 25 Nov 2008 12:26:38 +0100 (CET) Received: by province.act-europe.fr (Postfix, from userid 560) id 6463216571E; Tue, 25 Nov 2008 12:26:38 +0100 (CET) Date: Tue, 25 Nov 2008 18:11:00 -0000 From: Jerome Guitton To: Tom Tromey Cc: gdb-patches@sourceware.org Subject: Re: [RFA] "lazily" allocate the raw content of lazy values Message-ID: <20081125112638.GE61928@adacore.com> References: <20081124144810.GA90681@adacore.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="LKTjZJSUETSlgu2t" Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.17 (2007-11-01) Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2008-11/txt/msg00687.txt.bz2 --LKTjZJSUETSlgu2t Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-length: 1785 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 * 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. --LKTjZJSUETSlgu2t Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="lazy_values.diff" Content-length: 11242 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); --LKTjZJSUETSlgu2t--