Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [02/15] Python interpreter callback functions
@ 2009-06-09 15:15 Ulrich Weigand
  2009-06-09 17:59 ` Tom Tromey
  0 siblings, 1 reply; 6+ messages in thread
From: Ulrich Weigand @ 2009-06-09 15:15 UTC (permalink / raw)
  To: gdb-patches

Hello,

Python support has re-introduced a number of reference to current_gdbarch
(and current_language) that are somewhat hard to eliminate as they happen
from within callback routines called by the Pyhton interpreter.

My solution to this problem is to use a set of global variables called
python_gdbarch and python_langague that are initialized whenever we are
about to call into the Python interpreter, and which are used from within
those callbacks.

We're using
- "current" architecture/language for top-level CLI calls
- expression architecture/language when evaluating an internal function
- varobj architecture/language when pretty-printing a varobj

If there's a more elegant way of passing this sort of environmental
information through the Python interpreter, I'd appreciate any hints
from the Python experts ;-)


ChangeLog:

	* python/python-internal.h (struct language_defn): Declare.
	(python_gdbarch, python_language): Likewise.
	(make_cleanup_python_env): Add prototype.

	* python/python.c: Include "arch-utils.h", "value.h" and "language.h".
	(python_gdbarch, python_language): New global variables.
	(make_cleanup_python_env, clear_python_env): New functions.
	(eval_python_from_control_command): Call make_cleanup_python_env to
	install current architecture and language.
	(python_command): Likewise.
	* python/python-command.c: Include "arch-utils.h" and "language.h".
	(cmdpy_function, cmdpy_completer): Call make_cleanup_python_env.
	* python/python-prettyprint.c (apply_val_pretty_printer): Likewise.
	* varobj.c (update_dynamic_varobj_children, install_default_visualizer,
	varobj_set_visualizer, value_get_print_value): Likewise.

	* value.h (internal_function_fn): Add GDBARCH and LANGUAGE argument.
	(call_internal_function): Likewise.
	* value.c (call_internal_function): Likewise.  Pass to handler.
	* eval.c (evaluate_subexp_standard): Update call.
	* python/python-function.c: Include "language.h".
	(fnpy_call): Add GDBARCH and LANGAUAGE arguments and call
	make_cleanup_python_env.

	* python/python-value.c (builtin_type_pyint, builtin_type_pyfloat,
	builtin_type_pylong, builtin_type_pybool, builtin_type_pychar,
	valpy_str): Use python_gdbarch and python_language instead of
	current_gdbarch and current_language.
	* python/python-type.c (typy_lookup_typename): Likewise.


Index: gdb-head/gdb/python/python.c
===================================================================
--- gdb-head.orig/gdb/python/python.c
+++ gdb-head/gdb/python/python.c
@@ -18,12 +18,15 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
+#include "arch-utils.h"
 #include "command.h"
 #include "ui-out.h"
 #include "cli/cli-script.h"
 #include "gdbcmd.h"
 #include "objfiles.h"
 #include "observer.h"
+#include "value.h"
+#include "language.h"
 
 #include <ctype.h>
 
@@ -58,6 +61,45 @@ PyObject *gdbpy_children_cst;
 PyObject *gdbpy_display_hint_cst;
 PyObject *gdbpy_doc_cst;
 
+
+/* Architecture and language to be used in callbacks from
+   the Python interpreter.  */
+struct gdbarch *python_gdbarch;
+const struct language_defn *python_language;
+
+/* Clear out global language and architecture when leaving the
+   Python interpreter.  */
+static void
+clear_python_env (void *p)
+{
+  python_gdbarch = NULL;
+  python_language = NULL;
+}
+
+/* Called before entering the Python interpreter to install the
+   current language and architecture to be used for Python values.  */
+struct cleanup *
+make_cleanup_python_env (struct gdbarch *gdbarch,
+                         const struct language_defn *language)
+{
+  /* Allow recursive calls, e.g. via valpy_str calling common_val_print
+     calling back into the Python pretty-printer, but only if gdbarch
+     and language match.  Do *not* install a cleanup for the recursive
+     case.  */
+  if (python_gdbarch || python_language)
+    {
+      gdb_assert (python_gdbarch == gdbarch);
+      gdb_assert (python_language == language);
+      return NULL;
+    }
+
+  python_gdbarch = gdbarch;
+  python_language = language;
+
+  return make_cleanup (clear_python_env, NULL);
+}
+
+
 /* Given a command_line, return a command string suitable for passing
    to Python.  Lines in the string are separated by newlines.  The
    return value is allocated using xmalloc and the caller is
@@ -104,6 +146,8 @@ eval_python_from_control_command (struct
   state = PyGILState_Ensure ();
   cleanup = make_cleanup_py_restore_gil (&state);
 
+  make_cleanup_python_env (get_current_arch (), current_language);
+
   script = compute_python_string (cmd->body_list[0]);
   ret = PyRun_SimpleString (script);
   xfree (script);
@@ -131,6 +175,8 @@ python_command (char *arg, int from_tty)
     ++arg;
   if (arg && *arg)
     {
+      make_cleanup_python_env (get_current_arch (), current_language);
+
       if (PyRun_SimpleString (arg))
 	{
 	  gdbpy_print_stack ();
Index: gdb-head/gdb/python/python-internal.h
===================================================================
--- gdb-head.orig/gdb/python/python-internal.h
+++ gdb-head/gdb/python/python-internal.h
@@ -62,6 +62,7 @@ typedef int Py_ssize_t;
 #endif
 
 struct value;
+struct language_defn;
 
 extern PyObject *gdb_module;
 extern PyTypeObject value_object_type;
@@ -91,6 +92,12 @@ void gdbpy_initialize_objfile (void);
 struct cleanup *make_cleanup_py_decref (PyObject *py);
 struct cleanup *make_cleanup_py_restore_gil (PyGILState_STATE *state);
 
+struct cleanup *make_cleanup_python_env (struct gdbarch *gdbarch,
+					 const struct language_defn *language);
+
+extern struct gdbarch *python_gdbarch;
+extern const struct language_defn *python_language;
+
 /* Use this after a TRY_EXCEPT to throw the appropriate Python
    exception.  */
 #define GDB_PY_HANDLE_EXCEPTION(Exception)				\
Index: gdb-head/gdb/python/python-value.c
===================================================================
--- gdb-head.orig/gdb/python/python-value.c
+++ gdb-head/gdb/python/python-value.c
@@ -44,19 +44,19 @@ struct value *values_in_python = NULL;
    GDB (which uses target arithmetic).  */
 
 /* Python's integer type corresponds to C's long type.  */
-#define builtin_type_pyint builtin_type (current_gdbarch)->builtin_long
+#define builtin_type_pyint builtin_type (python_gdbarch)->builtin_long
 
 /* Python's float type corresponds to C's double type.  */
-#define builtin_type_pyfloat builtin_type (current_gdbarch)->builtin_double
+#define builtin_type_pyfloat builtin_type (python_gdbarch)->builtin_double
 
 /* Python's long type corresponds to C's long long type.  */
-#define builtin_type_pylong builtin_type (current_gdbarch)->builtin_long_long
+#define builtin_type_pylong builtin_type (python_gdbarch)->builtin_long_long
 
 #define builtin_type_pybool \
-  language_bool_type (current_language, current_gdbarch)
+  language_bool_type (python_language, python_gdbarch)
 
 #define builtin_type_pychar \
-  language_string_char_type (current_language, current_gdbarch)
+  language_string_char_type (python_language, python_gdbarch)
 
 typedef struct {
   PyObject_HEAD
@@ -333,7 +333,7 @@ valpy_str (PyObject *self)
   TRY_CATCH (except, RETURN_MASK_ALL)
     {
       common_val_print (((value_object *) self)->value, stb, 0,
-			&opts, current_language);
+			&opts, python_language);
       s = ui_file_xstrdup (stb, &dummy);
     }
   GDB_PY_HANDLE_EXCEPTION (except);
Index: gdb-head/gdb/value.c
===================================================================
--- gdb-head.orig/gdb/value.c
+++ gdb-head/gdb/value.c
@@ -1243,7 +1243,9 @@ value_internal_function_name (struct val
 }
 
 struct value *
-call_internal_function (struct value *func, int argc, struct value **argv)
+call_internal_function (struct gdbarch *gdbarch,
+			const struct language_defn *language,
+			struct value *func, int argc, struct value **argv)
 {
   struct internal_function *ifn;
   int result;
@@ -1252,7 +1254,7 @@ call_internal_function (struct value *fu
   result = get_internalvar_function (VALUE_INTERNALVAR (func), &ifn);
   gdb_assert (result);
 
-  return (*ifn->handler) (ifn->cookie, argc, argv);
+  return (*ifn->handler) (gdbarch, language, ifn->cookie, argc, argv);
 }
 
 /* The 'function' command.  This does nothing -- it is just a
Index: gdb-head/gdb/python/python-cmd.c
===================================================================
--- gdb-head.orig/gdb/python/python-cmd.c
+++ gdb-head/gdb/python/python-cmd.c
@@ -19,6 +19,7 @@
 
 
 #include "defs.h"
+#include "arch-utils.h"
 #include "value.h"
 #include "exceptions.h"
 #include "python-internal.h"
@@ -26,6 +27,7 @@
 #include "gdbcmd.h"
 #include "cli/cli-decode.h"
 #include "completer.h"
+#include "language.h"
 
 /* Struct representing built-in completion types.  */
 struct cmdpy_completer
@@ -120,6 +122,8 @@ cmdpy_function (struct cmd_list_element 
   state = PyGILState_Ensure ();
   cleanup = make_cleanup_py_restore_gil (&state);
 
+  make_cleanup_python_env (get_current_arch (), current_language);
+
   if (! obj)
     error (_("Invalid invocation of Python command object."));
   if (! PyObject_HasAttr ((PyObject *) obj, invoke_cst))
@@ -187,6 +191,8 @@ cmdpy_completer (struct cmd_list_element
   state = PyGILState_Ensure ();
   cleanup = make_cleanup_py_restore_gil (&state);
 
+  make_cleanup_python_env (get_current_arch (), current_language);
+
   if (! obj)
     error (_("Invalid invocation of Python command object."));
   if (! PyObject_HasAttr ((PyObject *) obj, complete_cst))
Index: gdb-head/gdb/python/python-function.c
===================================================================
--- gdb-head.orig/gdb/python/python-function.c
+++ gdb-head/gdb/python/python-function.c
@@ -27,6 +27,7 @@
 #include "cli/cli-decode.h"
 #include "completer.h"
 #include "expression.h"
+#include "language.h"
 
 static PyTypeObject fnpy_object_type;
 
@@ -53,7 +54,8 @@ convert_values_to_python (int argc, stru
 /* Call a Python function object's invoke method.  */
 
 static struct value *
-fnpy_call (void *cookie, int argc, struct value **argv)
+fnpy_call (struct gdbarch *gdbarch, const struct language_defn *language,
+	   void *cookie, int argc, struct value **argv)
 {
   int i;
   struct value *value = NULL;
@@ -66,6 +68,8 @@ fnpy_call (void *cookie, int argc, struc
 
   args = convert_values_to_python (argc, argv);
 
+  make_cleanup_python_env (gdbarch, language);
+
   callable = PyObject_GetAttrString ((PyObject *) cookie, "invoke");
   if (! callable)
     {
Index: gdb-head/gdb/value.h
===================================================================
--- gdb-head.orig/gdb/value.h
+++ gdb-head/gdb/value.h
@@ -666,7 +666,9 @@ extern struct value * value_subscripted_
 
 /* User function handler.  */
 
-typedef struct value *(*internal_function_fn) (void *cookie,
+typedef struct value *(*internal_function_fn) (struct gdbarch *gdbarch,
+					       const struct language_defn *language,
+					       void *cookie,
 					       int argc,
 					       struct value **argv);
 
@@ -674,7 +676,9 @@ void add_internal_function (const char *
 			    internal_function_fn handler,
 			    void *cookie);
 
-struct value *call_internal_function (struct value *function,
+struct value *call_internal_function (struct gdbarch *gdbarch,
+				      const struct language_defn *language,
+				      struct value *function,
 				      int argc, struct value **argv);
 
 char *value_internal_function_name (struct value *);
Index: gdb-head/gdb/eval.c
===================================================================
--- gdb-head.orig/gdb/eval.c
+++ gdb-head/gdb/eval.c
@@ -1523,7 +1523,8 @@ evaluate_subexp_standard (struct type *e
 	    error (_("Expression of type other than \"Function returning ...\" used as function"));
 	}
       if (TYPE_CODE (value_type (argvec[0])) == TYPE_CODE_INTERNAL_FUNCTION)
-	return call_internal_function (argvec[0], nargs, argvec + 1);
+	return call_internal_function (exp->gdbarch, exp->language_defn,
+				       argvec[0], nargs, argvec + 1);
 
       return call_function_by_hand (argvec[0], nargs, argvec + 1);
       /* pai: FIXME save value from call_function_by_hand, then adjust pc by adjust_fn_pc if +ve  */
Index: gdb-head/gdb/python/python-type.c
===================================================================
--- gdb-head.orig/gdb/python/python-type.c
+++ gdb-head/gdb/python/python-type.c
@@ -374,7 +374,7 @@ typy_lookup_typename (char *type_name)
       else if (!strncmp (type_name, "enum ", 5))
 	type = lookup_enum (type_name + 5, NULL);
       else
-	type = lookup_typename (current_language, current_gdbarch,
+	type = lookup_typename (python_language, python_gdbarch,
 				type_name, NULL, 0);
     }
   if (except.reason < 0)
Index: gdb-head/gdb/python/python-prettyprint.c
===================================================================
--- gdb-head.orig/gdb/python/python-prettyprint.c
+++ gdb-head/gdb/python/python-prettyprint.c
@@ -477,6 +477,8 @@ apply_val_pretty_printer (struct type *t
   state = PyGILState_Ensure ();
   cleanups = make_cleanup_py_restore_gil (&state);
 
+  make_cleanup_python_env (current_gdbarch, language);
+
   /* Instantiate the printer.  */
   if (valaddr)
     valaddr += embedded_offset;
Index: gdb-head/gdb/varobj.c
===================================================================
--- gdb-head.orig/gdb/varobj.c
+++ gdb-head/gdb/varobj.c
@@ -846,6 +846,9 @@ update_dynamic_varobj_children (struct v
   state = PyGILState_Ensure ();
   back_to = make_cleanup_py_restore_gil (&state);
 
+  make_cleanup_python_env (var->root->exp->gdbarch,
+			   var->root->exp->language_defn);
+
   *cchanged = 0;
   if (!PyObject_HasAttr (printer, gdbpy_children_cst))
     {
@@ -1407,6 +1410,9 @@ install_default_visualizer (struct varob
   state = PyGILState_Ensure ();
   cleanup = make_cleanup_py_restore_gil (&state);
 
+  make_cleanup_python_env (var->root->exp->gdbarch,
+			   var->root->exp->language_defn);
+
   if (var->value)
     {
       pretty_printer = gdbpy_get_varobj_pretty_printer (var->value);
@@ -1442,6 +1448,9 @@ varobj_set_visualizer (struct varobj *va
   state = PyGILState_Ensure ();
   back_to = make_cleanup_py_restore_gil (&state);
 
+  make_cleanup_python_env (var->root->exp->gdbarch,
+			   var->root->exp->language_defn);
+
   mainmod = PyImport_AddModule ("__main__");
   globals = PyModule_GetDict (mainmod);
   Py_INCREF (globals);
@@ -2240,6 +2249,10 @@ value_get_print_value (struct value *val
 #if HAVE_PYTHON
   {
     PyGILState_STATE state = PyGILState_Ensure ();
+    struct cleanup *back_to = make_cleanup_py_restore_gil (&state);
+
+    make_cleanup_python_env (current_gdbarch, current_language);
+
     if (value_formatter && PyObject_HasAttr (value_formatter,
 					     gdbpy_to_string_cst))
       {
@@ -2259,13 +2272,13 @@ value_get_print_value (struct value *val
 						&replacement);
 	if (thevalue && !string_print)
 	  {
-	    PyGILState_Release (state);
+	    do_cleanups (back_to);
 	    return thevalue;
 	  }
 	if (replacement)
 	  value = replacement;
       }
-    PyGILState_Release (state);
+    do_cleanups (back_to);
   }
 #endif
 
-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [02/15] Python interpreter callback functions
  2009-06-09 15:15 [02/15] Python interpreter callback functions Ulrich Weigand
@ 2009-06-09 17:59 ` Tom Tromey
  2009-06-10 15:49   ` Ulrich Weigand
  0 siblings, 1 reply; 6+ messages in thread
From: Tom Tromey @ 2009-06-09 17:59 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: gdb-patches

>>>>> "Ulrich" == Ulrich Weigand <uweigand@de.ibm.com> writes:

Ulrich> If there's a more elegant way of passing this sort of
Ulrich> environmental information through the Python interpreter, I'd
Ulrich> appreciate any hints from the Python experts ;-)

I think this is ok as a default, but ideally the various Python
methods would take an optional architecture argument.  That would mean
having some Python representation of the architecture.

I think any place that acquires the GIL should probably also set the
architecture.  I noticed that gdbpy_new_objfile was not touched in
your patch; there may be other places as well.  Perhaps all this work
could be done by a single convenience function, to make it harder to
forget in the future.

If we had some notion of the "host architecture", then stuff like
builtin_type_pyint could just use that instead.  Those defines really
represent types on the host.

Tom


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [02/15] Python interpreter callback functions
  2009-06-09 17:59 ` Tom Tromey
