+2018-04-06 Tom Tromey <tom@tromey.com>
+
+ * varobj.c (varobj_clear_saved_item)
+ (update_dynamic_varobj_children, install_new_value, ~varobj):
+ Update.
+ * value.h (value_incref): Move declaration earlier.
+ (value_decref): Rename from value_free.
+ (struct value_ref_policy): New.
+ (value_ref_ptr): New typedef.
+ (struct value_deleter): Remove.
+ (gdb_value_up): Remove typedef.
+ (release_value): Change return type.
+ (release_value_or_incref): Remove.
+ * value.c (set_value_parent): Update.
+ (value_incref): Change return type.
+ (value_decref): Rename from value_free.
+ (value_free_to_mark, free_all_values, free_value_chain): Update.
+ (release_value): Return value_ref_ptr.
+ (release_value_or_incref): Remove.
+ (record_latest_value, set_internalvar, clear_internalvar):
+ Update.
+ * stack.c (info_frame_command): Don't call value_free.
+ * python/py-value.c (valpy_dealloc, valpy_new)
+ (value_to_value_object): Update.
+ * printcmd.c (do_examine): Update.
+ * opencl-lang.c (lval_func_free_closure): Update.
+ * mi/mi-main.c (register_changed_p): Don't call value_free.
+ * mep-tdep.c (mep_frame_prev_register): Don't call value_free.
+ * m88k-tdep.c (m88k_frame_prev_register): Don't call value_free.
+ * m68hc11-tdep.c (m68hc11_frame_prev_register): Don't call
+ value_free.
+ * guile/scm-value.c (vlscm_free_value_smob)
+ (vlscm_scm_from_value): Update.
+ * frame.c (frame_register_unwind, frame_unwind_register_signed)
+ (frame_unwind_register_unsigned, get_frame_register_bytes)
+ (put_frame_register_bytes): Don't call value_free.
+ * findvar.c (address_from_register): Don't call value_free.
+ * dwarf2read.c (dwarf2_compute_name): Don't call value_free.
+ * dwarf2loc.c (entry_data_value_free_closure)
+ (value_of_dwarf_reg_entry, free_pieced_value_closure)
+ (dwarf2_evaluate_loc_desc_full): Update.
+ * breakpoint.c (update_watchpoint, breakpoint_init_inferior)
+ (~bpstats, bpstats, bpstat_clear_actions, watchpoint_check)
+ (~watchpoint, watch_command_1)
+ (invalidate_bp_value_on_memory_change): Update.
+ * alpha-tdep.c (alpha_register_to_value): Don't call value_free.
+
2018-04-06 Simon Marchi <simon.marchi@polymtl.ca>
PR gdb/23022
if (*optimizedp || *unavailablep)
{
release_value (value);
- value_free (value);
return 0;
}
alpha_sts (gdbarch, out, value_contents_all (value));
release_value (value);
- value_free (value);
return 1;
}
no longer relevant. We don't want to report a watchpoint hit
to the user when the old value and the new value may actually
be completely different objects. */
- value_free (b->val);
+ value_decref (b->val);
b->val = NULL;
b->val_valid = 0;
{
v = extract_bitfield_from_watchpoint_value (b, v);
if (v != NULL)
- release_value (v);
+ release_value (v).release ();
}
b->val = v;
b->val_valid = 1;
{
next = value_next (v);
if (v != b->val)
- value_free (v);
+ value_decref (v);
}
/* If a software watchpoint is not watching any memory, then the
/* Reset val field to force reread of starting value in
insert_breakpoints. */
if (w->val)
- value_free (w->val);
+ value_decref (w->val);
w->val = NULL;
w->val_valid = 0;
}
bpstats::~bpstats ()
{
if (old_val != NULL)
- value_free (old_val);
+ value_decref (old_val);
if (bp_location_at != NULL)
decref_bp_location (&bp_location_at);
}
print_it (other.print_it)
{
if (old_val != NULL)
- {
- old_val = value_copy (old_val);
- release_value (old_val);
- }
+ old_val = release_value (value_copy (old_val)).release ();
incref_bp_location (bp_location_at);
}
if (bs->old_val != NULL)
{
- value_free (bs->old_val);
+ value_decref (bs->old_val);
bs->old_val = NULL;
}
}
{
if (new_val != NULL)
{
- release_value (new_val);
+ release_value (new_val).release ();
value_free_to_mark (mark);
}
bs->old_val = b->val;
{
xfree (this->exp_string);
xfree (this->exp_string_reparse);
- value_free (this->val);
+ value_decref (this->val);
}
/* Implement the "re_set" breakpoint_ops method for watchpoints. */
int ret;
exp_valid_block = NULL;
- val = value_addr (result);
- release_value (val);
+ val = release_value (value_addr (result)).release ();
value_free_to_mark (mark);
if (use_mask)
}
}
else if (val != NULL)
- release_value (val);
+ release_value (val).release ();
tok = skip_spaces (arg);
end_tok = skip_to_space (tok);
&& loc->address + loc->length > addr
&& addr + len > loc->address)
{
- value_free (wp->val);
+ value_decref (wp->val);
wp->val = NULL;
wp->val_valid = 0;
}
{
struct value *target_val = (struct value *) value_computed_closure (v);
- value_free (target_val);
+ value_decref (target_val);
}
/* Vector for methods for an entry value reference where the referenced value
target_type, caller_frame,
caller_per_cu);
- release_value (target_val);
+ release_value (target_val).release ();
val = allocate_computed_value (type, &entry_data_value_funcs,
target_val /* closure */);
{
for (dwarf_expr_piece &p : c->pieces)
if (p.location == DWARF_VALUE_STACK)
- value_free (p.v.value);
+ value_decref (p.v.value);
delete c;
}
/* Preserve VALUE because we are going to free values back
to the mark, but we still need the value contents
below. */
- value_incref (value);
+ value_ref_ptr value_holder (value_incref (value));
free_values.free_to_mark ();
- gdb_value_up value_holder (value);
retval = allocate_value (subobj_type);
opts.raw = 1;
value_print (v, &buf, &opts);
release_value (v);
- value_free (v);
}
}
result = value_as_address (value);
release_value (value);
- value_free (value);
return result;
}
/* Dispose of the new value. This prevents watchpoints from
trying to watch the saved frame pointer. */
release_value (value);
- value_free (value);
}
void
byte_order);
release_value (value);
- value_free (value);
return r;
}
byte_order);
release_value (value);
- value_free (value);
return r;
}
if (*optimizedp || *unavailablep)
{
release_value (value);
- value_free (value);
return 0;
}
memcpy (myaddr, value_contents_all (value) + offset, curr_len);
release_value (value);
- value_free (value);
}
myaddr += curr_len;
curr_len);
put_frame_register (frame, regnum, value_contents_raw (value));
release_value (value);
- value_free (value);
}
myaddr += curr_len;
value_smob *v_smob = (value_smob *) SCM_SMOB_DATA (self);
vlscm_forget_value_smob (v_smob);
- value_free (v_smob->value);
+ value_decref (v_smob->value);
return 0;
}
SCM v_scm = vlscm_make_value_smob ();
value_smob *v_smob = (value_smob *) SCM_SMOB_DATA (v_scm);
- v_smob->value = value;
- release_value_or_incref (value);
+ v_smob->value = release_value (value).release ();
vlscm_remember_scheme_value (v_smob);
return v_scm;
CORE_ADDR page;
release_value (value);
- value_free (value);
value = trad_frame_get_prev_register (this_frame, info->saved_regs,
HARD_PAGE_REGNUM);
page = value_as_long (value);
release_value (value);
- value_free (value);
pc -= 0x08000;
pc += ((page & 0x0ff) << 14);
M88K_SXIP_REGNUM);
pc = value_as_long (value);
release_value (value);
- value_free (value);
if (regnum == M88K_SFIP_REGNUM)
pc += 4;
MEP_LP_REGNUM);
lp = value_as_long (value);
release_value (value);
- value_free (value);
return frame_unwind_got_constant (this_frame, regnum, lp & ~1);
}
psw = value_as_long (value);
release_value (value);
- value_free (value);
/* Get the LP's value, too. */
value = get_frame_register_value (this_frame, MEP_LP_REGNUM);
lp = value_as_long (value);
release_value (value);
- value_free (value);
/* If LP.LTOM is set, then toggle PSW.OM. */
if (lp & 0x1)
release_value (prev_value);
release_value (this_value);
- value_free (prev_value);
- value_free (this_value);
return ret;
}
if (c->refc == 0)
{
- value_free (c->val); /* Decrement the reference counter of the value. */
+ value_decref (c->val); /* Decrement the reference counter of the value. */
xfree (c->indices);
xfree (c);
}
last_examine_address = next_address;
if (last_examine_value)
- value_free (last_examine_value);
+ value_decref (last_examine_value);
/* The value to be displayed is not fetched greedily.
Instead, to avoid the possibility of a fetched value not
last_examine_value = value_at_lazy (val_type, next_address);
if (last_examine_value)
- release_value (last_examine_value);
+ release_value (last_examine_value).release ();
print_formatted (last_examine_value, size, &opts, gdb_stdout);
if (self->next)
self->next->prev = self->prev;
- value_free (self->value);
+ value_decref (self->value);
if (self->address)
/* Use braces to appease gcc warning. *sigh* */
return NULL;
}
- value_obj->value = value;
- release_value_or_incref (value);
+ value_obj->value = release_value (value).release ();
value_obj->address = NULL;
value_obj->type = NULL;
value_obj->dynamic_type = NULL;
val_obj = PyObject_New (value_object, &value_object_type);
if (val_obj != NULL)
{
- val_obj->value = val;
- release_value_or_incref (val);
+ val_obj->value = release_value (val).release ();
val_obj->address = NULL;
val_obj->type = NULL;
val_obj->dynamic_type = NULL;
}
release_value (value);
- value_free (value);
need_nl = 0;
}
/* else keep quiet. */
value->parent = parent;
if (parent != NULL)
value_incref (parent);
- value_free (old);
+ value_decref (old);
}
gdb_byte *
/* Take a reference to VAL. VAL will not be deallocated until all
references are released. */
-void
+struct value *
value_incref (struct value *val)
{
val->reference_count++;
+ return val;
}
/* Release a reference to VAL, which was acquired with value_incref.
chain. */
void
-value_free (struct value *val)
+value_decref (struct value *val)
{
if (val)
{
/* If there's an associated parent value, drop our reference to
it. */
if (val->parent != NULL)
- value_free (val->parent);
+ value_decref (val->parent);
if (VALUE_LVAL (val) == lval_computed)
{
{
next = val->next;
val->released = 1;
- value_free (val);
+ value_decref (val);
}
all_values = val;
}
{
next = val->next;
val->released = 1;
- value_free (val);
+ value_decref (val);
}
all_values = 0;
for (; v; v = next)
{
next = value_next (v);
- value_free (v);
+ value_decref (v);
}
}
/* Remove VAL from the chain all_values
so it will not be freed automatically. */
-void
+value_ref_ptr
release_value (struct value *val)
{
struct value *v;
+ bool released = false;
if (all_values == val)
{
all_values = val->next;
val->next = NULL;
- val->released = 1;
- return;
+ released = true;
}
-
- for (v = all_values; v; v = v->next)
+ else
{
- if (v->next == val)
+ for (v = all_values; v; v = v->next)
{
- v->next = val->next;
- val->next = NULL;
- val->released = 1;
- break;
+ if (v->next == val)
+ {
+ v->next = val->next;
+ val->next = NULL;
+ released = true;
+ break;
+ }
}
}
-}
-/* If the value is not already released, release it.
- If the value is already released, increment its reference count.
- That is, this function ensures that the value is released from the
- value chain and that the caller owns a reference to it. */
+ if (!released)
+ {
+ /* We must always return an owned reference. Normally this
+ happens because we transfer the reference from the value
+ chain, but in this case the value was not on the chain. */
+ value_incref (val);
+ }
-void
-release_value_or_incref (struct value *val)
-{
- if (val->released)
- value_incref (val);
- else
- release_value (val);
+ return value_ref_ptr (val);
}
/* Release all values up to mark */
but the current contents of that location. c'est la vie... */
val->modifiable = 0;
- /* The value may have already been released, in which case we're adding a
- new reference for its entry in the history. That is why we call
- release_value_or_incref here instead of release_value. */
- release_value_or_incref (val);
-
/* Here we treat value_history_count as origin-zero
and applying to the value being stored now. */
value_history_chain = newobj;
}
- value_history_chain->values[i] = val;
+ value_history_chain->values[i] = release_value (val).release ();
/* Now we regard value_history_count as origin-one
and applying to the value just stored. */
deleted by free_all_values. From here on this function should not
call error () until new_data is installed into the var->u to avoid
leaking memory. */
- release_value (new_data.value);
+ release_value (new_data.value).release ();
/* Internal variables which are created from values with a dynamic
location don't need the location property of the origin anymore.
switch (var->kind)
{
case INTERNALVAR_VALUE:
- value_free (var->u.value);
+ value_decref (var->u.value);
break;
case INTERNALVAR_STRING:
#include "frame.h" /* For struct frame_id. */
#include "extension.h"
+#include "common/gdb_ref_ptr.h"
struct block;
struct expression;
struct value;
+/* Decrease VAL's reference count. When the reference count drops to
+ 0, VAL will be freed. */
+
+extern struct value *value_incref (struct value *val);
+
+/* Increate VAL's reference count. VAL is returned. */
+
+extern void value_decref (struct value *val);
+
+/* A policy class to interface gdb::ref_ptr with struct value. */
+
+struct value_ref_policy
+{
+ static void incref (struct value *ptr)
+ {
+ value_incref (ptr);
+ }
+
+ static void decref (struct value *ptr)
+ {
+ value_decref (ptr);
+ }
+};
+
+/* A gdb:;ref_ptr pointer to a struct value. */
+
+typedef gdb::ref_ptr<struct value, value_ref_policy> value_ref_ptr;
+
/* 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
extern int destructor_name_p (const char *name, struct type *type);
-extern void value_incref (struct value *val);
-
-extern void value_free (struct value *val);
-
-/* A free policy class to interface std::unique_ptr with
- value_free. */
-
-struct value_deleter
-{
- void operator() (struct value *value) const
- {
- value_free (value);
- }
-};
-
-/* A unique pointer to a struct value. */
-
-typedef std::unique_ptr<struct value, value_deleter> gdb_value_up;
-
extern void free_all_values (void);
extern void free_value_chain (struct value *v);
-extern void release_value (struct value *val);
-
-extern void release_value_or_incref (struct value *val);
+extern value_ref_ptr release_value (struct value *val);
extern int record_latest_value (struct value *val);
{
if (var->saved_item != NULL)
{
- value_free (var->saved_item->value);
+ value_decref (var->saved_item->value);
delete var->saved_item;
var->saved_item = NULL;
}
/* Release vitem->value so its lifetime is not bound to the
execution of a command. */
if (item != NULL && item->value != NULL)
- release_value_or_incref (item->value);
+ release_value (item->value).release ();
}
if (item == NULL)
/* We must always keep the new value, since children depend on it. */
if (var->value != NULL && var->value != value)
- value_free (var->value);
+ value_decref (var->value);
var->value = value;
if (value && value_lazy (value) && intentionally_not_fetched)
var->not_fetched = true;
varobj_iter_delete (var->dynamic->child_iter);
varobj_clear_saved_item (var->dynamic);
- value_free (var->value);
+ value_decref (var->value);
if (is_root_p (var))
delete var->root;