summaryrefslogtreecommitdiff
path: root/src/base/refcnt.hh
diff options
context:
space:
mode:
authorRekai Gonzalez-Alberquilla <rekai.gonzalezalberquilla@arm.com>2017-02-06 11:10:06 +0000
committerGiacomo Gabrielli <giacomo.gabrielli@arm.com>2018-11-16 10:39:03 +0000
commit0c50a0b4fe3956f9d2e08e75d47c9cbd79bf0268 (patch)
tree7679abe2343e0504c93eb73d09635d546a211455 /src/base/refcnt.hh
parent338a173e822298bd22741342a7b24352450afdd1 (diff)
downloadgem5-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/refcnt.hh')
-rw-r--r--src/base/refcnt.hh60
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; }