From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 15046 invoked by alias); 9 Nov 2013 19:55:13 -0000 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 Received: (qmail 15020 invoked by uid 89); 9 Nov 2013 19:55:12 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.9 required=5.0 tests=BAYES_00,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM,RDNS_NONE,SPF_PASS,URIBL_BLOCKED autolearn=no version=3.3.2 X-HELO: mail-pd0-f195.google.com Received: from Unknown (HELO mail-pd0-f195.google.com) (209.85.192.195) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Sat, 09 Nov 2013 19:55:10 +0000 Received: by mail-pd0-f195.google.com with SMTP id y13so418816pdi.6 for ; Sat, 09 Nov 2013 11:55:02 -0800 (PST) X-Received: by 10.66.144.102 with SMTP id sl6mr22269934pab.96.1384026902504; Sat, 09 Nov 2013 11:55:02 -0800 (PST) Received: from seba.sebabeach.org.gmail.com (173-13-178-50-sfba.hfc.comcastbusiness.net. [173.13.178.50]) by mx.google.com with ESMTPSA id sg1sm20304099pbb.16.2013.11.09.11.55.00 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 09 Nov 2013 11:55:01 -0800 (PST) From: Doug Evans To: Tom Tromey Cc: Stan Shebs , gdb-patches@sourceware.org Subject: Re: [PATCH] Move "types deeply equal" code from py-type.c to gdbtypes.c References: <527AB482.80600@earthlink.net> <87ppqd1a0t.fsf@fleche.redhat.com> <87r4asz3be.fsf@fleche.redhat.com> Date: Sat, 09 Nov 2013 20:33:00 -0000 In-Reply-To: (Doug Evans's message of "Sat, 9 Nov 2013 11:50:47 -0800") Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-IsSubscribed: yes X-SW-Source: 2013-11/txt/msg00261.txt.bz2 Doug Evans writes: > WTF? Where'd the patch go? > Let's try this again. > > On Sat, Nov 9, 2013 at 11:47 AM, Doug Evans wrote: >> On Thu, Nov 7, 2013 at 8:40 AM, Doug Evans wrote: >>> On Thu, Nov 7, 2013 at 6:36 AM, Tom Tromey wrote: >>>>>>>>> "Doug" == Doug Evans writes: >>>> >>>> Doug> Tom Tromey writes: >>>> Stan> +/* A helper function for tyscm_richcompare that checks two types for >>>> Stan> + "deep" equality. Returns non-zero if the types are considered the >>>> Stan> + same, zero otherwise. */ >>>>>> >>>> Stan> "tyscm_richcompare"? Should that be typy_... ? >>>>>> >>>>>> It would be helpful if Doug could list all the change he made when >>>>>> moving the code. >>>> >>>> Doug> I don't understand. >>>> Doug> Which changes? While useful beyond its present state, this is in >>>> Doug> essence just a cleanup. >>>> >>>> I had thought this patch was more or less a straight move of the code. >>>> But Stan's note revealed a change from what is currently in the tree. >>>> So the question is, can you say what else changed? >>>> That would be handy so I don't have to go over it line-by-line myself. >>> >>> Ah. Except for the comment (*1) the only substantive change is in the result: >>> Py_{NE,EQ} -> 0.1. >>> >>> (*1): Early on I made a copy because I wasn't sure how things would end up, >>> and left in a FIXME to remind myself to revisit. >>> I revisited and realized there's no need for the copy, but missed the >>> comment. Blech. >>> "diff -b before after" shows nothing of note to me. >> >> Here's v2 of the patch. >> >> I fixed the comment and added an assert to check type1,type2 != NULL. >> >> I changed the email address in the ChangeLog entry 'cus I'm having >> problems with this domain. >> After this email hopefully the switchover is complete. Well that's weird. Ok, no more attachment. 2013-11-09 Doug Evans * gdbtypes.c: #include bcache.h, dwarf2loc.h. (type_equality_entry): Move here from python/py-type.c. (type_equality_entry_d): Ditto. (compare_maybe_null_strings, check_types_equal): Ditto. (check_types_worklist, types_deeply_equal): Ditto. * gdbtypes.h (types_deeply_equal): Declare. * python/py-type.c: Remove inclusion of bcache.h, dwarf2loc.h. (typy_richcompare): Update. diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index 9069a11..70a7fb5 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -38,6 +38,8 @@ #include "hashtab.h" #include "exceptions.h" #include "cp-support.h" +#include "bcache.h" +#include "dwarf2loc.h" /* Initialize BADNESS constants. */ @@ -2494,7 +2496,217 @@ types_equal (struct type *a, struct type *b) return 0; } + +/* Deep comparison of types. */ + +/* An entry in the type-equality bcache. */ + +typedef struct type_equality_entry +{ + struct type *type1, *type2; +} type_equality_entry_d; + +DEF_VEC_O (type_equality_entry_d); + +/* A helper function to compare two strings. Returns 1 if they are + the same, 0 otherwise. Handles NULLs properly. */ + +static int +compare_maybe_null_strings (const char *s, const char *t) +{ + if (s == NULL && t != NULL) + return 0; + else if (s != NULL && t == NULL) + return 0; + else if (s == NULL && t== NULL) + return 1; + return strcmp (s, t) == 0; +} + +/* A helper function for check_types_worklist that checks two types for + "deep" equality. Returns non-zero if the types are considered the + same, zero otherwise. */ + +static int +check_types_equal (struct type *type1, struct type *type2, + VEC (type_equality_entry_d) **worklist) +{ + CHECK_TYPEDEF (type1); + CHECK_TYPEDEF (type2); + + if (type1 == type2) + return 1; + + if (TYPE_CODE (type1) != TYPE_CODE (type2) + || TYPE_LENGTH (type1) != TYPE_LENGTH (type2) + || TYPE_UNSIGNED (type1) != TYPE_UNSIGNED (type2) + || TYPE_NOSIGN (type1) != TYPE_NOSIGN (type2) + || TYPE_VARARGS (type1) != TYPE_VARARGS (type2) + || TYPE_VECTOR (type1) != TYPE_VECTOR (type2) + || TYPE_NOTTEXT (type1) != TYPE_NOTTEXT (type2) + || TYPE_INSTANCE_FLAGS (type1) != TYPE_INSTANCE_FLAGS (type2) + || TYPE_NFIELDS (type1) != TYPE_NFIELDS (type2)) + return 0; + + if (!compare_maybe_null_strings (TYPE_TAG_NAME (type1), + TYPE_TAG_NAME (type2))) + return 0; + if (!compare_maybe_null_strings (TYPE_NAME (type1), TYPE_NAME (type2))) + return 0; + + if (TYPE_CODE (type1) == TYPE_CODE_RANGE) + { + if (memcmp (TYPE_RANGE_DATA (type1), TYPE_RANGE_DATA (type2), + sizeof (*TYPE_RANGE_DATA (type1))) != 0) + return 0; + } + else + { + int i; + + for (i = 0; i < TYPE_NFIELDS (type1); ++i) + { + const struct field *field1 = &TYPE_FIELD (type1, i); + const struct field *field2 = &TYPE_FIELD (type2, i); + struct type_equality_entry entry; + + if (FIELD_ARTIFICIAL (*field1) != FIELD_ARTIFICIAL (*field2) + || FIELD_BITSIZE (*field1) != FIELD_BITSIZE (*field2) + || FIELD_LOC_KIND (*field1) != FIELD_LOC_KIND (*field2)) + return 0; + if (!compare_maybe_null_strings (FIELD_NAME (*field1), + FIELD_NAME (*field2))) + return 0; + switch (FIELD_LOC_KIND (*field1)) + { + case FIELD_LOC_KIND_BITPOS: + if (FIELD_BITPOS (*field1) != FIELD_BITPOS (*field2)) + return 0; + break; + case FIELD_LOC_KIND_ENUMVAL: + if (FIELD_ENUMVAL (*field1) != FIELD_ENUMVAL (*field2)) + return 0; + break; + case FIELD_LOC_KIND_PHYSADDR: + if (FIELD_STATIC_PHYSADDR (*field1) + != FIELD_STATIC_PHYSADDR (*field2)) + return 0; + break; + case FIELD_LOC_KIND_PHYSNAME: + if (!compare_maybe_null_strings (FIELD_STATIC_PHYSNAME (*field1), + FIELD_STATIC_PHYSNAME (*field2))) + return 0; + break; + case FIELD_LOC_KIND_DWARF_BLOCK: + { + struct dwarf2_locexpr_baton *block1, *block2; + + block1 = FIELD_DWARF_BLOCK (*field1); + block2 = FIELD_DWARF_BLOCK (*field2); + if (block1->per_cu != block2->per_cu + || block1->size != block2->size + || memcmp (block1->data, block2->data, block1->size) != 0) + return 0; + } + break; + default: + internal_error (__FILE__, __LINE__, _("Unsupported field kind " + "%d by check_types_equal"), + FIELD_LOC_KIND (*field1)); + } + + entry.type1 = FIELD_TYPE (*field1); + entry.type2 = FIELD_TYPE (*field2); + VEC_safe_push (type_equality_entry_d, *worklist, &entry); + } + } + + if (TYPE_TARGET_TYPE (type1) != NULL) + { + struct type_equality_entry entry; + + if (TYPE_TARGET_TYPE (type2) == NULL) + return 0; + + entry.type1 = TYPE_TARGET_TYPE (type1); + entry.type2 = TYPE_TARGET_TYPE (type2); + VEC_safe_push (type_equality_entry_d, *worklist, &entry); + } + else if (TYPE_TARGET_TYPE (type2) != NULL) + return 0; + + return 1; +} + +/* Check types on a worklist for equality. Returns zero if any pair + is not equal, non-zero if they are all considered equal. */ + +static int +check_types_worklist (VEC (type_equality_entry_d) **worklist, + struct bcache *cache) +{ + while (!VEC_empty (type_equality_entry_d, *worklist)) + { + struct type_equality_entry entry; + int added; + + entry = *VEC_last (type_equality_entry_d, *worklist); + VEC_pop (type_equality_entry_d, *worklist); + + /* If the type pair has already been visited, we know it is + ok. */ + bcache_full (&entry, sizeof (entry), cache, &added); + if (!added) + continue; + if (check_types_equal (entry.type1, entry.type2, worklist) == 0) + return 0; + } + + return 1; +} + +/* Return non-zero if types TYPE1 and TYPE2 are equal, as determined by a + "deep comparison". Otherwise return zero. */ + +int +types_deeply_equal (struct type *type1, struct type *type2) +{ + volatile struct gdb_exception except; + int result = 0; + struct bcache *cache; + VEC (type_equality_entry_d) *worklist = NULL; + struct type_equality_entry entry; + + gdb_assert (type1 != NULL && type2 != NULL); + + /* Early exit for the simple case. */ + if (type1 == type2) + return 1; + + cache = bcache_xmalloc (NULL, NULL); + + entry.type1 = type1; + entry.type2 = type2; + VEC_safe_push (type_equality_entry_d, worklist, &entry); + + TRY_CATCH (except, RETURN_MASK_ALL) + { + result = check_types_worklist (&worklist, cache); + } + /* check_types_worklist calls several nested helper functions, + some of which can raise a GDB Exception, so we just check + and rethrow here. If there is a GDB exception, a comparison + is not capable (or trusted), so exit. */ + bcache_xfree (cache); + VEC_free (type_equality_entry_d, worklist); + /* Rethrow if there was a problem. */ + if (except.reason < 0) + throw_exception (except); + + return result; +} + /* Compare one type (PARM) for compatibility with another (ARG). * PARM is intended to be the parameter type of a function; and * ARG is the supplied argument's type. This function tests if diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index d7fdedf..c7bef5f 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -1664,4 +1664,6 @@ extern struct type *copy_type (const struct type *type); extern int types_equal (struct type *, struct type *); +extern int types_deeply_equal (struct type *, struct type *); + #endif /* GDBTYPES_H */ diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c index 337e307..628a764 100644 --- a/gdb/python/py-type.c +++ b/gdb/python/py-type.c @@ -28,8 +28,6 @@ #include "objfiles.h" #include "language.h" #include "vec.h" -#include "bcache.h" -#include "dwarf2loc.h" #include "typeprint.h" typedef struct pyty_type_object @@ -961,173 +959,6 @@ typy_str (PyObject *self) return result; } -/* An entry in the type-equality bcache. */ - -typedef struct type_equality_entry -{ - struct type *type1, *type2; -} type_equality_entry_d; - -DEF_VEC_O (type_equality_entry_d); - -/* A helper function to compare two strings. Returns 1 if they are - the same, 0 otherwise. Handles NULLs properly. */ - -static int -compare_maybe_null_strings (const char *s, const char *t) -{ - if (s == NULL && t != NULL) - return 0; - else if (s != NULL && t == NULL) - return 0; - else if (s == NULL && t== NULL) - return 1; - return strcmp (s, t) == 0; -} - -/* A helper function for typy_richcompare that checks two types for - "deep" equality. Returns Py_EQ if the types are considered the - same, Py_NE otherwise. */ - -static int -check_types_equal (struct type *type1, struct type *type2, - VEC (type_equality_entry_d) **worklist) -{ - CHECK_TYPEDEF (type1); - CHECK_TYPEDEF (type2); - - if (type1 == type2) - return Py_EQ; - - if (TYPE_CODE (type1) != TYPE_CODE (type2) - || TYPE_LENGTH (type1) != TYPE_LENGTH (type2) - || TYPE_UNSIGNED (type1) != TYPE_UNSIGNED (type2) - || TYPE_NOSIGN (type1) != TYPE_NOSIGN (type2) - || TYPE_VARARGS (type1) != TYPE_VARARGS (type2) - || TYPE_VECTOR (type1) != TYPE_VECTOR (type2) - || TYPE_NOTTEXT (type1) != TYPE_NOTTEXT (type2) - || TYPE_INSTANCE_FLAGS (type1) != TYPE_INSTANCE_FLAGS (type2) - || TYPE_NFIELDS (type1) != TYPE_NFIELDS (type2)) - return Py_NE; - - if (!compare_maybe_null_strings (TYPE_TAG_NAME (type1), - TYPE_TAG_NAME (type2))) - return Py_NE; - if (!compare_maybe_null_strings (TYPE_NAME (type1), TYPE_NAME (type2))) - return Py_NE; - - if (TYPE_CODE (type1) == TYPE_CODE_RANGE) - { - if (memcmp (TYPE_RANGE_DATA (type1), TYPE_RANGE_DATA (type2), - sizeof (*TYPE_RANGE_DATA (type1))) != 0) - return Py_NE; - } - else - { - int i; - - for (i = 0; i < TYPE_NFIELDS (type1); ++i) - { - const struct field *field1 = &TYPE_FIELD (type1, i); - const struct field *field2 = &TYPE_FIELD (type2, i); - struct type_equality_entry entry; - - if (FIELD_ARTIFICIAL (*field1) != FIELD_ARTIFICIAL (*field2) - || FIELD_BITSIZE (*field1) != FIELD_BITSIZE (*field2) - || FIELD_LOC_KIND (*field1) != FIELD_LOC_KIND (*field2)) - return Py_NE; - if (!compare_maybe_null_strings (FIELD_NAME (*field1), - FIELD_NAME (*field2))) - return Py_NE; - switch (FIELD_LOC_KIND (*field1)) - { - case FIELD_LOC_KIND_BITPOS: - if (FIELD_BITPOS (*field1) != FIELD_BITPOS (*field2)) - return Py_NE; - break; - case FIELD_LOC_KIND_ENUMVAL: - if (FIELD_ENUMVAL (*field1) != FIELD_ENUMVAL (*field2)) - return Py_NE; - break; - case FIELD_LOC_KIND_PHYSADDR: - if (FIELD_STATIC_PHYSADDR (*field1) - != FIELD_STATIC_PHYSADDR (*field2)) - return Py_NE; - break; - case FIELD_LOC_KIND_PHYSNAME: - if (!compare_maybe_null_strings (FIELD_STATIC_PHYSNAME (*field1), - FIELD_STATIC_PHYSNAME (*field2))) - return Py_NE; - break; - case FIELD_LOC_KIND_DWARF_BLOCK: - { - struct dwarf2_locexpr_baton *block1, *block2; - - block1 = FIELD_DWARF_BLOCK (*field1); - block2 = FIELD_DWARF_BLOCK (*field2); - if (block1->per_cu != block2->per_cu - || block1->size != block2->size - || memcmp (block1->data, block2->data, block1->size) != 0) - return Py_NE; - } - break; - default: - internal_error (__FILE__, __LINE__, _("Unsupported field kind " - "%d by check_types_equal"), - FIELD_LOC_KIND (*field1)); - } - - entry.type1 = FIELD_TYPE (*field1); - entry.type2 = FIELD_TYPE (*field2); - VEC_safe_push (type_equality_entry_d, *worklist, &entry); - } - } - - if (TYPE_TARGET_TYPE (type1) != NULL) - { - struct type_equality_entry entry; - - if (TYPE_TARGET_TYPE (type2) == NULL) - return Py_NE; - - entry.type1 = TYPE_TARGET_TYPE (type1); - entry.type2 = TYPE_TARGET_TYPE (type2); - VEC_safe_push (type_equality_entry_d, *worklist, &entry); - } - else if (TYPE_TARGET_TYPE (type2) != NULL) - return Py_NE; - - return Py_EQ; -} - -/* Check types on a worklist for equality. Returns Py_NE if any pair - is not equal, Py_EQ if they are all considered equal. */ - -static int -check_types_worklist (VEC (type_equality_entry_d) **worklist, - struct bcache *cache) -{ - while (!VEC_empty (type_equality_entry_d, *worklist)) - { - struct type_equality_entry entry; - int added; - - entry = *VEC_last (type_equality_entry_d, *worklist); - VEC_pop (type_equality_entry_d, *worklist); - - /* If the type pair has already been visited, we know it is - ok. */ - bcache_full (&entry, sizeof (entry), cache, &added); - if (!added) - continue; - - if (check_types_equal (entry.type1, entry.type2, worklist) == Py_NE) - return Py_NE; - } - - return Py_EQ; -} - /* Implement the richcompare method. */ static PyObject * @@ -1150,30 +981,16 @@ typy_richcompare (PyObject *self, PyObject *other, int op) result = Py_EQ; else { - struct bcache *cache; - VEC (type_equality_entry_d) *worklist = NULL; - struct type_equality_entry entry; - - cache = bcache_xmalloc (NULL, NULL); - - entry.type1 = type1; - entry.type2 = type2; - VEC_safe_push (type_equality_entry_d, worklist, &entry); - TRY_CATCH (except, RETURN_MASK_ALL) { - result = check_types_worklist (&worklist, cache); + result = types_deeply_equal (type1, type2); } - /* check_types_worklist calls several nested Python helper - functions, some of which can raise a GDB Exception, so we - just check and convert here. If there is a GDB exception, a - comparison is not capable (or trusted), so exit. */ - bcache_xfree (cache); - VEC_free (type_equality_entry_d, worklist); + /* If there is a GDB exception, a comparison is not capable + (or trusted), so exit. */ GDB_PY_HANDLE_EXCEPTION (except); } - if (op == result) + if (op == (result ? Py_EQ : Py_NE)) Py_RETURN_TRUE; Py_RETURN_FALSE; }