From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wr1-x42e.google.com (mail-wr1-x42e.google.com [IPv6:2a00:1450:4864:20::42e]) by sourceware.org (Postfix) with ESMTPS id 0D77F3865460 for ; Tue, 14 Jul 2020 17:14:38 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 0D77F3865460 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-x42e.google.com with SMTP id o11so23290618wrv.9 for ; Tue, 14 Jul 2020 10:14:38 -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=BC0kfthC6CsGu+y3H3UkQh9Du5wGNkVoaHyeNVoBp+I=; b=OIP5ssjicG0yGzsYl5ycytL0i0losa11mXRqPc7mltn7EN51RNF5kALwbfjA8VJYkP IUtsP7XDGJ9ja7NznO7HJHg2KWUKzPcmJr0GSQhGsfby8SzMKqh0ZPzu/eaNysswoSm8 dNOyYfx4f+KVSNv/o5CJ3f77YjGmSUV8zi0kPL4o4B6qGRPEwGA7EiwzCX+J0fKWoGjy T2mupZQBGzQ7hjfyYyVKpjx3GI4kT9cMpP80BBeSHG8VyabtEjPSWfZ4o0zyhmet4ctf scuhsHuB18/3yKcxTv0kYInC4Q3PeFxvjSCokekUpTynd3h7QwItnV6ZH/Ugpfia0qtK UIXw== 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=BC0kfthC6CsGu+y3H3UkQh9Du5wGNkVoaHyeNVoBp+I=; b=b4RELYu8OO90n7gcWwXLlpSmwYciLwB2BKbxQAmedqnBwFLzeyC1PFpexOKBlkCT05 FSF4oVfyM0eRug5YKJ7WLTFIQupTlygykJDXUUk+VEQaGVBAtQrNO/CHVIFkya/BTy09 4stnmmjEJa4uw2/oOQ9PnZoQwFrMXKgeY31T/PoQuvhWjfoXnGeTDflnGZA1kH8xJdW0 7s/mCV8KADHBErEvL5ZWHjKjrirouOfQGuxMux0Xb+qUNL3QyXtydr16WQS5ddifHUCF bjv2TmGn0nbi/r+fQgIBEI1QGCOcO6xpuLusr0VFdvCVU6LaCVC9CKjO3k6qMcVItdTN 9IEw== X-Gm-Message-State: AOAM532YeszFZqdM3CG6r7odVWtHkXsPqQtrzWJ7W/MxbKEENai2XtwQ 4iGcFhTkl+uo/6yc1rnJ1hnoHgA6LFk= X-Google-Smtp-Source: ABdhPJz55pRXLXIlackU9JwvFhuDwz67MoaCsw2+dlF4D9hZMP2ptGdYDgCfKNcEp9PN5XDGNzJeIA== X-Received: by 2002:adf:cf0a:: with SMTP id o10mr6969979wrj.14.1594746876785; Tue, 14 Jul 2020 10:14:36 -0700 (PDT) Received: from localhost (host86-128-12-23.range86-128.btcentralplus.com. [86.128.12.23]) by smtp.gmail.com with ESMTPSA id i6sm18609061wrp.92.2020.07.14.10.14.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 14 Jul 2020 10:14:35 -0700 (PDT) From: Andrew Burgess To: gdb-patches@sourceware.org Cc: Tom Tromey , Andrew Burgess Subject: [PATCHv2 1/2] gdb/python: Reuse gdb.RegisterDescriptor objects where possible Date: Tue, 14 Jul 2020 18:14:30 +0100 Message-Id: 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=-10.1 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: Tue, 14 Jul 2020 17:14:39 -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 | 61 +++++++++++++++---- gdb/testsuite/ChangeLog | 4 ++ .../gdb.python/py-arch-reg-names.exp | 19 ++++++ 4 files changed, 82 insertions(+), 13 deletions(-) diff --git a/gdb/python/py-registers.c b/gdb/python/py-registers.c index db0fe37eecb..8e22a919d87 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,17 @@ typedef struct { extern PyTypeObject reggroup_object_type CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("reggroup_object"); +/* Associates a vector of gdb.RegisterDescriptor objects 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 +131,38 @@ gdbpy_reggroup_name (PyObject *self, void *closure) return gdbpy_reggroup_to_string (self); } -/* Create an return a new gdb.RegisterDescriptor object. */ -static PyObject * -gdbpy_new_register_descriptor (struct gdbarch *gdbarch, +/* 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 gdbpy_ref<> +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; + auto 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) + { + gdbpy_ref reg + (PyObject_New (register_descriptor_object, + ®ister_descriptor_object_type)); + if (reg == NULL) + return NULL; + reg->regnum = regnum; + reg->gdbarch = gdbarch; + vec->at (regnum) = gdbpy_ref<> ((PyObject *) reg.release ()); + } + + /* Grab the register descriptor from the vector, the reference count is + automatically incremented thanks to gdbpy_ref. */ + return vec->at (regnum); } /* Convert the register descriptor to a string. */ @@ -281,7 +313,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).release (); } while (true); } @@ -291,6 +323,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