diff --git a/benchmark/src/benchmarks/benchmark.assembler.cpp b/benchmark/src/benchmarks/benchmark.assembler.cpp index 9d9fd15..e9ba5a9 100644 --- a/benchmark/src/benchmarks/benchmark.assembler.cpp +++ b/benchmark/src/benchmarks/benchmark.assembler.cpp @@ -120,10 +120,13 @@ namespace zasm::benchmarks assembler.setCursor(nullptr); state.ResumeTiming(); - for (const auto& instr : zasm::tests::data::Instructions) + for (int i = 0; i < 100; i++) { - instr.emitter(assembler); - numInstructions++; + for (const auto& instr : zasm::tests::data::Instructions) + { + instr.emitter(assembler); + numInstructions++; + } } } diff --git a/tests/src/tests/tests.assembler.cpp b/tests/src/tests/tests.assembler.cpp index 29f60c1..ec6ea18 100644 --- a/tests/src/tests/tests.assembler.cpp +++ b/tests/src/tests/tests.assembler.cpp @@ -51,14 +51,14 @@ namespace zasm::tests Program program(MachineMode::AMD64); x86::Assembler assembler(program); - + ASSERT_EQ(assembler.mov(x86::rax, x86::rax), ErrorCode::None); auto* nodeA = assembler.getCursor(); ASSERT_EQ(assembler.mov(x86::rdx, x86::rdx), ErrorCode::None); auto* nodeB = assembler.getCursor(); ASSERT_EQ(assembler.mov(x86::rbx, x86::rbx), ErrorCode::None); auto* nodeC = assembler.getCursor(); - + program.destroy(nodeC); ASSERT_EQ(assembler.getCursor(), nodeB); diff --git a/tests/src/tests/tests.program.cpp b/tests/src/tests/tests.program.cpp index 019f290..b206274 100644 --- a/tests/src/tests/tests.program.cpp +++ b/tests/src/tests/tests.program.cpp @@ -347,4 +347,26 @@ namespace zasm::tests ASSERT_EQ(imm.value(), 3); } + TEST(ProgramTests, TestNodeType) + { + Program program(MachineMode::AMD64); + + auto testIns = Instruction{}.setMnemonic(x86::Mnemonic::Add); + + auto* node = program.createNode(testIns); + ASSERT_NE(node, nullptr); + + ASSERT_TRUE(node->holds()); + + ASSERT_FALSE(node->holds()); + + auto* inst = node->getIf(); + ASSERT_NE(inst, nullptr); + + ASSERT_EQ(testIns, *inst); + + auto* data = node->getIf(); + ASSERT_EQ(data, nullptr); + } + } // namespace zasm::tests diff --git a/zasm/include/zasm/program/node.hpp b/zasm/include/zasm/program/node.hpp index 3f16c77..e89603b 100644 --- a/zasm/include/zasm/program/node.hpp +++ b/zasm/include/zasm/program/node.hpp @@ -40,7 +40,7 @@ namespace zasm NodeFlags _flags{}; Node* _prev{}; Node* _next{}; - std::variant _data{}; + std::variant _data{}; union { @@ -51,9 +51,9 @@ namespace zasm protected: // Internal use only. template - constexpr Node(Id nodeId, T&& val) noexcept + constexpr Node(Id nodeId, T* val) noexcept : _id{ nodeId } - , _data{ std::forward(val) } + , _data{ val } { } @@ -97,7 +97,7 @@ namespace zasm /// True if the T is the current type template constexpr bool holds() const noexcept { - return std::holds_alternative(_data); + return std::holds_alternative(_data); } /// @@ -108,13 +108,13 @@ namespace zasm /// Returns a reference to the data with the type of T template constexpr const T& get() const { - return std::get(_data); + return *std::get(_data); } /// template constexpr T& get() { - return std::get(_data); + return *std::get(_data); } /// @@ -125,13 +125,19 @@ namespace zasm /// Pointer of type T template constexpr const T* getIf() const noexcept { - return std::get_if(&_data); + auto r = std::get_if(&_data); + if (r == nullptr) + return nullptr; + return *r; } /// template constexpr T* getIf() noexcept { - return std::get_if(&_data); + auto r = std::get_if(&_data); + if (r == nullptr) + return nullptr; + return *r; } /// @@ -141,15 +147,15 @@ namespace zasm /// Function type /// Visitor function /// The result of the visitor function - template constexpr auto visit(F&& func) const + template constexpr auto visit(TPred&& func) const { - return std::visit(std::forward(func), _data); + return std::visit([&](auto&& obj) { return func(*obj); }, _data); } /// - template constexpr auto visit(F&& func) + template constexpr auto visit(TPred&& func) { - return std::visit(std::forward(func), _data); + return std::visit([&](auto&& obj) { return func(*obj); }, _data); } /// diff --git a/zasm/src/zasm/src/program/program.cpp b/zasm/src/zasm/src/program/program.cpp index bb50ad5..031cec9 100644 --- a/zasm/src/zasm/src/program/program.cpp +++ b/zasm/src/zasm/src/program/program.cpp @@ -127,8 +127,8 @@ namespace zasm return entry.node; } - template - static void notifyObservers(const F&& func, const std::vector& observers, TArgs&&... args) noexcept + template + static void notifyObservers(const TPred&& func, const std::vector& observers, TArgs&&... args) noexcept { if constexpr (TNotify) { @@ -374,12 +374,26 @@ namespace zasm // Release. auto* nodeToDestroy = detail::toInternal(node); - state.nodePool.destroy(nodeToDestroy); + + node->visit([&](auto& ptr) { + using T = std::decay_t; + + auto& objectPool = state.objectPools.get(); + objectPool.destroy(&ptr); + + if (!quickDestroy) + { + objectPool.deallocate(&ptr, 1); + } + }); + + auto& nodePool = state.objectPools.get(); + nodePool.destroy(nodeToDestroy); if (!quickDestroy) { // Release memory, when quickDestroy is true the entire pool will be cleared at once. - state.nodePool.deallocate(nodeToDestroy, 1); + nodePool.deallocate(nodeToDestroy, 1); // Remove mapping. auto& nodeMap = state.nodeMap; @@ -424,7 +438,7 @@ namespace zasm _state->sections.clear(); _state->labels.clear(); _state->symbolNames.clear(); - _state->nodePool.reset(); + _state->objectPools.reset(); } void Program::setEntryPoint(const Label& label) @@ -437,19 +451,27 @@ namespace zasm return _state->entryPoint; } - template Node* createNode_(detail::ProgramState& state, TArgs&&... args) + template Node* createNode_(detail::ProgramState& state, T&& object) { const auto nextId = state.nextNodeId; state.nextNodeId = static_cast(static_cast>(nextId) + 1U); - auto& pool = state.nodePool; - auto* node = detail::toInternal(pool.allocate(1)); + auto& nodePool = state.objectPools.get(); + auto* node = detail::toInternal(nodePool.allocate(1)); if (node == nullptr) { return nullptr; } - ::new ((void*)node) detail::Node(nextId, std::forward(args)...); + // Construct object. + using ObjectType = std::decay_t; + auto& objectPool = state.objectPools.get(); + + auto* obj = objectPool.allocate(1); + ::new ((void*)obj) ObjectType(std::move(object)); + + // Construct node. + ::new ((void*)node) detail::Node(nextId, obj); notifyObservers(&Observer::onNodeCreated, state.observer, node); diff --git a/zasm/src/zasm/src/program/program.node.hpp b/zasm/src/zasm/src/program/program.node.hpp index 0047601..43577d6 100644 --- a/zasm/src/zasm/src/program/program.node.hpp +++ b/zasm/src/zasm/src/program/program.node.hpp @@ -11,8 +11,8 @@ namespace zasm { public: template - constexpr Node(zasm::Node::Id id, T&& val) noexcept - : ::zasm::Node(id, std::forward(val)) + constexpr Node(zasm::Node::Id id, T* val) noexcept + : ::zasm::Node(id, val) { } void setPrev(::zasm::Node* node) noexcept diff --git a/zasm/src/zasm/src/program/program.state.hpp b/zasm/src/zasm/src/program/program.state.hpp index 1496ada..4c2e2a1 100644 --- a/zasm/src/zasm/src/program/program.state.hpp +++ b/zasm/src/zasm/src/program/program.state.hpp @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -22,8 +23,6 @@ namespace zasm namespace zasm::detail { - constexpr std::size_t PoolSize = 1U << 10; - struct LabelData { Label::Id id{ Label::Id::Invalid }; @@ -46,11 +45,36 @@ namespace zasm::detail zasm::Node* node{}; }; - struct NodeStorage + namespace detail { - ObjectPool nodePool; - Node::Id nextNodeId{}; - }; + template + struct PoolSize + { + static constexpr std::size_t kSize = 50'000; + }; + + template<> struct PoolSize + { + static constexpr std::size_t kSize = 30'000; + }; + + template struct ObjectPools + { + std::tuple::kSize>...> pools; + + template auto& get() + { + return std::get::kSize>>(pools); + } + + void reset() + { + std::apply([](auto&... pool) { (pool.reset(), ...); }, pools); + } + }; + } // namespace detail + + using ObjectPools = detail::ObjectPools; struct NodeList { @@ -64,7 +88,7 @@ namespace zasm::detail StringPool symbolNames; }; - struct ProgramState : NodeStorage, NodeList, Symbols + struct ProgramState : NodeList, Symbols { MachineMode mode{}; @@ -79,6 +103,9 @@ namespace zasm::detail Label entryPoint{ Label::Id::Invalid }; + ObjectPools objectPools; + Node::Id nextNodeId{}; + ProgramState(MachineMode m) : mode(m) {