@ 2009-06-10 15:49   ` Ulrich Weigand
  2009-06-22 20:59     ` Ulrich Weigand
  0 siblings, 1 reply; 6+ messages in thread
From: Ulrich Weigand @ 2009-06-10 15:49 UTC (permalink / raw)
  To: tromey; +Cc: gdb-patches

Tom Tromey wrote:

> I think this is ok as a default, but ideally the various Python
> methods would take an optional architecture argument.  That would mean
> having some Python representation of the architecture.

Right. 

> I think any place that acquires the GIL should probably also set the
> architecture.  I noticed that gdbpy_new_objfile was not touched in
> your patch; there may be other places as well.  Perhaps all this work
> could be done by a single convenience function, to make it harder to
> forget in the future.

Right, I overlooked gdbpy_new_objfile.  I'll fix that.  I can also
merge acquiring/releasing the GIL into make_cleanup_python_env ..

> If we had some notion of the "host architecture", then stuff like
> builtin_type_pyint could just use that instead.  Those defines really
> represent types on the host.

Note that even with my patch set applied, there are currently still 
some limitations on mixing and matching architectures.  For example,
you still cannot pass a value of arch A as argument to an inferior
function call of arch B.  These restrictions could presumably be
lifted over time, but for now, you'd have to deal with them if Python
values were of a different arch from the target ...

Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [02/15] Python interpreter callback functions
  2009-06-10 15:49   ` Ulrich Weigand
@ 2009-06-22 20:59     ` Ulrich Weigand
  2009-06-23 20:45       ` Tom Tromey
  0 siblings, 1 reply; 6+ messages in thread
From: Ulrich Weigand @ 2009-06-22 20:59 UTC (permalink / raw)
  To: tromey; +Cc: gdb-patches


> > I think any place that acquires the GIL should probably also set the
> > architecture.  I noticed that gdbpy_new_objfile was not touched in
> > your patch; there may be other places as well.  Perhaps all this work
> > could be done by a single convenience function, to make it harder to
> > forget in the future.
> 
> Right, I overlooked gdbpy_new_objfile.  I'll fix that.  I can also
> merge acquiring/releasing the GIL into make_cleanup_python_env ..

Does the following version look OK to you?

Tested on amd64-linux.

Bye,
Ulrich

ChangeLog:

	* python/python-internal.h (struct language_defn): Declare.
	(python_gdbarch, python_language): Likewise.
	(ensure_python_env): Add prototype.
	(make_cleanup_py_restore_gil): Remove prototype.

	* python/python.c: Include "arch-utils.h", "value.h" and "language.h".
	(python_gdbarch, python_language): New global variables.
	(struct python_env): New data type.
	(ensure_python_env, restore_python_env): New functions.
	(eval_python_from_control_command): Call ensure_python_env to
	install current architecture and language.
	(python_command, gdbpy_new_objfile): Likewise.
	* python/python-command.c: Include "arch-utils.h" and "language.h".
	(cmdpy_destroyer, cmdpy_function, cmdpy_completer): Call
	ensure_python_env.
	* python/python-type.c (clean_up_objfile_types): Likewise.
	* python/python-objfile.c: Include "language.h".
	(clean_up_objfile): Call ensure_python_env.
	* python/python-prettyprint.c (apply_val_pretty_printer): Likewise.
	(apply_varobj_pretty_printer): Do not call PyGILState_Ensure.
	* varobj.c (varobj_ensure_python_env): New helper function.
	* (varobj_get_display_hint, update_dynamic_varobj_children,
	install_default_visualizer, varobj_set_visualizer, free_variable,
	value_get_print_value): Call it.
	(value_get_print_value): Add varobj argument instead of pretty
	printer argument.  Update all callers.

	* python/python-utils.c (py_gil_restore, make_cleanup_py_restore_gil):
	Remove.

	* value.h (internal_function_fn): Add GDBARCH and LANGUAGE argument.
	(call_internal_function): Likewise.
	* value.c (call_internal_function): Likewise.  Pass to handler.
	* eval.c (evaluate_subexp_standard): Update call.
	* python/python-function.c: Include "language.h".
	(fnpy_call): Add GDBARCH and LANGAUAGE arguments and call
	make_cleanup_python_env.

	* python/python-value.c (builtin_type_pyint, builtin_type_pyfloat,
	builtin_type_pylong, builtin_type_pybool, builtin_type_pychar,
	valpy_str): Use python_gdbarch and python_language instead of
	current_gdbarch and current_language.
	* python/python-type.c (typy_lookup_typename): Likewise.


Index: gdb-head/gdb/python/python.c
===================================================================
--- gdb-head.orig/gdb/python/python.c
+++ gdb-head/gdb/python/python.c
@@ -18,12 +18,15 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
+#include "arch-utils.h"
 #include "command.h"
 #include "ui-out.h"
 #include "cli/cli-script.h"
 #include "gdbcmd.h"
 #include "objfiles.h"
 #include "observer.h"
+#include "value.h"
+#include "language.h"
 
 #include <ctype.h>
 
@@ -58,6 +61,52 @@ PyObject *gdbpy_children_cst;
 PyObject *gdbpy_display_hint_cst;
 PyObject *gdbpy_doc_cst;
 
+
+/* Architecture and language to be used in callbacks from
+   the Python interpreter.  */
+struct gdbarch *python_gdbarch;
+const struct language_defn *python_language;
+
+/* Restore global language and architecture and Python GIL state
+   when leaving the Python interpreter.  */
+
+struct python_env
+{
+  PyGILState_STATE state;
+  struct gdbarch *gdbarch;
+  const struct language_defn *language;
+};
+
+static void
+restore_python_env (void *p)
+{
+  struct python_env *env = (struct python_env *)p;
+  PyGILState_Release (env->state);
+  python_gdbarch = env->gdbarch;
+  python_language = env->language;
+  xfree (env);
+}
+
+/* Called before entering the Python interpreter to install the
+   current language and architecture to be used for Python values.  */
+
+struct cleanup *
+ensure_python_env (struct gdbarch *gdbarch,
+                   const struct language_defn *language)
+{
+  struct python_env *env = xmalloc (sizeof *env);
+
+  env->state = PyGILState_Ensure ();
+  env->gdbarch = python_gdbarch;
+  env->language = python_language;
+
+  python_gdbarch = gdbarch;
+  python_language = language;
+
+  return make_cleanup (restore_python_env, env);
+}
+
+
 /* Given a command_line, return a command string suitable for passing
    to Python.  Lines in the string are separated by newlines.  The
    return value is allocated using xmalloc and the caller is
@@ -96,13 +145,11 @@ eval_python_from_control_command (struct
   int ret;
   char *script;
   struct cleanup *cleanup;
-  PyGILState_STATE state;
 
   if (cmd->body_count != 1)
     error (_("Invalid \"python\" block structure."));
 
-  state = PyGILState_Ensure ();
-  cleanup = make_cleanup_py_restore_gil (&state);
+  cleanup = ensure_python_env (get_current_arch (), current_language);
 
   script = compute_python_string (cmd->body_list[0]);
   ret = PyRun_SimpleString (script);
@@ -122,10 +169,7 @@ static void
 python_command (char *arg, int from_tty)
 {
   struct cleanup *cleanup;
-  PyGILState_STATE state;
-
-  state = PyGILState_Ensure ();
-  cleanup = make_cleanup_py_restore_gil (&state);
+  cleanup = ensure_python_env (get_current_arch (), current_language);
 
   while (arg && *arg && isspace (*arg))
     ++arg;
@@ -330,13 +374,12 @@ gdbpy_new_objfile (struct objfile *objfi
   char *filename, *debugfile;
   int len;
   FILE *input;
-  PyGILState_STATE state;
   struct cleanup *cleanups;
 
   if (!gdbpy_auto_load || !objfile || !objfile->name)
     return;
 
-  state = PyGILState_Ensure ();
+  cleanups = ensure_python_env (get_objfile_arch (objfile), current_language);
 
   gdbpy_current_objfile = objfile;
 
@@ -349,7 +392,7 @@ gdbpy_new_objfile (struct objfile *objfi
   input = fopen (filename, "r");
   debugfile = filename;
 
-  cleanups = make_cleanup (xfree, filename);
+  make_cleanup (xfree, filename);
   make_cleanup (xfree, realname);
 
   if (!input && debug_file_directory)
@@ -391,8 +434,6 @@ gdbpy_new_objfile (struct objfile *objfi
 
   do_cleanups (cleanups);
   gdbpy_current_objfile = NULL;
-
-  PyGILState_Release (state);
 }
 
 /* Return the current Objfile, or None if there isn't one.  */
Index: gdb-head/gdb/python/python-internal.h
===================================================================
--- gdb-head.orig/gdb/python/python-internal.h
+++ gdb-head/gdb/python/python-internal.h
@@ -62,6 +62,7 @@ typedef int Py_ssize_t;
 #endif
 
 struct value;
+struct language_defn;
 
 extern PyObject *gdb_module;
 extern PyTypeObject value_object_type;
@@ -89,7 +90,12 @@ void gdbpy_initialize_functions (void);
 void gdbpy_initialize_objfile (void);
 
 struct cleanup *make_cleanup_py_decref (PyObject *py);
-struct cleanup *make_cleanup_py_restore_gil (PyGILState_STATE *state);
+
+struct cleanup *ensure_python_env (struct gdbarch *gdbarch,
+				   const struct language_defn *language);
+
+extern struct gdbarch *python_gdbarch;
+extern const struct language_defn *python_language;
 
 /* Use this after a TRY_EXCEPT to throw the appropriate Python
    exception.  */
Index: gdb-head/gdb/python/python-value.c
===================================================================
--- gdb-head.orig/gdb/python/python-value.c
+++ gdb-head/gdb/python/python-value.c
@@ -44,19 +44,19 @@ struct value *values_in_python = NULL;
    GDB (which uses target arithmetic).  */
 
 /* Python's integer type corresponds to C's long type.  */
-#define builtin_type_pyint builtin_type (current_gdbarch)->builtin_long
+#define builtin_type_pyint builtin_type (python_gdbarch)->builtin_long
 
 /* Python's float type corresponds to C's double type.  */
-#define builtin_type_pyfloat builtin_type (current_gdbarch)->builtin_double
+#define builtin_type_pyfloat builtin_type (python_gdbarch)->builtin_double
 
 /* Python's long type corresponds to C's long long type.  */
-#define builtin_type_pylong builtin_type (current_gdbarch)->builtin_long_long
+#define builtin_type_pylong builtin_type (python_gdbarch)->builtin_long_long
 
 #define builtin_type_pybool \
-  language_bool_type (current_language, current_gdbarch)
+  language_bool_type (python_language, python_gdbarch)
 
 #define builtin_type_pychar \
-  language_string_char_type (current_language, current_gdbarch)
+  language_string_char_type (python_language, python_gdbarch)
 
 typedef struct {
   PyObject_HEAD
@@ -333,7 +333,7 @@ valpy_str (PyObject *self)
   TRY_CATCH (except, RETURN_MASK_ALL)
     {
       common_val_print (((value_object *) self)->value, stb, 0,
-			&opts, current_language);
+			&opts, python_language);
       s = ui_file_xstrdup (stb, &dummy);
     }
   GDB_PY_HANDLE_EXCEPTION (except);
Index: gdb-head/gdb/value.c
===================================================================
--- gdb-head.orig/gdb/value.c
+++ gdb-head/gdb/value.c
@@ -1300,7 +1300,9 @@ value_internal_function_name (struct val
 }
 
 struct value *
-call_internal_function (struct value *func, int argc, struct value **argv)
+call_internal_function (struct gdbarch *gdbarch,
+			const struct language_defn *language,
+			struct value *func, int argc, struct value **argv)
 {
   struct internal_function *ifn;
   int result;
@@ -1309,7 +1311,7 @@ call_internal_function (struct value *fu
   result = get_internalvar_function (VALUE_INTERNALVAR (func), &ifn);
   gdb_assert (result);
 
-  return (*ifn->handler) (ifn->cookie, argc, argv);
+  return (*ifn->handler) (gdbarch, language, ifn->cookie, argc, argv);
 }
 
 /* The 'function' command.  This does nothing -- it is just a
Index: gdb-head/gdb/python/python-cmd.c
===================================================================
--- gdb-head.orig/gdb/python/python-cmd.c
+++ gdb-head/gdb/python/python-cmd.c
@@ -19,6 +19,7 @@
 
 
 #include "defs.h"
+#include "arch-utils.h"
 #include "value.h"
 #include "exceptions.h"
 #include "python-internal.h"
@@ -26,6 +27,7 @@
 #include "gdbcmd.h"
 #include "cli/cli-decode.h"
 #include "completer.h"
+#include "language.h"
 
 /* Struct representing built-in completion types.  */
 struct cmdpy_completer
@@ -90,9 +92,9 @@ static void
 cmdpy_destroyer (struct cmd_list_element *self, void *context)
 {
   cmdpy_object *cmd;
-  PyGILState_STATE state;
+  struct cleanup *cleanup;
 
-  state = PyGILState_Ensure ();
+  cleanup = ensure_python_env (get_current_arch (), current_language);
 
   /* Release our hold on the command object.  */
   cmd = (cmdpy_object *) context;
@@ -105,7 +107,7 @@ cmdpy_destroyer (struct cmd_list_element
   xfree (self->doc);
   xfree (self->prefixname);
 
-  PyGILState_Release (state);
+  do_cleanups (cleanup);
 }
 
 /* Called by gdb to invoke the command.  */
@@ -115,10 +117,8 @@ cmdpy_function (struct cmd_list_element 
   cmdpy_object *obj = (cmdpy_object *) get_cmd_context (command);
   PyObject *argobj, *ttyobj, *result;
   struct cleanup *cleanup;
-  PyGILState_STATE state;
 
-  state = PyGILState_Ensure ();
-  cleanup = make_cleanup_py_restore_gil (&state);
+  cleanup = ensure_python_env (get_current_arch (), current_language);
 
   if (! obj)
     error (_("Invalid invocation of Python command object."));
@@ -182,10 +182,8 @@ cmdpy_completer (struct cmd_list_element
   PyObject *textobj, *wordobj, *resultobj = NULL;
   char **result = NULL;
   struct cleanup *cleanup;
-  PyGILState_STATE state;
 
-  state = PyGILState_Ensure ();
-  cleanup = make_cleanup_py_restore_gil (&state);
+  cleanup = ensure_python_env (get_current_arch (), current_language);
 
   if (! obj)
     error (_("Invalid invocation of Python command object."));
Index: gdb-head/gdb/python/python-function.c
===================================================================
--- gdb-head.orig/gdb/python/python-function.c
+++ gdb-head/gdb/python/python-function.c
@@ -27,6 +27,7 @@
 #include "cli/cli-decode.h"
 #include "completer.h"
 #include "expression.h"
+#include "language.h"
 
 static PyTypeObject fnpy_object_type;
 
@@ -53,16 +54,15 @@ convert_values_to_python (int argc, stru
 /* Call a Python function object's invoke method.  */
 
 static struct value *
-fnpy_call (void *cookie, int argc, struct value **argv)
+fnpy_call (struct gdbarch *gdbarch, const struct language_defn *language,
+	   void *cookie, int argc, struct value **argv)
 {
   int i;
   struct value *value = NULL;
   PyObject *result, *callable, *args;
   struct cleanup *cleanup;
-  PyGILState_STATE state;
 
-  state = PyGILState_Ensure ();
-  cleanup = make_cleanup_py_restore_gil (&state);
+  cleanup = ensure_python_env (gdbarch, language);
 
   args = convert_values_to_python (argc, argv);
 
Index: gdb-head/gdb/value.h
===================================================================
--- gdb-head.orig/gdb/value.h
+++ gdb-head/gdb/value.h
@@ -667,7 +667,9 @@ extern struct value *value_subscripted_r
 
 /* User function handler.  */
 
-typedef struct value *(*internal_function_fn) (void *cookie,
+typedef struct value *(*internal_function_fn) (struct gdbarch *gdbarch,
+					       const struct language_defn *language,
+					       void *cookie,
 					       int argc,
 					       struct value **argv);
 
@@ -675,7 +677,9 @@ void add_internal_function (const char *
 			    internal_function_fn handler,
 			    void *cookie);
 
-struct value *call_internal_function (struct value *function,
+struct value *call_internal_function (struct gdbarch *gdbarch,
+				      const struct language_defn *language,
+				      struct value *function,
 				      int argc, struct value **argv);
 
 char *value_internal_function_name (struct value *);
Index: gdb-head/gdb/eval.c
===================================================================
--- gdb-head.orig/gdb/eval.c
+++ gdb-head/gdb/eval.c
@@ -1524,7 +1524,8 @@ evaluate_subexp_standard (struct type *e
 	    error (_("Expression of type other than \"Function returning ...\" used as function"));
 	}
       if (TYPE_CODE (value_type (argvec[0])) == TYPE_CODE_INTERNAL_FUNCTION)
-	return call_internal_function (argvec[0], nargs, argvec + 1);
+	return call_internal_function (exp->gdbarch, exp->language_defn,
+				       argvec[0], nargs, argvec + 1);
 
       return call_function_by_hand (argvec[0], nargs, argvec + 1);
       /* pai: FIXME save value from call_function_by_hand, then adjust pc by adjust_fn_pc if +ve  */
Index: gdb-head/gdb/python/python-type.c
===================================================================
--- gdb-head.orig/gdb/python/python-type.c
+++ gdb-head/gdb/python/python-type.c
@@ -374,7 +374,7 @@ typy_lookup_typename (char *type_name)
       else if (!strncmp (type_name, "enum ", 5))
 	type = lookup_enum (type_name + 5, NULL);
       else
-	type = lookup_typename (current_language, current_gdbarch,
+	type = lookup_typename (python_language, python_gdbarch,
 				type_name, NULL, 0);
     }
   if (except.reason < 0)
@@ -532,12 +532,10 @@ clean_up_objfile_types (struct objfile *
   type_object *obj = datum;
   htab_t copied_types;
   struct cleanup *cleanup;
-  PyGILState_STATE state;
 
   /* This prevents another thread from freeing the objects we're
      operating on.  */
-  state = PyGILState_Ensure ();
-  cleanup = make_cleanup_py_restore_gil (&state);
+  cleanup = ensure_python_env (get_objfile_arch (objfile), current_language);
 
   copied_types = create_copied_types_hash (objfile);
 
Index: gdb-head/gdb/python/python-prettyprint.c
===================================================================
--- gdb-head.orig/gdb/python/python-prettyprint.c
+++ gdb-head/gdb/python/python-prettyprint.c
@@ -474,10 +474,8 @@ apply_val_pretty_printer (struct type *t
   char *hint = NULL;
   struct cleanup *cleanups;
   int result = 0;
-  PyGILState_STATE state;
 
-  state = PyGILState_Ensure ();
-  cleanups = make_cleanup_py_restore_gil (&state);
+  cleanups = ensure_python_env (gdbarch, language);
 
   /* Instantiate the printer.  */
   if (valaddr)
@@ -526,13 +524,11 @@ apply_varobj_pretty_printer (PyObject *p
 			     struct value **replacement)
 {
   char *result;
-  PyGILState_STATE state = PyGILState_Ensure ();
 
   *replacement = NULL;
   result = pretty_print_one_value (printer_obj, replacement);
   if (result == NULL);
     gdbpy_print_stack ();
-  PyGILState_Release (state);
 
   return result;
 }
Index: gdb-head/gdb/varobj.c
===================================================================
--- gdb-head.orig/gdb/varobj.c
+++ gdb-head/gdb/varobj.c
@@ -257,7 +257,7 @@ static char *my_value_of_variable (struc
 
 static char *value_get_print_value (struct value *value,
 				    enum varobj_display_formats format,
-				    PyObject *value_formatter);
+				    struct varobj *var);
 
 static int varobj_value_is_changeable_p (struct varobj *var);
 
@@ -445,6 +445,17 @@ is_root_p (struct varobj *var)
   return (var->root->rootvar == var);
 }
 
+#ifdef HAVE_PYTHON
+/* Helper function to install a Python environment suitable for
+   use during operations on VAR.  */
+struct cleanup *
+varobj_ensure_python_env (struct varobj *var)
+{
+  return ensure_python_env (var->root->exp->gdbarch,
+			    var->root->exp->language_defn);
+}
+#endif
+
 /* Creates a varobj (not its children) */
 
 /* Return the full FRAME which corresponds to the given CORE_ADDR
@@ -764,8 +775,7 @@ varobj_set_display_format (struct varobj
       && var->value && !value_lazy (var->value))
     {
       xfree (var->print_value);
-      var->print_value = value_get_print_value (var->value, var->format,
-						var->pretty_printer);
+      var->print_value = value_get_print_value (var->value, var->format, var);
     }
 
   return var->format;
@@ -783,10 +793,12 @@ varobj_get_display_hint (struct varobj *
   char *result = NULL;
 
 #if HAVE_PYTHON
-  PyGILState_STATE state = PyGILState_Ensure ();
+  struct cleanup *back_to = varobj_ensure_python_env (var);
+
   if (var->pretty_printer)
     result = gdbpy_get_display_hint (var->pretty_printer);
-  PyGILState_Release (state);
+
+  do_cleanups (back_to);
 #endif
 
   return result;
@@ -841,10 +853,8 @@ update_dynamic_varobj_children (struct v
   int i;
   int children_changed = 0;
   PyObject *printer = var->pretty_printer;
-  PyGILState_STATE state;
 
-  state = PyGILState_Ensure ();
-  back_to = make_cleanup_py_restore_gil (&state);
+  back_to = varobj_ensure_python_env (var);
 
   *cchanged = 0;
   if (!PyObject_HasAttr (printer, gdbpy_children_cst))
@@ -1297,8 +1307,7 @@ install_new_value (struct varobj *var, s
      lazy -- if it is, the code above has decided that the value
      should not be fetched.  */
   if (value && !value_lazy (value))
-    print_value = value_get_print_value (value, var->format, 
-					 var->pretty_printer);
+    print_value = value_get_print_value (value, var->format, var);
 
   /* If the type is changeable, compare the old and the new values.
      If this is the initial assignment, we don't have any old value
@@ -1401,11 +1410,9 @@ install_default_visualizer (struct varob
 {
 #if HAVE_PYTHON
   struct cleanup *cleanup;
-  PyGILState_STATE state;
   PyObject *pretty_printer = NULL;
 
-  state = PyGILState_Ensure ();
-  cleanup = make_cleanup_py_restore_gil (&state);
+  cleanup = varobj_ensure_python_env (var);
 
   if (var->value)
     {
@@ -1436,11 +1443,8 @@ varobj_set_visualizer (struct varobj *va
 #if HAVE_PYTHON
   PyObject *mainmod, *globals, *pretty_printer, *constructor;
   struct cleanup *back_to, *value;
-  PyGILState_STATE state;
-
 
-  state = PyGILState_Ensure ();
-  back_to = make_cleanup_py_restore_gil (&state);
+  back_to = varobj_ensure_python_env (var);
 
   mainmod = PyImport_AddModule ("__main__");
   globals = PyModule_GetDict (mainmod);
@@ -1936,6 +1940,15 @@ new_root_variable (void)
 static void
 free_variable (struct varobj *var)
 {
+#if HAVE_PYTHON
+  if (var->pretty_printer)
+    {
+      struct cleanup *cleanup = varobj_ensure_python_env (var);
+      Py_DECREF (var->pretty_printer);
+      do_cleanups (cleanup);
+    }
+#endif
+
   value_free (var->value);
 
   /* Free the expression if this is a root variable. */
@@ -1945,14 +1958,6 @@ free_variable (struct varobj *var)
       xfree (var->root);
     }
 
-#if HAVE_PYTHON
-  {
-    PyGILState_STATE state = PyGILState_Ensure ();
-    Py_XDECREF (var->pretty_printer);
-    PyGILState_Release (state);
-  }
-#endif
-
   xfree (var->name);
   xfree (var->obj_name);
   xfree (var->print_value);
@@ -2227,7 +2232,7 @@ my_value_of_variable (struct varobj *var
 
 static char *
 value_get_print_value (struct value *value, enum varobj_display_formats format,
-		       PyObject *value_formatter)
+		       struct varobj *var)
 {
   long dummy;
   struct ui_file *stb;
@@ -2240,7 +2245,9 @@ value_get_print_value (struct value *val
 
 #if HAVE_PYTHON
   {
-    PyGILState_STATE state = PyGILState_Ensure ();
+    struct cleanup *back_to = varobj_ensure_python_env (var);
+    PyObject *value_formatter = var->pretty_printer;
+
     if (value_formatter && PyObject_HasAttr (value_formatter,
 					     gdbpy_to_string_cst))
       {
@@ -2260,13 +2267,13 @@ value_get_print_value (struct value *val
 						&replacement);
 	if (thevalue && !string_print)
 	  {
-	    PyGILState_Release (state);
+	    do_cleanups (back_to);
 	    return thevalue;
 	  }
 	if (replacement)
 	  value = replacement;
       }
-    PyGILState_Release (state);
+    do_cleanups (back_to);
   }
 #endif
 
@@ -2789,8 +2796,7 @@ c_value_of_variable (struct varobj *var,
 	    if (format == var->format)
 	      return xstrdup (var->print_value);
 	    else
-	      return value_get_print_value (var->value, format, 
-					    var->pretty_printer);
+	      return value_get_print_value (var->value, format, var);
 	  }
       }
     }
Index: gdb-head/gdb/python/python-objfile.c
===================================================================
--- gdb-head.orig/gdb/python/python-objfile.c
+++ gdb-head/gdb/python/python-objfile.c
@@ -21,6 +21,7 @@
 #include "python-internal.h"
 #include "charset.h"
 #include "objfiles.h"
+#include "language.h"
 
 typedef struct
 {
@@ -119,13 +120,13 @@ objfpy_set_printers (PyObject *o, PyObje
 static void
 clean_up_objfile (struct objfile *objfile, void *datum)
 {
-  PyGILState_STATE state;
+  struct cleanup *cleanup;
   objfile_object *object = datum;
 
-  state = PyGILState_Ensure ();
+  cleanup = ensure_python_env (get_objfile_arch (objfile), current_language);
   object->objfile = NULL;
   Py_DECREF ((PyObject *) object);
-  PyGILState_Release (state);
+  do_cleanups (cleanup);
 }
 
 /* Return a borrowed reference to the Python object of type Objfile
Index: gdb-head/gdb/python/python-utils.c
===================================================================
--- gdb-head.orig/gdb/python/python-utils.c
+++ gdb-head/gdb/python/python-utils.c
@@ -46,23 +46,6 @@ make_cleanup_py_decref (PyObject *py)
   return make_cleanup (py_decref, (void *) py);
 }
 
-/* A cleanup function to restore the thread state.  */
-
-static void
-py_gil_restore (void *p)
-{
-  PyGILState_STATE *state = p;
-  PyGILState_Release (*state);
-}
-
-/* Return a new cleanup which will restore the Python GIL state.  */
-
-struct cleanup *
-make_cleanup_py_restore_gil (PyGILState_STATE *state)
-{
-  return make_cleanup (py_gil_restore, state);
-}
-
 /* Converts a Python 8-bit string to a unicode string object.  Assumes the
    8-bit string is in the host charset.  If an error occurs during conversion,
    returns NULL with a python exception set.

-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [02/15] Python interpreter callback functions
  2009-06-22 20:59     ` Ulrich Weigand
