allocate x64 block structures in the code buffer for better data locality

This commit is contained in:
Anthony Pesch 2015-09-28 03:59:40 -07:00
parent 1265209ab6
commit 17274fe815
3 changed files with 283 additions and 281 deletions

View File

@ -32,7 +32,8 @@ const int x64_num_registers = sizeof(x64_registers) / sizeof(Register);
}
}
X64Backend::X64Backend(Memory &memory) : Backend(memory), emitter_(memory) {}
X64Backend::X64Backend(Memory &memory)
: Backend(memory), emitter_(memory, 1024 * 1024 * 8) {}
X64Backend::~X64Backend() {}
@ -45,13 +46,32 @@ int X64Backend::num_registers() const {
void X64Backend::Reset() { emitter_.Reset(); }
RuntimeBlock *X64Backend::AssembleBlock(ir::IRBuilder &builder) {
X64Fn fn;
if (!emitter_.Emit(builder, &fn)) {
// allocate block structure at start of code buffer, making for nice data
// locality
X64Block *block = emitter_.getCurr<X64Block *>();
try {
emitter_.setSize(emitter_.getSize() + sizeof(X64Block));
} catch (const Xbyak::Error &) {
return nullptr;
}
return new X64Block(builder.guest_cycles(), fn);
// try to generate the x64 code. if the code buffer overflows let the backend
// know so it can reset the cache and try again
X64Fn fn;
try {
fn = emitter_.Emit(builder);
} catch (const Xbyak::Error &e) {
if (e == Xbyak::ERR_CODE_IS_TOO_BIG) {
return nullptr;
}
LOG_FATAL("X64 codegen failure, %s", e.what());
}
// initialize block structure
new (block) X64Block(builder.guest_cycles(), fn);
return block;
}
void X64Backend::FreeBlock(RuntimeBlock *block) { delete block; }
void X64Backend::FreeBlock(RuntimeBlock *block) { /*delete block;*/
}

File diff suppressed because it is too large Load Diff

View File

@ -27,16 +27,16 @@ enum {
typedef uint32_t (*X64Fn)(void *guest_ctx, hw::Memory *memory);
class X64Emitter {
class X64Emitter : public Xbyak::CodeGenerator {
public:
X64Emitter(hw::Memory &memory);
X64Emitter(hw::Memory &memory, size_t max_size);
~X64Emitter();
Xbyak::Label &epilog_label() { return *epilog_label_; }
void Reset();
bool Emit(ir::IRBuilder &builder, X64Fn *fn);
X64Fn Emit(ir::IRBuilder &builder);
// helpers for the emitter callbacks
const Xbyak::Operand &GetOperand(const ir::Value *v, int size = -1);
@ -58,12 +58,7 @@ class X64Emitter {
void EmitBody(ir::IRBuilder &builder);
void EmitEpilog(ir::IRBuilder &builder, int stack_size);
int AlignLocals(ir::IRBuilder &builder);
int PushModifiedRegisters(ir::IRBuilder &builder);
void PopModifiedRegisters();
hw::Memory &memory_;
Xbyak::CodeGenerator c_;
Arena arena_;
Xbyak::Label *epilog_label_;
int modified_marker_;