[RFA,3/5] Introduce gdbpy_subclass and use it to simplify some logic

Message ID 20170115134253.24018-4-tom@tromey.com
State New, archived
Headers

Commit Message

Tom Tromey Jan. 15, 2017, 1:42 p.m. UTC
  This introduces a new typed variant of gdbpy_ref, called
gdbpy_subclass.  This is then used to simplify logic in various parts
of the Python layer; for example removing repeated error code or
removing gotos.

I wouldn't mind a better than than "gdb_subclass".  One idea was to
use gdb_ref with a default template parameter, and then change the
existing uses of "gdb_ref" to "gdb_ref<>".

2017-01-15  Tom Tromey  <tom@tromey.com>

	* python/py-cmd.c (cmdpy_destroyer): Use gdbpy_subclass.
	* python/py-breakpoint.c (gdbpy_breakpoint_deleted): Use
	gdbpy_subclass.
	* python/py-type.c (field_new): Use gdbpy_subclass.
	* python/py-symtab.c (symtab_and_line_to_sal_object): Use
	gdbpy_subclass.
	* python/py-progspace.c (pspy_new): Use gdbpy_subclass.
	(py_free_pspace): Likewise.
	(pspace_to_pspace_object): Likewise.
	* python/py-objfile.c (objfpy_new): Use gdbpy_subclass.
	(py_free_objfile): Likewise.
	(objfile_to_objfile_object): Likewise.
	* python/py-inferior.c (delete_thread_object): Use
	gdbpy_subclass.
	(infpy_read_memory): Likewise.
	(py_free_inferior): Likewise.
	* python/py-evtregistry.c (create_eventregistry_object): Use
	gdbpy_subclass.
	* python/py-event.c (create_event_object): Use gdbpy_subclass.
	* python/py-ref.h (gdbpy_ref_policy): Now a template class.
	(gdbpy_subclass): New typedef.
---
 gdb/ChangeLog               | 24 ++++++++++++++++++++++++
 gdb/python/py-breakpoint.c  |  8 +++-----
 gdb/python/py-cmd.c         |  5 +----
 gdb/python/py-event.c       | 16 +++++-----------
 gdb/python/py-evtregistry.c | 17 +++++++----------
 gdb/python/py-frame.c       |  9 ++++-----
 gdb/python/py-inferior.c    | 26 +++++++++-----------------
 gdb/python/py-objfile.c     | 41 +++++++++++++++++------------------------
 gdb/python/py-progspace.c   | 40 +++++++++++++++++-----------------------
 gdb/python/py-ref.h         | 14 ++++++++++----
 gdb/python/py-symtab.c      | 17 +++++++----------
 gdb/python/py-type.c        | 12 +++++-------
 12 files changed, 109 insertions(+), 120 deletions(-)
  

Comments

Simon Marchi Jan. 24, 2017, 8:21 p.m. UTC | #1
On 2017-01-15 08:42, Tom Tromey wrote:
> This introduces a new typed variant of gdbpy_ref, called
> gdbpy_subclass.  This is then used to simplify logic in various parts
> of the Python layer; for example removing repeated error code or
> removing gotos.
> 
> I wouldn't mind a better than than "gdb_subclass".  One idea was to
> use gdb_ref with a default template parameter, and then change the
> existing uses of "gdb_ref" to "gdb_ref<>".

Do you mean gdbpy_ref and gdbpy_subclass?

I don't really like gdbpy_subclass, I think there should be "ref" in the 
name to be clear.  So it could be gdbpy_subclass_ref.  However, I find 
gdbpy_subclass_ref<gdbpy_breakpoint_object> a bit long.  As you may have 
seen in my version of the patch, I had decided to keep gdbpy_ref for 
PyObjects and introduce typedef for other types (gdbpy_inf_ref).  So I 
could see one called gdbpy_bp_ref.

Otherwise, I like gdbpy_ref<> and gdbpy_ref<gdbpy_breakpoint_object>.

The patch looked good to me otherwise (and confirmed that I still find 
refcounting difficult).
  
Pedro Alves Feb. 9, 2017, 11:44 a.m. UTC | #2
On 01/24/2017 08:21 PM, Simon Marchi wrote:

>> I wouldn't mind a better than than "gdb_subclass".  One idea was to
>> use gdb_ref with a default template parameter, and then change the
>> existing uses of "gdb_ref" to "gdb_ref<>".
> 
> Do you mean gdbpy_ref and gdbpy_subclass?
> 
> I don't really like gdbpy_subclass, I think there should be "ref" in the
> name to be clear.  So it could be gdbpy_subclass_ref.  However, I find
> gdbpy_subclass_ref<gdbpy_breakpoint_object> a bit long.  As you may have
> seen in my version of the patch, I had decided to keep gdbpy_ref for
> PyObjects and introduce typedef for other types (gdbpy_inf_ref).  So I
> could see one called gdbpy_bp_ref.
> 
> Otherwise, I like gdbpy_ref<> and gdbpy_ref<gdbpy_breakpoint_object>.
> 
> The patch looked good to me otherwise (and confirmed that I still find
> refcounting difficult).

I agree.  Simon's gdbpy_ref_base + typedef idea would work for me too.

Thanks,
Pedro Alves
  
Pedro Alves Feb. 9, 2017, 1 p.m. UTC | #3
On 01/15/2017 01:42 PM, Tom Tromey wrote:

> diff --git a/gdb/python/py-ref.h b/gdb/python/py-ref.h
> index b2479bf..3430768 100644
> --- a/gdb/python/py-ref.h
> +++ b/gdb/python/py-ref.h
> @@ -1,6 +1,6 @@
>  /* Python reference-holding class
>  
> -   Copyright (C) 2016 Free Software Foundation, Inc.
> +   Copyright (C) 2016, 2017 Free Software Foundation, Inc.

No sure the end-year script converts this to a range automatically.
Better write 2016-2017 from the get go.


>  /* A gdb::ref_ptr that has been specialized for Python objects.  */
> -typedef gdb::ref_ptr<PyObject, gdbpy_ref_policy> gdbpy_ref;
> +typedef gdb::ref_ptr<PyObject, gdbpy_ref_policy<PyObject> > gdbpy_ref;

No need for the space in "> >" in C++11.

Other than the naming issue, this looks really nice to me.

Thanks,
Pedro Alves
  
Tom Tromey Feb. 9, 2017, 6:51 p.m. UTC | #4
>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

>> I don't really like gdbpy_subclass, I think there should be "ref" in the
>> name to be clear.  So it could be gdbpy_subclass_ref.  However, I find
>> gdbpy_subclass_ref<gdbpy_breakpoint_object> a bit long.  As you may have
>> seen in my version of the patch, I had decided to keep gdbpy_ref for
>> PyObjects and introduce typedef for other types (gdbpy_inf_ref).  So I
>> could see one called gdbpy_bp_ref.
>> 
>> Otherwise, I like gdbpy_ref<> and gdbpy_ref<gdbpy_breakpoint_object>.

Pedro> I agree.  Simon's gdbpy_ref_base + typedef idea would work for me too.

This patch would mean introducing 12 typedefs, most used (so far) in a
single spot.

That doesn't seem so great to me, so I think I will look at the
gdbpy_ref<> rename instead.

Tom
  

Patch

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 08670fb..61e4ca4 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,29 @@ 
 2017-01-15  Tom Tromey  <tom@tromey.com>
 
+	* python/py-cmd.c (cmdpy_destroyer): Use gdbpy_subclass.
+	* python/py-breakpoint.c (gdbpy_breakpoint_deleted): Use
+	gdbpy_subclass.
+	* python/py-type.c (field_new): Use gdbpy_subclass.
+	* python/py-symtab.c (symtab_and_line_to_sal_object): Use
+	gdbpy_subclass.
+	* python/py-progspace.c (pspy_new): Use gdbpy_subclass.
+	(py_free_pspace): Likewise.
+	(pspace_to_pspace_object): Likewise.
+	* python/py-objfile.c (objfpy_new): Use gdbpy_subclass.
+	(py_free_objfile): Likewise.
+	(objfile_to_objfile_object): Likewise.
+	* python/py-inferior.c (delete_thread_object): Use
+	gdbpy_subclass.
+	(infpy_read_memory): Likewise.
+	(py_free_inferior): Likewise.
+	* python/py-evtregistry.c (create_eventregistry_object): Use
+	gdbpy_subclass.
+	* python/py-event.c (create_event_object): Use gdbpy_subclass.
+	* python/py-ref.h (gdbpy_ref_policy): Now a template class.
+	(gdbpy_subclass): New typedef.
+
+2017-01-15  Tom Tromey  <tom@tromey.com>
+
 	* ui-file.h (mem_fileopen): Return ui_file_up.
 	(ui_file_up): New typedef.
 	(ui_file_deleter): New struct.
diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c
index f086725..f95a396 100644
--- a/gdb/python/py-breakpoint.c
+++ b/gdb/python/py-breakpoint.c
@@ -913,25 +913,23 @@  gdbpy_breakpoint_deleted (struct breakpoint *b)
   int num = b->number;
   PyGILState_STATE state;
   struct breakpoint *bp = NULL;
-  gdbpy_breakpoint_object *bp_obj;
 
   state = PyGILState_Ensure ();
   bp = get_breakpoint (num);
   if (bp)
     {
-      bp_obj = bp->py_bp_object;
-      if (bp_obj)
+      gdbpy_subclass<gdbpy_breakpoint_object> bp_obj (bp->py_bp_object);
+      if (bp_obj != NULL)
 	{
 	  if (!evregpy_no_listeners_p (gdb_py_events.breakpoint_deleted))
 	    {
-	      if (evpy_emit_event ((PyObject *) bp_obj,
+	      if (evpy_emit_event ((PyObject *) bp_obj.get (),
 				   gdb_py_events.breakpoint_deleted) < 0)
 		gdbpy_print_stack ();
 	    }
 
 	  bp_obj->bp = NULL;
 	  --bppy_live;
-	  Py_DECREF (bp_obj);
 	}
     }
   PyGILState_Release (state);
diff --git a/gdb/python/py-cmd.c b/gdb/python/py-cmd.c
index 28c391c..b798c8a 100644
--- a/gdb/python/py-cmd.c
+++ b/gdb/python/py-cmd.c
@@ -95,14 +95,11 @@  cmdpy_dont_repeat (PyObject *self, PyObject *args)
 static void
 cmdpy_destroyer (struct cmd_list_element *self, void *context)
 {
-  cmdpy_object *cmd;
-
   gdbpy_enter enter_py (get_current_arch (), current_language);
 
   /* Release our hold on the command object.  */
-  cmd = (cmdpy_object *) context;
+  gdbpy_subclass<cmdpy_object> cmd ((cmdpy_object *) context);
   cmd->command = NULL;
-  Py_DECREF (cmd);
 
   /* We allocated the name, doc string, and perhaps the prefix
      name.  */
diff --git a/gdb/python/py-event.c b/gdb/python/py-event.c
index a50da1f..1369fb4 100644
--- a/gdb/python/py-event.c
+++ b/gdb/python/py-event.c
@@ -30,21 +30,15 @@  evpy_dealloc (PyObject *self)
 PyObject *
 create_event_object (PyTypeObject *py_type)
 {
-  event_object *event_obj;
-
-  event_obj = PyObject_New (event_object, py_type);
-  if (!event_obj)
-    goto fail;
+  gdbpy_subclass<event_object> event_obj (PyObject_New (event_object, py_type));
+  if (event_obj == NULL)
+    return NULL;
 
   event_obj->dict = PyDict_New ();
   if (!event_obj->dict)
-    goto fail;
-
-  return (PyObject*) event_obj;
+    return NULL;
 
- fail:
-  Py_XDECREF (event_obj);
-  return NULL;
+  return (PyObject*) event_obj.release ();
 }
 
 /* Add the attribute ATTR to the event object EVENT.  In
diff --git a/gdb/python/py-evtregistry.c b/gdb/python/py-evtregistry.c
index 81bf927..023a7ce 100644
--- a/gdb/python/py-evtregistry.c
+++ b/gdb/python/py-evtregistry.c
@@ -20,6 +20,7 @@ 
 #include "defs.h"
 #include "command.h"
 #include "py-events.h"
+#include "py-ref.h"
 
 events_object gdb_py_events;
 
@@ -79,22 +80,18 @@  evregpy_disconnect (PyObject *self, PyObject *function)
 eventregistry_object *
 create_eventregistry_object (void)
 {
-  eventregistry_object *eventregistry_obj;
+  gdbpy_subclass<eventregistry_object>
+    eventregistry_obj (PyObject_New (eventregistry_object,
+				     &eventregistry_object_type));
 
-  eventregistry_obj = PyObject_New (eventregistry_object,
-                                    &eventregistry_object_type);
-
-  if (!eventregistry_obj)
+  if (eventregistry_obj == NULL)
     return NULL;
 
   eventregistry_obj->callbacks = PyList_New (0);
   if (!eventregistry_obj->callbacks)
-    {
-      Py_DECREF (eventregistry_obj);
-      return NULL;
-    }
+    return NULL;
 
-  return eventregistry_obj;
+  return eventregistry_obj.release ();
 }
 
 static void
diff --git a/gdb/python/py-frame.c b/gdb/python/py-frame.c
index 3594be2..8b07f72 100644
--- a/gdb/python/py-frame.c
+++ b/gdb/python/py-frame.c
@@ -28,6 +28,7 @@ 
 #include "symfile.h"
 #include "objfiles.h"
 #include "user-regs.h"
+#include "py-ref.h"
 
 typedef struct {
   PyObject_HEAD
@@ -361,9 +362,8 @@  frapy_function (PyObject *self, PyObject *args)
 PyObject *
 frame_info_to_frame_object (struct frame_info *frame)
 {
-  frame_object *frame_obj;
-
-  frame_obj = PyObject_New (frame_object, &frame_object_type);
+  gdbpy_subclass<frame_object> frame_obj
+    (PyObject_New (frame_object, &frame_object_type));
   if (frame_obj == NULL)
     return NULL;
 
@@ -389,13 +389,12 @@  frame_info_to_frame_object (struct frame_info *frame)
     }
   CATCH (except, RETURN_MASK_ALL)
     {
-      Py_DECREF (frame_obj);
       gdbpy_convert_exception (except);
       return NULL;
     }
   END_CATCH
 
-  return (PyObject *) frame_obj;
+  return (PyObject *) frame_obj.release ();
 }
 
 /* Implementation of gdb.Frame.older (self) -> gdb.Frame.
diff --git a/gdb/python/py-inferior.c b/gdb/python/py-inferior.c
index 9e10d62..e2f21d4 100644
--- a/gdb/python/py-inferior.c
+++ b/gdb/python/py-inferior.c
@@ -307,7 +307,6 @@  add_thread_object (struct thread_info *tp)
 static void
 delete_thread_object (struct thread_info *tp, int ignore)
 {
-  inferior_object *inf_obj;
   struct threadlist_entry **entry, *tmp;
 
   if (!gdb_python_initialized)
@@ -315,9 +314,9 @@  delete_thread_object (struct thread_info *tp, int ignore)
 
   gdbpy_enter enter_py (python_gdbarch, python_language);
 
-  inf_obj
-    = (inferior_object *) find_inferior_object (ptid_get_pid (tp->ptid));
-  if (!inf_obj)
+  gdbpy_subclass<inferior_object> inf_obj
+    ((inferior_object *) find_inferior_object (ptid_get_pid (tp->ptid)));
+  if (inf_obj == NULL)
     return;
 
   /* Find thread entry in its inferior's thread_list.  */
@@ -327,10 +326,7 @@  delete_thread_object (struct thread_info *tp, int ignore)
       break;
 
   if (!*entry)
-    {
-      Py_DECREF (inf_obj);
-      return;
-    }
+    return;
 
   tmp = *entry;
   tmp->thread_obj->thread = NULL;
@@ -339,7 +335,6 @@  delete_thread_object (struct thread_info *tp, int ignore)
   inf_obj->nthreads--;
 
   Py_DECREF (tmp->thread_obj);
-  Py_DECREF (inf_obj);
   xfree (tmp);
 }
 
@@ -446,7 +441,6 @@  infpy_read_memory (PyObject *self, PyObject *args, PyObject *kw)
 {
   CORE_ADDR addr, length;
   gdb_byte *buffer = NULL;
-  membuf_object *membuf_obj;
   PyObject *addr_obj, *length_obj, *result;
   static char *keywords[] = { "address", "length", NULL };
 
@@ -471,7 +465,8 @@  infpy_read_memory (PyObject *self, PyObject *args, PyObject *kw)
     }
   END_CATCH
 
-  membuf_obj = PyObject_New (membuf_object, &membuf_object_type);
+  gdbpy_subclass<membuf_object> membuf_obj (PyObject_New (membuf_object,
+							  &membuf_object_type));
   if (membuf_obj == NULL)
     {
       xfree (buffer);
@@ -483,12 +478,11 @@  infpy_read_memory (PyObject *self, PyObject *args, PyObject *kw)
   membuf_obj->length = length;
 
 #ifdef IS_PY3K
-  result = PyMemoryView_FromObject ((PyObject *) membuf_obj);
+  result = PyMemoryView_FromObject ((PyObject *) membuf_obj.get ());
 #else
-  result = PyBuffer_FromReadWriteObject ((PyObject *) membuf_obj, 0,
+  result = PyBuffer_FromReadWriteObject ((PyObject *) membuf_obj.get (), 0,
 					 Py_END_OF_BUFFER);
 #endif
-  Py_DECREF (membuf_obj);
 
   return result;
 }
@@ -776,7 +770,7 @@  infpy_dealloc (PyObject *obj)
 static void
 py_free_inferior (struct inferior *inf, void *datum)
 {
-  inferior_object *inf_obj = (inferior_object *) datum;
+  gdbpy_subclass<inferior_object> inf_obj ((inferior_object *) datum);
   struct threadlist_entry *th_entry, *th_tmp;
 
   if (!gdb_python_initialized)
@@ -797,8 +791,6 @@  py_free_inferior (struct inferior *inf, void *datum)
     }
 
   inf_obj->nthreads = 0;
-
-  Py_DECREF ((PyObject *) inf_obj);
 }
 
 /* Implementation of gdb.selected_inferior() -> gdb.Inferior.
diff --git a/gdb/python/py-objfile.c b/gdb/python/py-objfile.c
index 694fa09..136dfa7 100644
--- a/gdb/python/py-objfile.c
+++ b/gdb/python/py-objfile.c
@@ -24,6 +24,7 @@ 
 #include "language.h"
 #include "build-id.h"
 #include "symtab.h"
+#include "py-ref.h"
 
 typedef struct
 {
@@ -227,18 +228,16 @@  objfpy_initialize (objfile_object *self)
 static PyObject *
 objfpy_new (PyTypeObject *type, PyObject *args, PyObject *keywords)
 {
-  objfile_object *self = (objfile_object *) type->tp_alloc (type, 0);
+  gdbpy_subclass<objfile_object> self
+    ((objfile_object *) type->tp_alloc (type, 0));
 
-  if (self)
+  if (self != NULL)
     {
-      if (!objfpy_initialize (self))
-	{
-	  Py_DECREF (self);
-	  return NULL;
-	}
+      if (!objfpy_initialize (self.get ()))
+	return NULL;
     }
 
-  return (PyObject *) self;
+  return (PyObject *) self.release ();
 }
 
 PyObject *
@@ -612,11 +611,9 @@  gdbpy_lookup_objfile (PyObject *self, PyObject *args, PyObject *kw)
 static void
 py_free_objfile (struct objfile *objfile, void *datum)
 {
-  objfile_object *object = (objfile_object *) datum;
-
   gdbpy_enter enter_py (get_objfile_arch (objfile), current_language);
+  gdbpy_subclass<objfile_object> object ((objfile_object *) datum);
   object->objfile = NULL;
-  Py_DECREF ((PyObject *) object);
 }
 
 /* Return a borrowed reference to the Python object of type Objfile
@@ -627,26 +624,22 @@  py_free_objfile (struct objfile *objfile, void *datum)
 PyObject *
 objfile_to_objfile_object (struct objfile *objfile)
 {
-  objfile_object *object;
-
-  object = (objfile_object *) objfile_data (objfile, objfpy_objfile_data_key);
-  if (!object)
+  gdbpy_subclass<objfile_object> object
+    ((objfile_object *) objfile_data (objfile, objfpy_objfile_data_key));
+  if (object == NULL)
     {
-      object = PyObject_New (objfile_object, &objfile_object_type);
-      if (object)
+      object.reset (PyObject_New (objfile_object, &objfile_object_type));
+      if (object != NULL)
 	{
-	  if (!objfpy_initialize (object))
-	    {
-	      Py_DECREF (object);
-	      return NULL;
-	    }
+	  if (!objfpy_initialize (object.get ()))
+	    return NULL;
 
 	  object->objfile = objfile;
-	  set_objfile_data (objfile, objfpy_objfile_data_key, object);
+	  set_objfile_data (objfile, objfpy_objfile_data_key, object.get ());
 	}
     }
 
-  return (PyObject *) object;
+  return (PyObject *) object.release ();
 }
 
 int
diff --git a/gdb/python/py-progspace.c b/gdb/python/py-progspace.c
index b0d9458..70e052b 100644
--- a/gdb/python/py-progspace.c
+++ b/gdb/python/py-progspace.c
@@ -24,6 +24,7 @@ 
 #include "objfiles.h"
 #include "language.h"
 #include "arch-utils.h"
+#include "py-ref.h"
 
 typedef struct
 {
@@ -128,18 +129,16 @@  pspy_initialize (pspace_object *self)
 static PyObject *
 pspy_new (PyTypeObject *type, PyObject *args, PyObject *keywords)
 {
-  pspace_object *self = (pspace_object *) type->tp_alloc (type, 0);
+  gdbpy_subclass<pspace_object> self
+    ((pspace_object *) type->tp_alloc (type, 0));
 
-  if (self)
+  if (self != NULL)
     {
-      if (!pspy_initialize (self))
-	{
-	  Py_DECREF (self);
-	  return NULL;
-	}
+      if (!pspy_initialize (self.get ()))
+	return NULL;
     }
 
-  return (PyObject *) self;
+  return (PyObject *) self.release ();
 }
 
 PyObject *
@@ -323,7 +322,7 @@  pspy_set_type_printers (PyObject *o, PyObject *value, void *ignore)
 static void
 py_free_pspace (struct program_space *pspace, void *datum)
 {
-  pspace_object *object = (pspace_object *) datum;
+  gdbpy_subclass<pspace_object> object ((pspace_object *) datum);
   /* This is a fiction, but we're in a nasty spot: The pspace is in the
      process of being deleted, we can't rely on anything in it.  Plus
      this is one time when the current program space and current inferior
@@ -337,7 +336,6 @@  py_free_pspace (struct program_space *pspace, void *datum)
 
   gdbpy_enter enter_py (arch, current_language);
   object->pspace = NULL;
-  Py_DECREF ((PyObject *) object);
 }
 
 /* Return a borrowed reference to the Python object of type Pspace
@@ -348,26 +346,22 @@  py_free_pspace (struct program_space *pspace, void *datum)
 PyObject *
 pspace_to_pspace_object (struct program_space *pspace)
 {
-  pspace_object *object;
-
-  object = (pspace_object *) program_space_data (pspace, pspy_pspace_data_key);
-  if (!object)
+  gdbpy_subclass<pspace_object> object
+    ((pspace_object *) program_space_data (pspace, pspy_pspace_data_key));
+  if (object == NULL)
     {
-      object = PyObject_New (pspace_object, &pspace_object_type);
-      if (object)
+      object.reset (PyObject_New (pspace_object, &pspace_object_type));
+      if (object != NULL)
 	{
-	  if (!pspy_initialize (object))
-	    {
-	      Py_DECREF (object);
-	      return NULL;
-	    }
+	  if (!pspy_initialize (object.get ()))
+	    return NULL;
 
 	  object->pspace = pspace;
-	  set_program_space_data (pspace, pspy_pspace_data_key, object);
+	  set_program_space_data (pspace, pspy_pspace_data_key, object.get ());
 	}
     }
 
-  return (PyObject *) object;
+  return (PyObject *) object.release ();
 }
 
 int
diff --git a/gdb/python/py-ref.h b/gdb/python/py-ref.h
index b2479bf..3430768 100644
--- a/gdb/python/py-ref.h
+++ b/gdb/python/py-ref.h
@@ -1,6 +1,6 @@ 
 /* Python reference-holding class
 
-   Copyright (C) 2016 Free Software Foundation, Inc.
+   Copyright (C) 2016, 2017 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -23,20 +23,26 @@ 
 #include "common/gdb_ref_ptr.h"
 
 /* A policy class for gdb::ref_ptr for Python reference counting.  */
+template<typename T>
 struct gdbpy_ref_policy
 {
-  static void incref (PyObject *ptr)
+  static void incref (T *ptr)
   {
     Py_INCREF (ptr);
   }
 
-  static void decref (PyObject *ptr)
+  static void decref (T *ptr)
   {
     Py_DECREF (ptr);
   }
 };
 
 /* A gdb::ref_ptr that has been specialized for Python objects.  */
-typedef gdb::ref_ptr<PyObject, gdbpy_ref_policy> gdbpy_ref;
+typedef gdb::ref_ptr<PyObject, gdbpy_ref_policy<PyObject> > gdbpy_ref;
+
+/* A gdb::ref_ptr that has been specialized for "subclasses" of Python
+   objects.  */
+template<typename T> using gdbpy_subclass
+  = gdb::ref_ptr<T, gdbpy_ref_policy<T> >;
 
 #endif /* GDB_PYTHON_REF_H */
diff --git a/gdb/python/py-symtab.c b/gdb/python/py-symtab.c
index 9fdb42f..770c898 100644
--- a/gdb/python/py-symtab.c
+++ b/gdb/python/py-symtab.c
@@ -24,6 +24,7 @@ 
 #include "python-internal.h"
 #include "objfiles.h"
 #include "block.h"
+#include "py-ref.h"
 
 typedef struct stpy_symtab_object {
   PyObject_HEAD
@@ -436,19 +437,15 @@  symtab_to_symtab_object (struct symtab *symtab)
 PyObject *
 symtab_and_line_to_sal_object (struct symtab_and_line sal)
 {
-  sal_object *sal_obj;
-
-  sal_obj = PyObject_New (sal_object, &sal_object_type);
-  if (sal_obj)
+  gdbpy_subclass<sal_object> sal_obj (PyObject_New (sal_object,
+						    &sal_object_type));
+  if (sal_obj != NULL)
     {
-      if (set_sal (sal_obj, sal) < 0)
-	{
-	  Py_DECREF (sal_obj);
-	  return NULL;
-	}
+      if (set_sal (sal_obj.get (), sal) < 0)
+	return NULL;
     }
 
-  return (PyObject *) sal_obj;
+  return (PyObject *) sal_obj.release ();
 }
 
 /* Return struct symtab_and_line reference that is wrapped by this
diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c
index 235e8b5..cc1bbf5 100644
--- a/gdb/python/py-type.c
+++ b/gdb/python/py-type.c
@@ -130,18 +130,16 @@  field_dealloc (PyObject *obj)
 static PyObject *
 field_new (void)
 {
-  field_object *result = PyObject_New (field_object, &field_object_type);
+  gdbpy_subclass<field_object> result (PyObject_New (field_object,
+						     &field_object_type));
 
-  if (result)
+  if (result != NULL)
     {
       result->dict = PyDict_New ();
       if (!result->dict)
-	{
-	  Py_DECREF (result);
-	  result = NULL;
-	}
+	return NULL;
     }
-  return (PyObject *) result;
+  return (PyObject *) result.release ();
 }