@ 2009-06-23 20:45       ` Tom Tromey
  2009-07-02 17:06         ` Ulrich Weigand
  0 siblings, 1 reply; 6+ messages in thread
From: Tom Tromey @ 2009-06-23 20:45 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: gdb-patches

>>>>> "Ulrich" == Ulrich Weigand <uweigand@de.ibm.com> writes:

Ulrich> Does the following version look OK to you?

Yes, thanks.

Tom


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [02/15] Python interpreter callback functions
  2009-06-23 20:45       ` Tom Tromey
@ 2009-07-02 17:06         ` Ulrich Weigand
  0 siblings, 0 replies; 6+ messages in thread
From: Ulrich Weigand @ 2009-07-02 17:06 UTC (permalink / raw)
  To: tromey; +Cc: gdb-patches

Tom Tromey wrote:
> >>>>> "Ulrich" == Ulrich Weigand <uweigand@de.ibm.com> writes:
> 
> Ulrich> Does the following version look OK to you?
> 
> Yes, thanks.

I've checked this in now.

Thanks,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2009-07-02 17:06 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-06-09 15:15 [02/15] Python interpreter callback functions Ulrich Weigand
2009-06-09 17:59 ` Tom Tromey
2009-06-10 15:49   ` Ulrich Weigand
2009-06-22 20:59     ` Ulrich Weigand
2009-06-23 20:45       ` Tom Tromey
2009-07-02 17:06         ` Ulrich Weigand

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox