This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFA] Python: PR/13327: expose laziness to Python


The attached implements a solution for PR/13327 by introducing the gdb.Value attribute "is_lazy" and method "fetch_lazy()".  It also reverts an earlier change I made that always immediately fetches values for gdb.Value, as discussed in http://sourceware.org/ml/gdb-patches/2011-10/msg00541.html .

The documentation briefly touches on how lazy fetching works in the discussion of the is_lazy attribute, but it doesn't more fully discuss it as a topic of its own.  I could try to do so, in the introductory material for gdb.Value.  Should I do that?

Ok to commit?

	paul

ChangeLog:

2011-10-25  Paul Koning  <paul_koning@dell.com>

	PR python/13327
	
	* python/py-value.c (value_to_value_object): Remove fetching of
	the value if it was lazy.
	(valpy_get_is_lazy): New function.
	(valpy_fetch_lazy): New function.

doc/Changelog:

2011-10-25  Paul Koning  <paul_koning@dell.com>

	PR python/13327
	
	* gdb.texinfo (Values From Inferior): Add is_lazy attribute,
	fetch_lazy method.

testsuite/ChangeLog:

2011-10-25  Paul Koning  <paul_koning@dell.com>

	PR python/13327
	
	* gdb.python/py-value.exp: Add testcases for is_lazy attribute,
	fetch_lazy method.

Index: doc/gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.880
diff -u -r1.880 gdb.texinfo
--- doc/gdb.texinfo	20 Oct 2011 12:31:29 -0000	1.880
+++ doc/gdb.texinfo	25 Oct 2011 17:24:18 -0000
@@ -21681,6 +21681,20 @@
 it will just return the static type of the value as in @kbd{ptype foo}
 (@pxref{Symbols, ptype}).
 @end defvar
+
+@defvar Value.is_lazy
+This read-only boolean attribute is true if the value has not yet
+been fetched from the inferior.  GDB does not fetch values until
+necessary, for efficiency.  For example:
+
+@smallexample
+myval = gdb.parse_and_eval ('somevar')
+@end smallexample
+
+The value of @var{somevar} is not fetched at this time.  It will be 
+fetched when the value is needed, or when the @code{fetch_lazy ()}
+method is invoked.  
+@end defvar
 @end table
 
 The following methods are provided:
@@ -21814,6 +21828,19 @@
 the @var{length} argument is not provided, the string will be fetched
 and encoded until a null of appropriate width is found.
 @end defun
+
+@defun Value.fetch_lazy ()
+If the @code{gdb.Value} object is currently a lazy value 
+(@code{gdb.Value.is_lazy} is @code{True}) then the value is
+fetched from the inferior.  Any errors that occur in the process
+will produce a Python exception.
+
+If the @code{gdb.Value} object is not a lazy value, this method
+has no effect.
+
+This method does not return a value.
+@end defun
+
 @end table
 
 @node Types In Python
Index: python/py-value.c
===================================================================
RCS file: /cvs/src/src/gdb/python/py-value.c,v
retrieving revision 1.28
diff -u -r1.28 py-value.c
--- python/py-value.c	7 Oct 2011 22:02:42 -0000	1.28
+++ python/py-value.c	25 Oct 2011 17:24:18 -0000
@@ -617,6 +617,43 @@
   Py_RETURN_FALSE;
 }
 
+/* Implements gdb.Value.is_lazy.  */
+static PyObject *
+valpy_get_is_lazy (PyObject *self, void *closure)
+{
+  struct value *value = ((value_object *) self)->value;
+  int opt = 0;
+  volatile struct gdb_exception except;
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      opt = value_lazy (value);
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  if (opt)
+    Py_RETURN_TRUE;
+
+  Py_RETURN_FALSE;
+}
+
+/* Implements gdb.Value.fetch_lazy ().  */
+static PyObject *
+valpy_fetch_lazy (PyObject *self, PyObject *args)
+{
+  struct value *value = ((value_object *) self)->value;
+  volatile struct gdb_exception except;
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      if (value_lazy (value))
+	value_fetch_lazy (value);
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  Py_RETURN_NONE;
+}
+
 /* Calculate and return the address of the PyObject as the value of
    the builtin __hash__ call.  */
 static long 
