[dynarmic] inlined pool in block + slab-like for each block
Signed-off-by: lizzie <lizzie@eden-emu.dev>
This commit is contained in:
parent
119a373bd7
commit
202caab3de
2 changed files with 23 additions and 1 deletions
|
@ -37,7 +37,21 @@ Block::Block(const LocationDescriptor& location)
|
||||||
/// @param args A sequence of Value instances used as arguments for the instruction.
|
/// @param args A sequence of Value instances used as arguments for the instruction.
|
||||||
/// @returns Iterator to the newly created instruction.
|
/// @returns Iterator to the newly created instruction.
|
||||||
Block::iterator Block::PrependNewInst(iterator insertion_point, Opcode opcode, std::initializer_list<Value> args) noexcept {
|
Block::iterator Block::PrependNewInst(iterator insertion_point, Opcode opcode, std::initializer_list<Value> args) noexcept {
|
||||||
IR::Inst* inst = new IR::Inst(opcode);
|
// First try using the "inline" buffer, otherwise fallback to a slower slab-like allocation scheme
|
||||||
|
// purpouse is to avoid many calls to new/delete which invoke malloc which invokes mmap
|
||||||
|
// just pool it!!! - reason why there is an inline buffer is because many small blocks are created
|
||||||
|
// with few instructions due to subpar optimisations on other passes... plus branch-heavy code will
|
||||||
|
// hugely benefit from the coherency of faster allocations...
|
||||||
|
IR::Inst* inst;
|
||||||
|
if (inlined_inst.size() < inlined_inst.max_size()) {
|
||||||
|
inst = &inlined_inst[inlined_inst.size()];
|
||||||
|
inlined_inst.emplace_back(opcode);
|
||||||
|
} else {
|
||||||
|
if (pooled_inst.empty() || pooled_inst.back().size() == pooled_inst.back().max_size())
|
||||||
|
pooled_inst.emplace_back();
|
||||||
|
inst = &pooled_inst.back()[pooled_inst.back().size()];
|
||||||
|
pooled_inst.back().emplace_back(opcode);
|
||||||
|
}
|
||||||
DEBUG_ASSERT(args.size() == inst->NumArgs());
|
DEBUG_ASSERT(args.size() == inst->NumArgs());
|
||||||
std::for_each(args.begin(), args.end(), [&inst, index = size_t(0)](const auto& arg) mutable {
|
std::for_each(args.begin(), args.end(), [&inst, index = size_t(0)](const auto& arg) mutable {
|
||||||
inst->SetArg(index, arg);
|
inst->SetArg(index, arg);
|
||||||
|
|
|
@ -13,6 +13,9 @@
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include <boost/container/container_fwd.hpp>
|
||||||
|
#include <boost/container/static_vector.hpp>
|
||||||
|
#include <boost/container/stable_vector.hpp>
|
||||||
#include <mcl/container/intrusive_list.hpp>
|
#include <mcl/container/intrusive_list.hpp>
|
||||||
#include "dynarmic/common/common_types.h"
|
#include "dynarmic/common/common_types.h"
|
||||||
|
|
||||||
|
@ -163,8 +166,12 @@ public:
|
||||||
return cycle_count;
|
return cycle_count;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
|
/// "Hot cache" for small blocks so we don't call global allocator
|
||||||
|
boost::container::static_vector<Inst, 14> inlined_inst;
|
||||||
/// List of instructions in this block.
|
/// List of instructions in this block.
|
||||||
instruction_list_type instructions;
|
instruction_list_type instructions;
|
||||||
|
/// "Long/far" memory pool
|
||||||
|
boost::container::stable_vector<boost::container::static_vector<Inst, 32>> pooled_inst;
|
||||||
/// Block to execute next if `cond` did not pass.
|
/// Block to execute next if `cond` did not pass.
|
||||||
std::optional<LocationDescriptor> cond_failed = {};
|
std::optional<LocationDescriptor> cond_failed = {};
|
||||||
/// Description of the starting location of this block
|
/// Description of the starting location of this block
|
||||||
|
@ -180,6 +187,7 @@ private:
|
||||||
/// Number of cycles this block takes to execute.
|
/// Number of cycles this block takes to execute.
|
||||||
size_t cycle_count = 0;
|
size_t cycle_count = 0;
|
||||||
};
|
};
|
||||||
|
static_assert(sizeof(Block) == 2048);
|
||||||
|
|
||||||
/// Returns a string representation of the contents of block. Intended for debugging.
|
/// Returns a string representation of the contents of block. Intended for debugging.
|
||||||
std::string DumpBlock(const IR::Block& block) noexcept;
|
std::string DumpBlock(const IR::Block& block) noexcept;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue