From 0c50a0b4fe3956f9d2e08e75d47c9cbd79bf0268 Mon Sep 17 00:00:00 2001 From: Rekai Gonzalez-Alberquilla Date: Mon, 6 Feb 2017 11:10:06 +0000 Subject: cpu: Fix the usage of const DynInstPtr Summary: Usage of const DynInstPtr& when possible and introduction of move operators to RefCountingPtr. In many places, scoped references to dynamic instructions do a copy of the DynInstPtr when a reference would do. This is detrimental to performance. On top of that, in case there is a need for reference tracking for debugging, the redundant copies make the process much more painful than it already is. Also, from the theoretical point of view, a function/method that defines a convenience name to access an instruction should not be considered an owner of the data, i.e., doing a copy and not a reference is not justified. On a related topic, C++11 introduces move semantics, and those are useful when, for example, there is a class modelling a HW structure that contains a list, and has a getHeadOfList function, to prevent doing a copy to an internal variable -> update pointer, remove from the list -> update pointer, return value making a copy to the assined variable -> update pointer, destroy the returned value -> update pointer. Change-Id: I3bb46c20ef23b6873b469fd22befb251ac44d2f6 Signed-off-by: Giacomo Gabrielli Reviewed-on: https://gem5-review.googlesource.com/c/13105 Reviewed-by: Andreas Sandberg Reviewed-by: Jason Lowe-Power Maintainer: Andreas Sandberg Maintainer: Jason Lowe-Power --- src/base/refcnt.hh | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 2 deletions(-) (limited to 'src/base') diff --git a/src/base/refcnt.hh b/src/base/refcnt.hh index baf08c62e..f2821231d 100644 --- a/src/base/refcnt.hh +++ b/src/base/refcnt.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2017 ARM Limited + * All rights reserved. + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2002-2005 The Regents of The University of Michigan * All rights reserved. * @@ -31,6 +43,8 @@ #ifndef __BASE_REFCNT_HH__ #define __BASE_REFCNT_HH__ +#include + /** * @file base/refcnt.hh * @@ -80,11 +94,11 @@ class RefCounted virtual ~RefCounted() {} /// Increment the reference count - void incref() { ++count; } + void incref() const { ++count; } /// Decrement the reference count and destroy the object if all /// references are gone. - void decref() { if (--count <= 0) delete this; } + void decref() const { if (--count <= 0) delete this; } }; /** @@ -106,6 +120,18 @@ template class RefCountingPtr { protected: + /** Convenience aliases for const/non-const versions of T w/ friendship. */ + /** @{ */ + static constexpr auto TisConst = std::is_const::value; + using ConstT = typename std::conditional, + RefCountingPtr::type>>::type; + friend ConstT; + using NonConstT = typename std::conditional::type>, + RefCountingPtr>::type; + friend NonConstT; + /** @} */ /// The stored pointer. /// Arguably this should be private. T *data; @@ -163,6 +189,18 @@ class RefCountingPtr /// one. Adds a reference. RefCountingPtr(const RefCountingPtr &r) { copy(r.data); } + /** Move-constructor. + * Does not add a reference. + */ + RefCountingPtr(RefCountingPtr&& r) + { + data = r.data; + r.data = nullptr; + } + + template + RefCountingPtr(const NonConstT &r) { copy(r.data); } + /// Destroy the pointer and any reference it may hold. ~RefCountingPtr() { del(); } @@ -179,6 +217,12 @@ class RefCountingPtr /// Directly access the pointer itself without taking a reference. T *get() const { return data; } + template + operator RefCountingPtr::type>() + { + return RefCountingPtr(*this); + } + /// Assign a new value to the pointer const RefCountingPtr &operator=(T *p) { set(p); return *this; } @@ -186,6 +230,18 @@ class RefCountingPtr const RefCountingPtr &operator=(const RefCountingPtr &r) { return operator=(r.data); } + /// Move-assign the pointer from another RefCountingPtr + const RefCountingPtr &operator=(RefCountingPtr&& r) + { + /* This happens regardless of whether the pointer is the same or not, + * because of the move semantics, the rvalue needs to be 'destroyed'. + */ + del(); + data = r.data; + r.data = nullptr; + return *this; + } + /// Check if the pointer is empty bool operator!() const { return data == 0; } -- cgit v1.2.3