Remove value::next and value::released

This patch converts all_values to simply hold a list of references to
values.  Now, there's no need to have a value record whether or not it
is released -- there is only a single reference-counting mechanism for
values.  So, this also removes value::next, value::released, and
value_next.

gdb/ChangeLog
2018-04-06  Tom Tromey  <tom@tromey.com>

	* value.c (struct value) <released, next>: Remove.
	(all_values): Now a std::vector.
	(allocate_value_lazy): Update.
	(value_next): Remove.
	(value_mark, value_free_to_mark, release_value)
	(value_release_to_mark): Update.
This commit is contained in:
Tom Tromey 2018-04-03 21:52:31 -06:00
parent a6535de190
commit 062d818d25
2 changed files with 36 additions and 68 deletions

View file

@ -1,3 +1,12 @@
2018-04-06 Tom Tromey <tom@tromey.com>
* value.c (struct value) <released, next>: Remove.
(all_values): Now a std::vector.
(allocate_value_lazy): Update.
(value_next): Remove.
(value_mark, value_free_to_mark, release_value)
(value_release_to_mark): Update.
2018-04-06 Tom Tromey <tom@tromey.com> 2018-04-06 Tom Tromey <tom@tromey.com>
* value.h (fetch_subexp_value, value_release_to_mark): Update. * value.h (fetch_subexp_value, value_release_to_mark): Update.

View file

@ -198,9 +198,6 @@ struct value
used instead of read_memory to enable extra caching. */ used instead of read_memory to enable extra caching. */
unsigned int stack : 1; unsigned int stack : 1;
/* If the value has been released. */
unsigned int released : 1;
/* Location of value (if lval). */ /* Location of value (if lval). */
union union
{ {
@ -309,12 +306,6 @@ struct value
LONGEST embedded_offset; LONGEST embedded_offset;
LONGEST pointed_to_offset; LONGEST pointed_to_offset;
/* Values are stored in a chain, so that they can be deleted easily
over calls to the inferior. Values assigned to internal
variables, put into the value history or exposed to Python are
taken off this list. */
struct value *next;
/* Actual contents of the value. Target byte-order. NULL or not /* Actual contents of the value. Target byte-order. NULL or not
valid if lazy is nonzero. */ valid if lazy is nonzero. */
gdb_byte *contents; gdb_byte *contents;
@ -891,7 +882,7 @@ static std::vector<value_ref_ptr> value_history;
(except for those released by calls to release_value) (except for those released by calls to release_value)
This is so they can be freed after each command. */ This is so they can be freed after each command. */
static struct value *all_values; static std::vector<value_ref_ptr> all_values;
/* Allocate a lazy value for type TYPE. Its actual content is /* Allocate a lazy value for type TYPE. Its actual content is
"lazily" allocated too: the content field of the return value is "lazily" allocated too: the content field of the return value is
@ -912,8 +903,6 @@ allocate_value_lazy (struct type *type)
val = XCNEW (struct value); val = XCNEW (struct value);
val->contents = NULL; val->contents = NULL;
val->next = all_values;
all_values = val;
val->type = type; val->type = type;
val->enclosing_type = type; val->enclosing_type = type;
VALUE_LVAL (val) = not_lval; VALUE_LVAL (val) = not_lval;
@ -929,6 +918,7 @@ allocate_value_lazy (struct type *type)
/* Values start out on the all_values chain. */ /* Values start out on the all_values chain. */
val->reference_count = 1; val->reference_count = 1;
all_values.emplace_back (val);
return val; return val;
} }
@ -1070,12 +1060,6 @@ allocate_optimized_out_value (struct type *type)
/* Accessor methods. */ /* Accessor methods. */
struct value *
value_next (const struct value *value)
{
return value->next;
}
struct type * struct type *
value_type (const struct value *value) value_type (const struct value *value)
{ {
@ -1573,7 +1557,9 @@ deprecated_value_modifiable (const struct value *value)
struct value * struct value *
value_mark (void) value_mark (void)
{ {
return all_values; if (all_values.empty ())
return nullptr;
return all_values.back ().get ();
} }
/* Take a reference to VAL. VAL will not be deallocated until all /* Take a reference to VAL. VAL will not be deallocated until all
@ -1626,16 +1612,11 @@ value_decref (struct value *val)
void void
value_free_to_mark (const struct value *mark) value_free_to_mark (const struct value *mark)
{ {
struct value *val; auto iter = std::find (all_values.begin (), all_values.end (), mark);
struct value *next; if (iter == all_values.end ())
all_values.clear ();
for (val = all_values; val && val != mark; val = next) else
{ all_values.erase (iter + 1, all_values.end ());
next = val->next;
val->released = 1;
value_decref (val);
}
all_values = val;
} }
/* Remove VAL from the chain all_values /* Remove VAL from the chain all_values
@ -1645,40 +1626,25 @@ value_ref_ptr
release_value (struct value *val) release_value (struct value *val)
{ {
struct value *v; struct value *v;
bool released = false;
if (val == nullptr) if (val == nullptr)
return value_ref_ptr (); return value_ref_ptr ();
if (all_values == val) std::vector<value_ref_ptr>::reverse_iterator iter;
for (iter = all_values.rbegin (); iter != all_values.rend (); ++iter)
{ {
all_values = val->next; if (*iter == val)
val->next = NULL;
released = true;
}
else
{ {
for (v = all_values; v; v = v->next) value_ref_ptr result = *iter;
{ all_values.erase (iter.base () - 1);
if (v->next == val) return result;
{
v->next = val->next;
val->next = NULL;
released = true;
break;
}
} }
} }
if (!released) /* We must always return an owned reference. Normally this happens
{ because we transfer the reference from the value chain, but in
/* We must always return an owned reference. Normally this this case the value was not on the chain. */
happens because we transfer the reference from the value return value_ref_ptr (value_incref (val));
chain, but in this case the value was not on the chain. */
value_incref (val);
}
return value_ref_ptr (val);
} }
/* See value.h. */ /* See value.h. */
@ -1687,23 +1653,16 @@ std::vector<value_ref_ptr>
value_release_to_mark (const struct value *mark) value_release_to_mark (const struct value *mark)
{ {
std::vector<value_ref_ptr> result; std::vector<value_ref_ptr> result;
struct value *next;
for (next = all_values; next; next = next->next) auto iter = std::find (all_values.begin (), all_values.end (), mark);
if (iter == all_values.end ())
std::swap (result, all_values);
else
{ {
next->released = 1; std::move (iter + 1, all_values.end (), std::back_inserter (result));
result.emplace_back (next); all_values.erase (iter + 1, all_values.end ());
if (next->next == mark)
{
struct value *save = next->next;
next->next = NULL;
next = save;
break;
} }
} std::reverse (result.begin (), result.end ());
all_values = next;
return result; return result;
} }