diff options
author | Simon Marchi <simon.marchi@polymtl.ca> | 2018-01-07 09:25:32 -0500 |
---|---|---|
committer | Simon Marchi <simon.marchi@ericsson.com> | 2018-01-07 09:25:32 -0500 |
commit | ba18742c3a1b62ff218db99bee47bb932af6dab9 (patch) | |
tree | 14680d97dbbc56e326a6b2bda0bb1ba25dbd6970 /gdb/python | |
parent | d672364615e87e8c366b536940f269fdc3141330 (diff) | |
download | gdb-ba18742c3a1b62ff218db99bee47bb932af6dab9.zip gdb-ba18742c3a1b62ff218db99bee47bb932af6dab9.tar.gz gdb-ba18742c3a1b62ff218db99bee47bb932af6dab9.tar.bz2 |
C++ify xmethod_worker, get rid of VEC(xmethod_worker_ptr)
The initial goal of this patch was to remove the usage of
VEC(xmethod_worker_ptr) and corresponding cleanups. I ended up having
to C++ify the xmethod_worker code, to be able to have xmethod_workers
free their data in destructors, and therefore be able to use vectors of
xmethod_worker unique_ptr.
The operations in extension_language_ops that act on one instance of
xmethod_worker (get result type, get args type, invoke) are transformed
to methods of xmethod_worker. xmethod_worker becomes an abstract base
class with virtual pure methods which python_xmethod_worker implements.
The only xmethod-related operation left in extension_language_ops is
get_matching_xmethod_workers, which returns a list of xmethod_workers.
The changes are relatively straightforward, but here are some notes on
things that may raise eyebrows:
- I was not really comfortable with the value_of_xmethod function. At
first it looks like a simple getter, so I considered making it a
method of xmethod_worker. But actually it creates a value and
transfers the ownership of the xmethod_worker to it. It would be a
bit weird and error-prone if calling a method on an object silently
removed the ownership of the object from the caller. To reflect the
behavior more accurately, I renamed it to value_from_xmethod and made
it accept an rvalue-reference (so the caller knows it gives away the
ownership). I noticed the backlink from xmethod_worker to its owning
value was not used, so I removed it.
- Some code, like get_matching_xmethod_workers, made each callee fill
a new vector, which was then merged in the result vector. I think
it's safe if we always pass the same vector around, and each
implementation just appends to it.
- The clone operation does not seem particularly useful, it is removed
in the following patch.
gdb/ChangeLog:
* extension-priv.h (enum ext_lang_rc): Remove, move to extension.h.
(struct extension_language_ops) <clone_xmethod_worker_data>: Remove.
<free_xmethod_worker_data>: Remove.
<get_matching_xmethod_workers>: Chance VEC to std::vector.
<get_xmethod_arg_types>: Remove.
<get_xmethod_result_type>: Remove.
<invoke_xmethod>: Remove.
* extension.c (new_xmethod_worker): Remove.
(clone_xmethod_worker): Remove.
(get_matching_xmethod_workers): Return void, pass std::vector by
pointer.
(get_xmethod_arg_types): Rename to...
(xmethod_worker::get_arg_types): ... this, and adjust.
(get_xmethod_result_type): Rename to...
(xmethod_worker::get_result_type): ... this, and adjust.
(invoke_xmethod): Remove.
(free_xmethod_worker): Remove.
(free_xmethod_worker_vec): Remove.
* extension.h (enum ext_lang_rc): Move here from
extension-priv.h.
(struct xmethod_worker): Add constructor and destructor.
<data>: Remove.
<value>: Remove.
<invoke, clone, do_get_result_type, do_get_arg_types>: New
virtual pure methods.
<get_arg_types, get_result_type>: New methods.
(xmethod_worker_ptr): Remove typedef.
(DEF_VEC_P (xmethod_worker_ptr)): Remove.
(xmethod_worker_vec): Remove typedef.
(xmethod_worker_up): New typedef.
(invoke_xmethod): Remove.
(clone_xmethod_worker): Remove.
(free_xmethod_worker): Remove.
(free_xmethod_worker_vec): Remove.
(get_xmethod_arg_types): Remove.
(get_xmethod_result_type): Remove.
* valops.c (find_method_list): Use std::vector, don't use
intermediate vector.
(value_find_oload_method_list): Use std::vector.
(find_overload_match): Use std::vector.
(find_oload_champ): Use std::vector.
* value.c (value_free): Use operator delete.
(value_of_xmethod): Rename to...
(value_from_xmethod): ... this. Don't assign
xmethod_worker::value, take rvalue-reference.
(result_type_of_xmethod): Adjust.
(call_xmethod): Adjust.
* value.h: Include extension.h.
(struct xmethod_worker): Don't forward-declare.
(value_of_xmethod): Rename to...
(value_from_xmethod): ... this, take rvalue-reference.
* python/py-xmethods.c (struct gdbpy_worker_data): Rename to...
(struct python_xmethod_worker): ... this, add constructor and
destructor.
<invoke, clone, do_get_arg_types, do_get_result_type>: Implement.
(gdbpy_free_xmethod_worker_data): Rename to...
(python_xmethod_worker::~python_xmethod_worker): ... this and
adjust.
(gdbpy_clone_xmethod_worker_data): Rename to...
(python_xmethod_worker::clone): ... this and adjust.
(gdbpy_get_matching_xmethod_workers): Use std::vector, don't use
temporary vector.
(gdbpy_get_xmethod_arg_types): Rename to...
(python_xmethod_worker::do_get_arg_types): ... this and adjust.
(gdbpy_get_xmethod_result_type): Rename to...
(python_xmethod_worker::do_get_result_type): ... this and
adjust.
(gdbpy_invoke_xmethod): Rename to...
(python_xmethod_worker::invoke): ... this and adjust.
(new_python_xmethod_worker): Rename to...
(python_xmethod_worker::python_xmethod_worker): ... this and
adjust.
* python/python-internal.h (gdbpy_clone_xmethod_worker_data):
Remove.
(gdbpy_free_xmethod_worker_data): Remove.
(gdbpy_get_matching_xmethod_workers): Use std::vector.
(gdbpy_get_xmethod_arg_types): Remove.
(gdbpy_get_xmethod_result_type): Remove.
(gdbpy_invoke_xmethod): Remove.
* python/python.c (python_extension_ops): Remove obsolete
callbacks.
Diffstat (limited to 'gdb/python')
-rw-r--r-- | gdb/python/py-xmethods.c | 154 | ||||
-rw-r--r-- | gdb/python/python-internal.h | 21 | ||||
-rw-r--r-- | gdb/python/python.c | 5 |
3 files changed, 69 insertions, 111 deletions
diff --git a/gdb/python/py-xmethods.c b/gdb/python/py-xmethods.c index 750f263..f4064c2 100644 --- a/gdb/python/py-xmethods.c +++ b/gdb/python/py-xmethods.c @@ -37,54 +37,60 @@ static const char matchers_attr_str[] = "xmethods"; static PyObject *py_match_method_name = NULL; static PyObject *py_get_arg_types_method_name = NULL; -struct gdbpy_worker_data +struct python_xmethod_worker : xmethod_worker { - PyObject *worker; - PyObject *this_type; -}; + python_xmethod_worker (PyObject *worker, PyObject *this_type); + ~python_xmethod_worker (); -static struct xmethod_worker *new_python_xmethod_worker (PyObject *item, - PyObject *py_obj_type); + DISABLE_COPY_AND_ASSIGN (python_xmethod_worker); -/* Implementation of free_xmethod_worker_data for Python. */ + /* Implementation of xmethod_worker::invoke for Python. */ -void -gdbpy_free_xmethod_worker_data (const struct extension_language_defn *extlang, - void *data) -{ - struct gdbpy_worker_data *worker_data = (struct gdbpy_worker_data *) data; + value *invoke (value *obj, value **args, int nargs) override; + + /* Implementation of xmethod_worker::clone for Python. */ + + xmethod_worker_up clone () override; + + /* Implementation of xmethod_worker::do_get_arg_types for Python. */ + + ext_lang_rc do_get_arg_types (int *nargs, type ***arg_types) override; + + /* Implementation of xmethod_worker::do_get_result_type for Python. - gdb_assert (worker_data->worker != NULL && worker_data->this_type != NULL); + For backward compatibility with 7.9, which did not support getting the + result type, if the get_result_type operation is not provided by WORKER + then EXT_LANG_RC_OK is returned and NULL is returned in *RESULT_TYPE. */ + ext_lang_rc do_get_result_type (value *obj, value **args, int nargs, + type **result_type_ptr) override; + +private: + + PyObject *m_py_worker; + PyObject *m_this_type; +}; + +python_xmethod_worker::~python_xmethod_worker () +{ /* We don't do much here, but we still need the GIL. */ gdbpy_enter enter_py (get_current_arch (), current_language); - Py_DECREF (worker_data->worker); - Py_DECREF (worker_data->this_type); - xfree (worker_data); + Py_DECREF (m_py_worker); + Py_DECREF (m_this_type); } -/* Implementation of clone_xmethod_worker_data for Python. */ +/* See declaration. */ -void * -gdbpy_clone_xmethod_worker_data (const struct extension_language_defn *extlang, - void *data) +xmethod_worker_up +python_xmethod_worker::clone () { - struct gdbpy_worker_data *worker_data - = (struct gdbpy_worker_data *) data, *new_data; - - gdb_assert (worker_data->worker != NULL && worker_data->this_type != NULL); - /* We don't do much here, but we still need the GIL. */ gdbpy_enter enter_py (get_current_arch (), current_language); - new_data = XCNEW (struct gdbpy_worker_data); - new_data->worker = worker_data->worker; - new_data->this_type = worker_data->this_type; - Py_INCREF (new_data->worker); - Py_INCREF (new_data->this_type); + xmethod_worker *worker = new python_xmethod_worker (m_py_worker, m_this_type); - return new_data; + return xmethod_worker_up (worker); } /* Invoke the "match" method of the MATCHER and return a new reference @@ -130,10 +136,9 @@ enum ext_lang_rc gdbpy_get_matching_xmethod_workers (const struct extension_language_defn *extlang, struct type *obj_type, const char *method_name, - xmethod_worker_vec **dm_vec) + std::vector<xmethod_worker_up> *dm_vec) { struct objfile *objfile; - VEC (xmethod_worker_ptr) *worker_vec = NULL; PyObject *py_progspace; gdb_assert (obj_type != NULL && method_name != NULL); @@ -282,39 +287,33 @@ gdbpy_get_matching_xmethod_workers break; } - worker = new_python_xmethod_worker (py_worker.get (), + worker = new python_xmethod_worker (py_worker.get (), py_type.get ()); - VEC_safe_push (xmethod_worker_ptr, worker_vec, worker); + + dm_vec->emplace_back (worker); } } else { struct xmethod_worker *worker; - worker = new_python_xmethod_worker (match_result.get (), + worker = new python_xmethod_worker (match_result.get (), py_type.get ()); - VEC_safe_push (xmethod_worker_ptr, worker_vec, worker); + dm_vec->emplace_back (worker); } } - *dm_vec = worker_vec; - return EXT_LANG_RC_OK; } -/* Implementation of get_xmethod_arg_types for Python. */ +/* See declaration. */ -enum ext_lang_rc -gdbpy_get_xmethod_arg_types (const struct extension_language_defn *extlang, - struct xmethod_worker *worker, - int *nargs, struct type ***arg_types) +ext_lang_rc +python_xmethod_worker::do_get_arg_types (int *nargs, type ***arg_types) { /* The gdbpy_enter object needs to be placed first, so that it's the last to be destroyed. */ gdbpy_enter enter_py (get_current_arch (), current_language); - struct gdbpy_worker_data *worker_data - = (struct gdbpy_worker_data *) worker->data; - PyObject *py_worker = worker_data->worker; struct type *obj_type; int i = 1, arg_count; gdbpy_ref<> list_iter; @@ -324,7 +323,7 @@ gdbpy_get_xmethod_arg_types (const struct extension_language_defn *extlang, *nargs = -1; gdbpy_ref<> get_arg_types_method - (PyObject_GetAttrString (py_worker, get_arg_types_method_name)); + (PyObject_GetAttrString (m_py_worker, get_arg_types_method_name)); if (get_arg_types_method == NULL) { gdbpy_print_stack (); @@ -332,7 +331,7 @@ gdbpy_get_xmethod_arg_types (const struct extension_language_defn *extlang, } gdbpy_ref<> py_argtype_list - (PyObject_CallMethodObjArgs (py_worker, py_get_arg_types_method_name, + (PyObject_CallMethodObjArgs (m_py_worker, py_get_arg_types_method_name, NULL)); if (py_argtype_list == NULL) { @@ -418,7 +417,7 @@ gdbpy_get_xmethod_arg_types (const struct extension_language_defn *extlang, /* Add the type of 'this' as the first argument. The 'this' pointer should be a 'const' value. Hence, create a 'const' variant of the 'this' pointer type. */ - obj_type = type_object_to_type (worker_data->this_type); + obj_type = type_object_to_type (m_this_type); (type_array.get ())[0] = make_cv_type (1, 0, lookup_pointer_type (obj_type), NULL); *nargs = i; @@ -427,18 +426,12 @@ gdbpy_get_xmethod_arg_types (const struct extension_language_defn *extlang, return EXT_LANG_RC_OK; } -/* Implementation of get_xmethod_result_type for Python. */ +/* See declaration. */ -enum ext_lang_rc -gdbpy_get_xmethod_result_type (const struct extension_language_defn *extlang, - struct xmethod_worker *worker, - struct value *obj, - struct value **args, int nargs, - struct type **result_type_ptr) +ext_lang_rc +python_xmethod_worker::do_get_result_type (value *obj, value **args, int nargs, + type **result_type_ptr) { - struct gdbpy_worker_data *worker_data - = (struct gdbpy_worker_data *) worker->data; - PyObject *py_worker = worker_data->worker; struct type *obj_type, *this_type; int i; @@ -447,7 +440,7 @@ gdbpy_get_xmethod_result_type (const struct extension_language_defn *extlang, /* First see if there is a get_result_type method. If not this could be an old xmethod (pre 7.9.1). */ gdbpy_ref<> get_result_type_method - (PyObject_GetAttrString (py_worker, get_result_type_method_name)); + (PyObject_GetAttrString (m_py_worker, get_result_type_method_name)); if (get_result_type_method == NULL) { PyErr_Clear (); @@ -456,7 +449,7 @@ gdbpy_get_xmethod_result_type (const struct extension_language_defn *extlang, } obj_type = check_typedef (value_type (obj)); - this_type = check_typedef (type_object_to_type (worker_data->this_type)); + this_type = check_typedef (type_object_to_type (m_this_type)); if (TYPE_CODE (obj_type) == TYPE_CODE_PTR) { struct type *this_ptr = lookup_pointer_type (this_type); @@ -528,24 +521,20 @@ gdbpy_get_xmethod_result_type (const struct extension_language_defn *extlang, return EXT_LANG_RC_OK; } -/* Implementation of invoke_xmethod for Python. */ +/* See declaration. */ struct value * -gdbpy_invoke_xmethod (const struct extension_language_defn *extlang, - struct xmethod_worker *worker, - struct value *obj, struct value **args, int nargs) +python_xmethod_worker::invoke (struct value *obj, struct value **args, + int nargs) { + gdbpy_enter enter_py (get_current_arch (), current_language); + int i; struct type *obj_type, *this_type; struct value *res = NULL; - struct gdbpy_worker_data *worker_data - = (struct gdbpy_worker_data *) worker->data; - PyObject *xmethod_worker = worker_data->worker; - - gdbpy_enter enter_py (get_current_arch (), current_language); obj_type = check_typedef (value_type (obj)); - this_type = check_typedef (type_object_to_type (worker_data->this_type)); + this_type = check_typedef (type_object_to_type (m_this_type)); if (TYPE_CODE (obj_type) == TYPE_CODE_PTR) { struct type *this_ptr = lookup_pointer_type (this_type); @@ -597,7 +586,7 @@ gdbpy_invoke_xmethod (const struct extension_language_defn *extlang, PyTuple_SET_ITEM (py_arg_tuple.get (), i + 1, py_value_arg); } - gdbpy_ref<> py_result (PyObject_CallObject (xmethod_worker, + gdbpy_ref<> py_result (PyObject_CallObject (m_py_worker, py_arg_tuple.get ())); if (py_result == NULL) { @@ -623,24 +612,15 @@ gdbpy_invoke_xmethod (const struct extension_language_defn *extlang, return res; } -/* Creates a new Python xmethod_worker object. - The new object has data of type 'struct gdbpy_worker_data' composed - with the components PY_WORKER and THIS_TYPE. */ - -static struct xmethod_worker * -new_python_xmethod_worker (PyObject *py_worker, PyObject *this_type) +python_xmethod_worker::python_xmethod_worker (PyObject *py_worker, + PyObject *this_type) +: xmethod_worker (&extension_language_python), + m_py_worker (py_worker), m_this_type (this_type) { - struct gdbpy_worker_data *data; - - gdb_assert (py_worker != NULL && this_type != NULL); + gdb_assert (m_py_worker != NULL && m_this_type != NULL); - data = XCNEW (struct gdbpy_worker_data); - data->worker = py_worker; - data->this_type = this_type; Py_INCREF (py_worker); Py_INCREF (this_type); - - return new_xmethod_worker (&extension_language_python, data); } int diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h index f32a258..f38f0b3 100644 --- a/gdb/python/python-internal.h +++ b/gdb/python/python-internal.h @@ -463,28 +463,11 @@ extern enum ext_lang_bp_stop gdbpy_breakpoint_cond_says_stop extern int gdbpy_breakpoint_has_cond (const struct extension_language_defn *, struct breakpoint *b); -extern void *gdbpy_clone_xmethod_worker_data - (const struct extension_language_defn *extlang, void *data); -extern void gdbpy_free_xmethod_worker_data - (const struct extension_language_defn *extlang, void *data); extern enum ext_lang_rc gdbpy_get_matching_xmethod_workers (const struct extension_language_defn *extlang, struct type *obj_type, const char *method_name, - xmethod_worker_vec **dm_vec); -extern enum ext_lang_rc gdbpy_get_xmethod_arg_types - (const struct extension_language_defn *extlang, - struct xmethod_worker *worker, - int *nargs, - struct type ***arg_types); -extern enum ext_lang_rc gdbpy_get_xmethod_result_type - (const struct extension_language_defn *extlang, - struct xmethod_worker *worker, - struct value *object, struct value **args, int nargs, - struct type **result_type); -extern struct value *gdbpy_invoke_xmethod - (const struct extension_language_defn *extlang, - struct xmethod_worker *worker, - struct value *obj, struct value **args, int nargs); + std::vector<xmethod_worker_up> *dm_vec); + PyObject *gdbpy_history (PyObject *self, PyObject *args); PyObject *gdbpy_breakpoints (PyObject *, PyObject *); diff --git a/gdb/python/python.c b/gdb/python/python.c index 4844c86..9eae8a1 100644 --- a/gdb/python/python.c +++ b/gdb/python/python.c @@ -190,12 +190,7 @@ const struct extension_language_ops python_extension_ops = gdbpy_before_prompt_hook, - gdbpy_clone_xmethod_worker_data, - gdbpy_free_xmethod_worker_data, gdbpy_get_matching_xmethod_workers, - gdbpy_get_xmethod_arg_types, - gdbpy_get_xmethod_result_type, - gdbpy_invoke_xmethod }; /* Architecture and language to be used in callbacks from |