@@ -1081,15 +1118,7 @@
 value_to_value_object (struct value *val)
 {
   value_object *val_obj;
-  volatile struct gdb_exception except;
 
-  TRY_CATCH (except, RETURN_MASK_ALL)
-    {
-      if (value_lazy (val))
-	value_fetch_lazy (val);
-    }
-  GDB_PY_HANDLE_EXCEPTION (except);
-  
   val_obj = PyObject_New (value_object, &value_object_type);
   if (val_obj != NULL)
     {
@@ -1276,6 +1305,10 @@
   { "type", valpy_get_type, NULL, "Type of the value.", NULL },
   { "dynamic_type", valpy_get_dynamic_type, NULL,
     "Dynamic type of the value.", NULL },
+  { "is_lazy", valpy_get_is_lazy, NULL,
+    "Boolean telling whether the value is lazy (not fetched yet\n\
+from the inferior).  A lazy value is fetched when needed, or when\n\
+the \"fetch_lazy()\" method is called.", NULL },
   {NULL}  /* Sentinel */
 };
 
@@ -1298,6 +1331,8 @@
   { "string", (PyCFunction) valpy_string, METH_VARARGS | METH_KEYWORDS,
     "string ([encoding] [, errors] [, length]) -> string\n\
 Return Unicode string representation of the value." },
+  { "fetch_lazy", valpy_fetch_lazy, METH_NOARGS, 
+    "Fetches the value from the inferior, if it was lazy." },
   {NULL}  /* Sentinel */
 };
 
Index: testsuite/gdb.python/py-value.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.python/py-value.exp,v
retrieving revision 1.24
diff -u -r1.24 py-value.exp
--- testsuite/gdb.python/py-value.exp	3 Oct 2011 16:15:26 -0000	1.24
+++ testsuite/gdb.python/py-value.exp	25 Oct 2011 17:24:19 -0000
@@ -236,17 +236,27 @@
     gdb_test "python print gdb.parse_and_eval('*(int*)0')" "gdb.MemoryError: Cannot access memory at address 0x0.*" $test
   }
 
-  # Test Python values are not lazy.
-  set test "memory error occurs even for possibly lazy values"
+  # Test Python lazy value handling
+  set test "memory error and lazy values"
   if {$can_read_0} {
     untested $test
   } else {
-    gdb_test "python inval = gdb.parse_and_eval('*(int*)0')" "gdb.MemoryError: Cannot access memory at address 0x0.*" $test
+    gdb_test "python inval = gdb.parse_and_eval('*(int*)0')"
+    gdb_test "python print inval.is_lazy" "True"
+    gdb_test "python inval2 = inval+1" "gdb.MemoryError: Cannot access memory at address 0x0.*" $test
+    gdb_test "python inval.fetch_lazy ()" "gdb.MemoryError: Cannot access memory at address 0x0.*" $test
   }
   gdb_test "python argc_lazy = gdb.parse_and_eval('argc')"
+  gdb_test "python argc_notlazy = gdb.parse_and_eval('argc')"
+  gdb_test "python argc_notlazy.fetch_lazy()"
+  gdb_test "python print argc_lazy.is_lazy" "True"
+  gdb_test "python print argc_notlazy.is_lazy" "False"
   gdb_test "print argc" " = 1" "sanity check argc"
+  gdb_test "python print argc_lazy.is_lazy" "\r\nTrue"
   gdb_test_no_output "set argc=2"
-  gdb_test "python print argc_lazy" "\r\n1"
+  gdb_test "python print argc_notlazy" "\r\n1"
+  gdb_test "python print argc_lazy" "\r\n2"
+  gdb_test "python print argc_lazy.is_lazy" "False"
 
   # Test string fetches,  both partial and whole.
   gdb_test "print st" "\"divide et impera\""


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]