diff options
author | Rekai Gonzalez-Alberquilla <rekai.gonzalezalberquilla@arm.com> | 2017-02-06 11:10:06 +0000 |
---|---|---|
committer | Giacomo Gabrielli <giacomo.gabrielli@arm.com> | 2018-11-16 10:39:03 +0000 |
commit | 0c50a0b4fe3956f9d2e08e75d47c9cbd79bf0268 (patch) | |
tree | 7679abe2343e0504c93eb73d09635d546a211455 /src/base | |
parent | 338a173e822298bd22741342a7b24352450afdd1 (diff) | |
download | gem5-0c50a0b4fe3956f9d2e08e75d47c9cbd79bf0268.tar.xz |
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 <giacomo.gabrielli@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/c/13105
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
Maintainer: Jason Lowe-Power <jason@lowepower.com>
Diffstat (limited to 'src/base')
-rw-r--r-- | src/base/refcnt.hh | 60 |
1 files changed, 58 insertions, 2 deletions
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 <type_traits> + /** * @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 T> class RefCountingPtr { protected: + /** Convenience aliases for const/non-const versions of T w/ friendship. */ + /** @{ */ + static constexpr auto TisConst = std::is_const<T>::value; + using ConstT = typename std::conditional<TisConst, + RefCountingPtr<T>, + RefCountingPtr<typename std::add_const<T>::type>>::type; + friend ConstT; + using NonConstT = typename std::conditional<TisConst, + RefCountingPtr<typename std::remove_const<T>::type>, + RefCountingPtr<T>>::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 <bool B = TisConst> + 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 <bool B = TisConst> + operator RefCountingPtr<typename std::enable_if<!B, ConstT>::type>() + { + return RefCountingPtr<const T>(*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; } |