Common: Add an intrusive list implementation; remove use of boost::intrusive::list.
This commit is contained in:
parent
9264e2e04c
commit
94b99f5949
6 changed files with 289 additions and 7 deletions
|
@ -43,6 +43,7 @@ set(HEADERS
|
|||
common/bit_util.h
|
||||
common/code_block.h
|
||||
common/common_types.h
|
||||
common/intrusive_list.h
|
||||
common/memory_pool.h
|
||||
common/memory_util.h
|
||||
common/mp.h
|
||||
|
|
282
src/common/intrusive_list.h
Normal file
282
src/common/intrusive_list.h
Normal file
|
@ -0,0 +1,282 @@
|
|||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2016 MerryMage
|
||||
* This software may be used and distributed according to the terms of the GNU
|
||||
* General Public License version 2 or any later version.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Dynarmic {
|
||||
namespace Common {
|
||||
|
||||
template <typename T> class IntrusiveListNode;
|
||||
template <typename T> class IntrusiveList;
|
||||
template <typename T> class IntrusiveListIterator;
|
||||
template <typename T> class IntrusiveListConstIterator;
|
||||
|
||||
template <typename T>
|
||||
class IntrusiveListNode {
|
||||
public:
|
||||
IntrusiveListNode() : next(this), prev(this) {}
|
||||
void UnlinkFromList() {
|
||||
prev->next = next;
|
||||
next->prev = prev;
|
||||
#if !defined(NDEBUG)
|
||||
next = prev = nullptr;
|
||||
#endif
|
||||
}
|
||||
private:
|
||||
friend class IntrusiveList<T>;
|
||||
friend class IntrusiveListIterator<T>;
|
||||
friend class IntrusiveListConstIterator<T>;
|
||||
IntrusiveListNode<T>* next;
|
||||
IntrusiveListNode<T>* prev;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class IntrusiveList {
|
||||
public:
|
||||
/**
|
||||
* Add an entry to the start of the list.
|
||||
* @param node Node to add to the list.
|
||||
*/
|
||||
void Prepend(T& node) {
|
||||
AddAfter(root.get(), static_cast<IntrusiveListNode<T>*>(&node));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an entry to the end of the list
|
||||
* @param node Node to add to the list.
|
||||
*/
|
||||
void Append(T& node) {
|
||||
AddBefore(root.get(), static_cast<IntrusiveListNode<T>*>(&node));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an entry after an existing node in this list
|
||||
* @param existing_node Node to add new_node after. Must already be member of the list.
|
||||
* @param new_node Node to add to the list.
|
||||
*/
|
||||
void AddAfter(T& existing, T& node) {
|
||||
AddAfter(static_cast<IntrusiveListNode<T>*>(&existing), static_cast<IntrusiveListNode<T>*>(&node));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an entry before an existing node in this list
|
||||
* @param existing_node Node to add new_node before. Must already be member of the list.
|
||||
* @param new_node Node to add to the list.
|
||||
*/
|
||||
void AddBefore(T& existing, T& node) {
|
||||
AddBefore(static_cast<IntrusiveListNode<T>*>(&existing), static_cast<IntrusiveListNode<T>*>(&node));
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes node from list
|
||||
* @param node Node to remove from list.
|
||||
*/
|
||||
void Remove(T& node) {
|
||||
node.UnlinkFromList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this list empty?
|
||||
* @returns true if there are no nodes in this list.
|
||||
*/
|
||||
bool IsEmpty() {
|
||||
return root->next == root.get();
|
||||
}
|
||||
|
||||
IntrusiveListIterator<T> begin();
|
||||
IntrusiveListIterator<T> end();
|
||||
IntrusiveListIterator<T> erase(const IntrusiveListIterator<T>&);
|
||||
IntrusiveListIterator<T> iterator_to(T&);
|
||||
|
||||
IntrusiveListConstIterator<T> begin() const;
|
||||
IntrusiveListConstIterator<T> end() const;
|
||||
IntrusiveListConstIterator<T> iterator_to(T&) const;
|
||||
|
||||
private:
|
||||
friend class IntrusiveListIterator<T>;
|
||||
friend class IntrusiveListConstIterator<T>;
|
||||
|
||||
void AddAfter(IntrusiveListNode<T>* existing_node, IntrusiveListNode<T>* new_node) {
|
||||
new_node->next = existing_node->next;
|
||||
new_node->prev = existing_node;
|
||||
existing_node->next->prev = new_node;
|
||||
existing_node->next = new_node;
|
||||
}
|
||||
|
||||
void AddBefore(IntrusiveListNode<T>* existing_node, IntrusiveListNode<T>* new_node) {
|
||||
new_node->next = existing_node;
|
||||
new_node->prev = existing_node->prev;
|
||||
existing_node->prev->next = new_node;
|
||||
existing_node->prev = new_node;
|
||||
}
|
||||
|
||||
std::shared_ptr<IntrusiveListNode<T>> root = std::make_shared<IntrusiveListNode<T>>();
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class IntrusiveListIterator {
|
||||
public:
|
||||
IntrusiveListIterator() : root(nullptr), node(nullptr) {}
|
||||
IntrusiveListIterator(IntrusiveList<T>* list, IntrusiveListNode<T>* node) : root(list->root.get()), node(node) {}
|
||||
IntrusiveListIterator(const IntrusiveListIterator& other) : root(other.root), node(other.node) {}
|
||||
IntrusiveListIterator& operator=(IntrusiveListIterator other) {
|
||||
std::swap(root, other.root);
|
||||
std::swap(node, other.node);
|
||||
return *this;
|
||||
}
|
||||
|
||||
IntrusiveListIterator& operator++() {
|
||||
node = node == root ? node : node->next;
|
||||
return *this;
|
||||
}
|
||||
IntrusiveListIterator operator++(int) {
|
||||
IntrusiveListIterator it(*this);
|
||||
node = node == root ? node : node->next;
|
||||
return it;
|
||||
}
|
||||
IntrusiveListIterator& operator--() {
|
||||
node = node->prev == root ? node : node->prev;
|
||||
return *this;
|
||||
}
|
||||
IntrusiveListIterator operator--(int) {
|
||||
IntrusiveListIterator it(*this);
|
||||
node = node->prev == root ? node : node->prev;
|
||||
return it;
|
||||
}
|
||||
|
||||
bool operator==(const IntrusiveListIterator& other) const {
|
||||
DEBUG_ASSERT(root == other.root);
|
||||
return node == other.node;
|
||||
}
|
||||
bool operator!=(const IntrusiveListIterator& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
const T& operator*() const {
|
||||
DEBUG_ASSERT(node != root);
|
||||
return *reinterpret_cast<T*>(node);
|
||||
}
|
||||
T& operator*() {
|
||||
DEBUG_ASSERT(node != root);
|
||||
return *reinterpret_cast<T*>(node);
|
||||
}
|
||||
T* operator->() {
|
||||
DEBUG_ASSERT(node != root);
|
||||
return reinterpret_cast<T*>(node);
|
||||
}
|
||||
const T* operator->() const {
|
||||
DEBUG_ASSERT(node != root);
|
||||
return reinterpret_cast<T*>(node);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class IntrusiveList<T>;
|
||||
IntrusiveListNode<T>* root;
|
||||
IntrusiveListNode<T>* node;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class IntrusiveListConstIterator {
|
||||
public:
|
||||
IntrusiveListConstIterator() : root(nullptr), node(nullptr) {}
|
||||
IntrusiveListConstIterator(const IntrusiveList<T>* list, IntrusiveListNode<T>* node) : root(list->root.get()), node(node) {}
|
||||
IntrusiveListConstIterator(const IntrusiveListConstIterator& other) : root(other.root), node(other.node) {}
|
||||
IntrusiveListConstIterator& operator=(IntrusiveListConstIterator other) {
|
||||
std::swap(root, other.root);
|
||||
std::swap(node, other.node);
|
||||
return *this;
|
||||
}
|
||||
|
||||
IntrusiveListConstIterator& operator++() {
|
||||
node = node == root ? node : node->next;
|
||||
return *this;
|
||||
}
|
||||
IntrusiveListConstIterator operator++(int) {
|
||||
IntrusiveListConstIterator it(*this);
|
||||
node = node == root ? node : node->next;
|
||||
return it;
|
||||
}
|
||||
IntrusiveListConstIterator& operator--() {
|
||||
node = node->prev == root ? node : node->prev;
|
||||
return *this;
|
||||
}
|
||||
IntrusiveListConstIterator operator--(int) {
|
||||
IntrusiveListConstIterator it(*this);
|
||||
node = node->prev == root ? node : node->prev;
|
||||
return it;
|
||||
}
|
||||
|
||||
bool operator==(const IntrusiveListConstIterator& other) const {
|
||||
DEBUG_ASSERT(root == other.root);
|
||||
return node == other.node;
|
||||
}
|
||||
bool operator!=(const IntrusiveListConstIterator& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
const T& operator*() const {
|
||||
DEBUG_ASSERT(node != root);
|
||||
return *reinterpret_cast<T*>(node);
|
||||
}
|
||||
const T* operator->() const {
|
||||
DEBUG_ASSERT(node != root);
|
||||
return reinterpret_cast<T*>(node);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class IntrusiveList<T>;
|
||||
IntrusiveListNode<T>* root;
|
||||
IntrusiveListNode<T>* node;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
IntrusiveListIterator<T> IntrusiveList<T>::begin() {
|
||||
return IntrusiveListIterator<T>(this, root->next);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
IntrusiveListIterator<T> IntrusiveList<T>::end() {
|
||||
return IntrusiveListIterator<T>(this, root.get());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
IntrusiveListIterator<T> IntrusiveList<T>::erase(const IntrusiveListIterator<T>& it) {
|
||||
DEBUG_ASSERT(it.root == root.get() && it.node != it.root);
|
||||
IntrusiveListNode<T>* to_remove = it.node;
|
||||
IntrusiveListIterator<T> ret = it;
|
||||
++ret;
|
||||
to_remove->UnlinkFromList();
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
IntrusiveListIterator<T> IntrusiveList<T>::iterator_to(T& item) {
|
||||
return IntrusiveListIterator<T>(this, static_cast<IntrusiveListNode<T>*>(&item));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
IntrusiveListConstIterator<T> IntrusiveList<T>::begin() const {
|
||||
return IntrusiveListConstIterator<T>(this, root->next);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
IntrusiveListConstIterator<T> IntrusiveList<T>::end() const {
|
||||
return IntrusiveListConstIterator<T>(this, root.get());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
IntrusiveListConstIterator<T> IntrusiveList<T>::iterator_to(T& item) const {
|
||||
return IntrusiveListConstIterator<T>(this, static_cast<IntrusiveListNode<T>*>(&item));
|
||||
}
|
||||
|
||||
} // namespace Common
|
||||
} // namespace Dynarmic
|
|
@ -10,12 +10,12 @@
|
|||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/intrusive/list.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/variant.hpp>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/intrusive_list.h"
|
||||
#include "common/memory_pool.h"
|
||||
#include "frontend/arm_types.h"
|
||||
#include "frontend/ir/opcodes.h"
|
||||
|
@ -113,8 +113,7 @@ private:
|
|||
} inner;
|
||||
};
|
||||
|
||||
using InstListLinkMode = boost::intrusive::link_mode<boost::intrusive::normal_link>;
|
||||
class Inst final : public boost::intrusive::list_base_hook<InstListLinkMode> {
|
||||
class Inst final : public Common::IntrusiveListNode<Inst> {
|
||||
public:
|
||||
Inst(Opcode op) : op(op) {}
|
||||
|
||||
|
@ -242,7 +241,7 @@ public:
|
|||
boost::optional<Arm::LocationDescriptor> cond_failed = {};
|
||||
|
||||
/// List of instructions in this block.
|
||||
boost::intrusive::list<Inst, InstListLinkMode> instructions;
|
||||
Common::IntrusiveList<Inst> instructions;
|
||||
/// Memory pool for instruction list
|
||||
std::unique_ptr<Common::Pool> instruction_alloc_pool = std::make_unique<Common::Pool>(sizeof(Inst), 4096);
|
||||
/// Terminal instruction of this block.
|
||||
|
|
|
@ -353,7 +353,7 @@ IR::Value IREmitter::Inst(IR::Opcode op, std::initializer_list<IR::Value> args)
|
|||
index++;
|
||||
});
|
||||
|
||||
block.instructions.push_back(*inst);
|
||||
block.instructions.Append(*inst);
|
||||
return IR::Value(inst);
|
||||
}
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ bool ArmTranslatorVisitor::ConditionPassed(Cond cond) {
|
|||
|
||||
// non-AL cond
|
||||
|
||||
if (!ir.block.instructions.empty()) {
|
||||
if (!ir.block.instructions.IsEmpty()) {
|
||||
// We've already emitted instructions. Quit for now, we'll make a new block here later.
|
||||
cond_state = ConditionalState::Break;
|
||||
ir.SetTerm(IR::Term::LinkBlock{ir.current_location});
|
||||
|
|
|
@ -19,7 +19,7 @@ void DeadCodeElimination(IR::Block& block) {
|
|||
// We iterate over the instructions in reverse order.
|
||||
// This is because removing an instruction reduces the number of uses for earlier instructions.
|
||||
|
||||
if (block.instructions.empty()) {
|
||||
if (block.instructions.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue