From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 22197 invoked by alias); 25 Oct 2011 17:38:54 -0000 Received: (qmail 21870 invoked by uid 22791); 25 Oct 2011 17:38:52 -0000 X-SWARE-Spam-Status: No, hits=-2.2 required=5.0 tests=AWL,BAYES_00,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE,RP_MATCHES_RCVD,T_TO_NO_BRKTS_FREEMAIL X-Spam-Check-By: sourceware.org Received: from qmta14.westchester.pa.mail.comcast.net (HELO qmta14.westchester.pa.mail.comcast.net) (76.96.59.212) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 25 Oct 2011 17:38:32 +0000 Received: from omta02.westchester.pa.mail.comcast.net ([76.96.62.19]) by qmta14.westchester.pa.mail.comcast.net with comcast id p5QW1h0040QuhwU5E5eYyx; Tue, 25 Oct 2011 17:38:32 +0000 Received: from [10.127.238.91] ([65.206.2.68]) by omta02.westchester.pa.mail.comcast.net with comcast id p5eN1h00E1U2a2h3N5eQza; Tue, 25 Oct 2011 17:38:30 +0000 From: Paul Koning Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: quoted-printable Subject: [RFA] Python: PR/13327: expose laziness to Python Date: Tue, 25 Oct 2011 17:43:00 -0000 Message-Id: Cc: Tom Tromey To: gdb-patches@sourceware.org Mime-Version: 1.0 (Apple Message framework v1084) Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2011-10/txt/msg00667.txt.bz2 The attached implements a solution for PR/13327 by introducing the gdb.Valu= e attribute "is_lazy" and method "fetch_lazy()". It also reverts an earlie= r change I made that always immediately fetches values for gdb.Value, as di= scussed in http://sourceware.org/ml/gdb-patches/2011-10/msg00541.html . The documentation briefly touches on how lazy fetching works in the discuss= ion of the is_lazy attribute, but it doesn't more fully discuss it as a top= ic 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 PR python/13327 =09 * 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 PR python/13327 =09 * gdb.texinfo (Values From Inferior): Add is_lazy attribute, fetch_lazy method. testsuite/ChangeLog: 2011-10-25 Paul Koning PR python/13327 =09 * gdb.python/py-value.exp: Add testcases for is_lazy attribute, fetch_lazy method. Index: doc/gdb.texinfo =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D 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 =3D gdb.parse_and_eval ('somevar') +@end smallexample + +The value of @var{somevar} is not fetched at this time. It will be=20 +fetched when the value is needed, or when the @code{fetch_lazy ()} +method is invoked.=20=20 +@end defvar @end table =20 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=20 +(@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 =20 @node Types In Python Index: python/py-value.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D 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; } =20 +/* Implements gdb.Value.is_lazy. */ +static PyObject * +valpy_get_is_lazy (PyObject *self, void *closure) +{ + struct value *value =3D ((value_object *) self)->value; + int opt =3D 0; + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + opt =3D 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 =3D ((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=20 @@ -1081,15 +1118,7 @@ value_to_value_object (struct value *val) { value_object *val_obj; - volatile struct gdb_exception except; =20 - TRY_CATCH (except, RETURN_MASK_ALL) - { - if (value_lazy (val)) - value_fetch_lazy (val); - } - GDB_PY_HANDLE_EXCEPTION (except); -=20=20 val_obj =3D PyObject_New (value_object, &value_object_type); if (val_obj !=3D 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 */ }; =20 @@ -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,=20 + "Fetches the value from the inferior, if it was lazy." }, {NULL} /* Sentinel */ }; =20 Index: testsuite/gdb.python/py-value.exp =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D 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.MemoryErro= r: Cannot access memory at address 0x0.*" $test } =20 - # 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 =3D gdb.parse_and_eval('*(int*)0')" "gdb.Memory= Error: Cannot access memory at address 0x0.*" $test + gdb_test "python inval =3D gdb.parse_and_eval('*(int*)0')" + gdb_test "python print inval.is_lazy" "True" + gdb_test "python inval2 =3D inval+1" "gdb.MemoryError: Cannot access m= emory at address 0x0.*" $test + gdb_test "python inval.fetch_lazy ()" "gdb.MemoryError: Cannot access = memory at address 0x0.*" $test } gdb_test "python argc_lazy =3D gdb.parse_and_eval('argc')" + gdb_test "python argc_notlazy =3D 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" " =3D 1" "sanity check argc" + gdb_test "python print argc_lazy.is_lazy" "\r\nTrue" gdb_test_no_output "set argc=3D2" - 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" =20 # Test string fetches, both partial and whole. gdb_test "print st" "\"divide et impera\""