Avoid Interval and RefPosition unnecessary initialization and copying
authorMike Danes <onemihaid@hotmail.com>
Sat, 12 Mar 2016 11:33:10 +0000 (13:33 +0200)
committerMike Danes <onemihaid@hotmail.com>
Sat, 12 Mar 2016 12:34:33 +0000 (14:34 +0200)
RefPosition() builds a temporary object and initializes it with memset. push_back copies the temporary object to the list node. memset is called again to zero out the newly created RefPosition object.

Add emplace methods to jitstd::list to avoid copying. Drop the redundant memset call.

src/jit/jitstd.h
src/jit/jitstd/list.h
src/jit/jitstd/type_traits.h
src/jit/jitstd/utility.h
src/jit/lsra.cpp
src/jit/lsra.h

index 6bb1dda..59995fd 100644 (file)
@@ -5,6 +5,8 @@
 
 
 #include "allocator.h"
+#include "type_traits.h"
+#include "pair.h"
+#include "utility.h"
 #include "unordered_map.h"
 #include "unordered_set.h"
-#include "utility.h"
index d5d8361..a01ed45 100644 (file)
@@ -196,6 +196,8 @@ public:
     allocator_type get_allocator() const;
 
     iterator insert(iterator position, const T& x);
+    template <class... Args>
+    iterator emplace(iterator position, Args&&... args);
     void insert(iterator position, size_type n, const T& x);
     template <class InputIterator>
     void insert(iterator position, InputIterator first, InputIterator last);
@@ -212,7 +214,11 @@ public:
     void pop_front();
 
     void push_back(const T& val);
+    template <class... Args>
+    void emplace_back(Args&&... args);
     void push_front (const T& val);
+    template <class... Args>
+    void emplace_front(Args&&... args);
 
     reverse_iterator rbegin();
     const_reverse_iterator rbegin() const;
@@ -256,6 +262,14 @@ private:
             , m_pPrev(pPrev)
         {
         }
+
+        template <class... Args>
+        Node(Node* pPrev, Node* pNext, Args&&... args)
+            : m_value(jitstd::forward<Args>(args)...)
+            , m_pNext(pNext)
+            , m_pPrev(pPrev)
+        {
+        }
     };
 
     void destroy_helper();
@@ -494,6 +508,45 @@ typename list<T, Allocator>::iterator
 }
 
 template <typename T, typename Allocator>
+template <typename... Args>
+typename list<T, Allocator>::iterator 
+    list<T, Allocator>::emplace(iterator position, Args&&... args)
+{
+    ++m_nSize;
+
+    Node* pInsert = position.m_pNode;
+    if (pInsert == nullptr)
+    {
+        Node* pNewTail = new (m_nodeAllocator.allocate(1), placement_t()) Node(m_pTail, nullptr, jitstd::forward<Args>(args)...);
+        if (m_pHead == nullptr)
+        {
+            m_pTail = pNewTail;
+            m_pHead = m_pTail;
+        }
+        else
+        {
+            m_pTail->m_pNext = pNewTail;
+            m_pTail = pNewTail;
+        }
+        return iterator(m_pTail);
+    }
+    else
+    {
+        Node* pNode = new (m_nodeAllocator.allocate(1), placement_t()) Node(pInsert->m_pPrev, pInsert, jitstd::forward<Args>(args)...);
+        if (pInsert->m_pPrev)
+        {
+            pInsert->m_pPrev->m_pNext = pNode;
+        }
+        else
+        {
+            m_pHead = pNode;
+        }
+        pInsert->m_pPrev = pNode;
+        return iterator(pNode);
+    }
+}
+
+template <typename T, typename Allocator>
 void list<T, Allocator>::insert(iterator position, size_type n, const T& val)
 {
     insert_helper(position, n, val, int_not_an_iterator_tag());
@@ -614,12 +667,26 @@ void list<T, Allocator>::push_back(const T& val)
 }
 
 template <typename T, typename Allocator>
+template <typename... Args>
+void list<T, Allocator>::emplace_back(Args&&... args)
+{
+    emplace(end(), jitstd::forward<Args>(args)...);
+}
+
+template <typename T, typename Allocator>
 void list<T, Allocator>::push_front(const T& val)
 {
     insert(begin(), val);
 }
 
 template <typename T, typename Allocator>
+template <typename... Args>
+void list<T, Allocator>::emplace_front(Args&&... args)
+{
+    emplace(begin(), jitstd::forward<Args>(args)...);
+}
+
+template <typename T, typename Allocator>
 typename list<T, Allocator>::reverse_iterator
     list<T, Allocator>::rbegin()
 {
index 21503fb..1e853e8 100644 (file)
@@ -37,6 +37,36 @@ struct remove_cv : remove_const<typename remove_volatile<T>::type>
 };
 
 template <typename T>
+struct remove_reference
+{
+    typedef T type;
+};
+
+template <typename T>
+struct remove_reference<T&>
+{
+    typedef T type;
+};
+
+template <typename T>
+struct remove_reference<T&&>
+{
+    typedef T type;
+};
+
+template <typename T>
+struct is_lvalue_reference
+{
+    enum { value = false };
+};
+
+template <typename T>
+struct is_lvalue_reference<T&>
+{
+    enum { value = true };
+};
+
+template <typename T>
 struct is_unqualified_pointer
 {
     enum { value = false };
index 39379cb..80ce58e 100644 (file)
@@ -9,6 +9,21 @@
 namespace jitstd
 {
 
+template <typename T>
+inline 
+T&& forward(typename jitstd::remove_reference<T>::type& arg)
+{
+    return static_cast<T&&>(arg);
+}
+
+template <typename T>
+inline 
+T&& forward(typename jitstd::remove_reference<T>::type&& arg)
+{
+    static_assert(!jitstd::is_lvalue_reference<T>::value, "unexpected lvalue reference");
+    return static_cast<T&&>(arg);
+}
+
 namespace utility
 {
     // Template class for scoped execution of a lambda.
index 5bf10dd..4ec9996 100644 (file)
@@ -313,7 +313,7 @@ LinearScan::stressLimitRegs(RefPosition* refPosition, regMaskTP mask)
 Interval *
 LinearScan::newInterval(RegisterType theRegisterType)
 {
-    intervals.push_back(Interval());
+    intervals.emplace_back();
     Interval *newInt = &intervals.back();
     newInt->init();
 
@@ -332,9 +332,8 @@ LinearScan::newInterval(RegisterType theRegisterType)
 RefPosition *
 LinearScan::newRefPositionRaw()
 {
-    refPositions.push_back(RefPosition());
+    refPositions.emplace_back();
     RefPosition *newRP = &refPositions.back();
-    memset(newRP, 0, sizeof(RefPosition)); // TODO-Cleanup: call a RefPosition constructor instead?
 #ifdef DEBUG
     newRP->rpNum = refPositionCount;
 #endif // DEBUG
index 19843a3..69dd0e5 100644 (file)
@@ -1052,7 +1052,6 @@ public:
     // Initialize the interval
     void init()
     {
-        memset(this, 0, sizeof(Interval));
         physReg = REG_COUNT;
     }