From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wr1-x42c.google.com (mail-wr1-x42c.google.com [IPv6:2a00:1450:4864:20::42c]) by sourceware.org (Postfix) with ESMTPS id E5ED23861031 for ; Wed, 8 Jul 2020 08:48:17 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org E5ED23861031 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=embecosm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=andrew.burgess@embecosm.com Received: by mail-wr1-x42c.google.com with SMTP id f7so44955537wrw.1 for ; Wed, 08 Jul 2020 01:48:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=embecosm.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=uF6K6DoeJUv2KzXxaCcCvuV+vDIjjh/+ot5lBGGuhos=; b=V6ApQv0FDTO7npc/E9xn6OMJP5HGnWJxWxziVL7r+oBKWjsy+tpehFT3yHUJ+toPrq Bz0HemIbK9oI6vQOSLQl9YRprAXM3n8KcdZyDbhnS37jKU7bQk23Ox8Th/Xm1UJSzCQ7 TO4F6wH4eicoUdZQ5q87O8A0k2FN8Wt+3onRNX95qu2SYelfPQE5Jl4YSb1yMKm8A8Fu u0lXaImP+ZWYWkXFl8ZVIJm6aTZoB8lPEJHrKnXKLBzlwGF+DLSi4GnXoOGDgMhcGnIX SkwdMr2MArjd9Q9qxZKa+CYlkzzJYpgi2miK/zLQRGmnDu3Tb5IK9KqbDSj2fj2VRjBL m1cg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=uF6K6DoeJUv2KzXxaCcCvuV+vDIjjh/+ot5lBGGuhos=; b=jMyw/jftBRZlgJasurvUezVvVRRKjn2M3emeD3S2brZZmwtfDCPmfzC8h8sgTUf+by IU4TBgWvfgluZG5SW6scnKeqHJg8aQfxqP79V2Cx/I/o4Nt771kI7w9r4Gr9KzkBAxLL MuIjmsyfBsq2qtbvqEQy60u43dSKYhS1AHv7y0Q9OmZF+NXzLROBEkUwWGIKnbX7kKid CxzJi+zYi6QrC3pk39DjvOcXDFb6YlUiXgu4wIAuxpr99a4v+qX6poD1eoqO2anMgY92 0ApcUSxQWT8w0fpA/2fAxYKVyhf12WqvHGKylSgD3+l9NJNdsaUjdut5IfTt0KFlNCcZ o5Yw== X-Gm-Message-State: AOAM530Q2UNDmkMQ7YyyJW1o4XivxKPeR7A28xgrA7wuo7YE6BiyBO2M phi+ls34B//B2G62P6B56v8zSb9eikI= X-Google-Smtp-Source: ABdhPJzSvg7MDiTeGad6aqhmjsW/TiofT4FsVWfoW4SXoD4AgoyvO1Fy06859cbXp0A7qjJWxR00Lg== X-Received: by 2002:a5d:698e:: with SMTP id g14mr61761901wru.301.1594198096701; Wed, 08 Jul 2020 01:48:16 -0700 (PDT) Received: from localhost (host109-154-20-168.range109-154.btcentralplus.com. [109.154.20.168]) by smtp.gmail.com with ESMTPSA id x5sm5133402wmg.2.2020.07.08.01.48.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 08 Jul 2020 01:48:16 -0700 (PDT) From: Andrew Burgess To: gdb-patches@sourceware.org Subject: [PATCH 1/2] gdb/python: Reuse gdb.RegisterDescriptor objects where possible Date: Wed, 8 Jul 2020 09:48:11 +0100 Message-Id: <325856d3d21fd0f417d4ec0bfd9b233c0190c780.1594197735.git.andrew.burgess@embecosm.com> X-Mailer: git-send-email 2.25.4 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-9.8 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 08 Jul 2020 08:48:19 -0000 Instead of having the gdb.RegisterDescriptorIterator creating new gdb.RegisterDescriptor objects for each regnum, instead cache gdb.RegisterDescriptor objects on the gdbarch object and reuse these. This means that for every gdbarch/regnum pair there is a single unique gdb.RegisterDescriptor, this feels like a neater implementation than the existing one. It is possible for a user to see (in Python code) that the descriptors are now identical, but as the descriptors are read-only this should make no real difference. There should be no other user visible changes. gdb/ChangeLog: * python/py-registers.c (gdbpy_register_object_data): New static global. (gdbpy_register_object_data_init): New function. (gdbpy_new_register_descriptor): Renamed to... (gdbpy_get_register_descriptor): ...this, and update to reuse existing register descriptors where possible. (gdbpy_register_descriptor_iter_next): Update. (gdbpy_initialize_registers): Register new gdbarch data. gdb/testsuite/ChangeLog: * gdb.python/py-arch-reg-names.exp: Additional tests. --- gdb/ChangeLog | 11 ++++ gdb/python/py-registers.c | 63 +++++++++++++++---- gdb/testsuite/ChangeLog | 4 ++ .../gdb.python/py-arch-reg-names.exp | 19 ++++++ 4 files changed, 85 insertions(+), 12 deletions(-) diff --git a/gdb/python/py-registers.c b/gdb/python/py-registers.c index db0fe37eecb..fec84e5d5d4 100644 --- a/gdb/python/py-registers.c +++ b/gdb/python/py-registers.c @@ -24,6 +24,9 @@ #include "reggroups.h" #include "python-internal.h" +/* Token to access per-gdbarch data related to register descriptors. */ +static struct gdbarch_data *gdbpy_register_object_data = NULL; + /* Structure for iterator over register descriptors. */ typedef struct { PyObject_HEAD @@ -81,6 +84,18 @@ typedef struct { extern PyTypeObject reggroup_object_type CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("reggroup_object"); +/* Associates a vector of register_descriptor_object pointers with GDBARCH + as gdbarch_data via the gdbarch post init registration mechanism + (gdbarch_data_register_post_init). */ + +static void * +gdbpy_register_object_data_init (struct gdbarch *gdbarch) +{ + std::vector *vec + = new (std::vector); + return (void *) vec; +} + /* Create a new gdb.RegisterGroup object wrapping REGGROUP. */ static PyObject * @@ -117,20 +132,41 @@ gdbpy_reggroup_name (PyObject *self, void *closure) return gdbpy_reggroup_to_string (self); } -/* Create an return a new gdb.RegisterDescriptor object. */ +/* Return a gdb.RegisterDescriptor object for REGNUM from GDBARCH. For + each REGNUM (in GDBARCH) only one descriptor is ever created, which is + then cached on the GDBARCH. */ + static PyObject * -gdbpy_new_register_descriptor (struct gdbarch *gdbarch, +gdbpy_get_register_descriptor (struct gdbarch *gdbarch, int regnum) { - /* Create a new object and fill in its details. */ - register_descriptor_object *reg - = PyObject_New (register_descriptor_object, - ®ister_descriptor_object_type); - if (reg == NULL) - return NULL; - reg->regnum = regnum; - reg->gdbarch = gdbarch; - return (PyObject *) reg; + std::vector *vec + = (std::vector *) gdbarch_data + (gdbarch, gdbpy_register_object_data); + + /* Ensure that we have enough entries in the vector. */ + if (vec->size () <= regnum) + vec->resize ((regnum + 1), nullptr); + + /* If we don't already have a descriptor for REGNUM in GDBARCH then + create one now. */ + if (vec->at (regnum) == nullptr) + { + register_descriptor_object *reg + = PyObject_New (register_descriptor_object, + ®ister_descriptor_object_type); + if (reg == NULL) + return NULL; + reg->regnum = regnum; + reg->gdbarch = gdbarch; + vec->at (regnum) = reg; + } + + /* Grab the register descriptor from the vector and increment its + reference count before returning it. */ + PyObject *obj = (PyObject *) vec->at (regnum); + Py_XINCREF (obj); + return obj; } /* Convert the register descriptor to a string. */ @@ -281,7 +317,7 @@ gdbpy_register_descriptor_iter_next (PyObject *self) iter_obj->regnum++; if (name != nullptr && *name != '\0') - return gdbpy_new_register_descriptor (gdbarch, regnum); + return gdbpy_get_register_descriptor (gdbarch, regnum); } while (true); } @@ -291,6 +327,9 @@ gdbpy_register_descriptor_iter_next (PyObject *self) int gdbpy_initialize_registers () { + gdbpy_register_object_data + = gdbarch_data_register_post_init (gdbpy_register_object_data_init); + register_descriptor_object_type.tp_new = PyType_GenericNew; if (PyType_Ready (®ister_descriptor_object_type) < 0) return -1; diff --git a/gdb/testsuite/gdb.python/py-arch-reg-names.exp b/gdb/testsuite/gdb.python/py-arch-reg-names.exp index 14bc0a822a4..8dd34ef5fd2 100644 --- a/gdb/testsuite/gdb.python/py-arch-reg-names.exp +++ b/gdb/testsuite/gdb.python/py-arch-reg-names.exp @@ -85,3 +85,22 @@ for { set i 0 } { $i < [llength $regs] } { incr i } { } } gdb_assert { $found_non_match == 0 } "all registers match" + +# Check that we get the same register descriptors from two different +# iterators. +gdb_py_test_silent_cmd \ + "python iter1 = arch.registers ()" \ + "get first all register iterator" 0 +gdb_py_test_silent_cmd \ + "python iter2 = arch.registers ()" \ + "get second all register iterator" 0 +gdb_py_test_silent_cmd \ + [multi_line_input \ + "python" \ + "for r1, r2 in zip(iter1, iter2):" \ + " if (r1.name != r2.name):"\ + " raise gdb.GdbError (\"miss-matched names\")" \ + " if (r1 != r2):" \ + " raise gdb.GdbError (\"miss-matched objects\")" \ + "\004" ] \ + "check names and objects match" 1 -- 2.25.4