Custom stack for IVM. 2-3x faster.
This commit is contained in:
parent
2ed6f478c1
commit
698eaeeb88
|
@ -10,6 +10,7 @@
|
|||
#include <alloy/backend/ivm/ivm_backend.h>
|
||||
|
||||
#include <alloy/backend/ivm/ivm_assembler.h>
|
||||
#include <alloy/backend/ivm/ivm_stack.h>
|
||||
#include <alloy/backend/ivm/tracing.h>
|
||||
|
||||
using namespace alloy;
|
||||
|
@ -39,6 +40,15 @@ int IVMBackend::Initialize() {
|
|||
return result;
|
||||
}
|
||||
|
||||
void* IVMBackend::AllocThreadData() {
|
||||
return new IVMStack();
|
||||
}
|
||||
|
||||
void IVMBackend::FreeThreadData(void* thread_data) {
|
||||
auto stack = (IVMStack*)thread_data;
|
||||
delete stack;
|
||||
}
|
||||
|
||||
Assembler* IVMBackend::CreateAssembler() {
|
||||
return new IVMAssembler(this);
|
||||
}
|
||||
|
|
|
@ -30,6 +30,9 @@ public:
|
|||
|
||||
virtual int Initialize();
|
||||
|
||||
virtual void* AllocThreadData();
|
||||
virtual void FreeThreadData(void* thread_data);
|
||||
|
||||
virtual Assembler* CreateAssembler();
|
||||
};
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include <alloy/backend/ivm/ivm_function.h>
|
||||
|
||||
#include <alloy/backend/ivm/ivm_stack.h>
|
||||
#include <alloy/backend/tracing.h>
|
||||
#include <alloy/runtime/runtime.h>
|
||||
#include <alloy/runtime/thread_state.h>
|
||||
|
@ -103,11 +104,8 @@ void IVMFunction::OnBreakpointHit(ThreadState* thread_state, IntCode* i) {
|
|||
|
||||
int IVMFunction::CallImpl(ThreadState* thread_state, uint64_t return_address) {
|
||||
// Setup register file on stack.
|
||||
const size_t max_stack_alloc = 16 * 1024;
|
||||
size_t register_file_size = register_count_ * sizeof(Register);
|
||||
Register* register_file = (Register*)(
|
||||
register_file_size >= max_stack_alloc ?
|
||||
xe_malloc(register_file_size) : alloca(register_file_size));
|
||||
auto stack = (IVMStack*)thread_state->backend_data();
|
||||
auto register_file = (Register*)stack->Alloc(register_count_);
|
||||
|
||||
Memory* memory = thread_state->memory();
|
||||
|
||||
|
@ -151,9 +149,7 @@ int IVMFunction::CallImpl(ThreadState* thread_state, uint64_t return_address) {
|
|||
}
|
||||
}
|
||||
|
||||
if (register_file_size >= max_stack_alloc) {
|
||||
xe_free(register_file);
|
||||
}
|
||||
stack->Free(register_count_);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <alloy/backend/ivm/ivm_stack.h>
|
||||
|
||||
using namespace alloy;
|
||||
using namespace alloy::backend;
|
||||
using namespace alloy::backend::ivm;
|
||||
|
||||
|
||||
IVMStack::IVMStack() :
|
||||
chunk_size_(2 * 1024 * 1024),
|
||||
head_chunk_(NULL), active_chunk_(NULL) {
|
||||
}
|
||||
|
||||
IVMStack::~IVMStack() {
|
||||
Chunk* chunk = head_chunk_;
|
||||
while (chunk) {
|
||||
Chunk* next = chunk->next;
|
||||
delete chunk;
|
||||
chunk = next;
|
||||
}
|
||||
head_chunk_ = NULL;
|
||||
}
|
||||
|
||||
Register* IVMStack::Alloc(size_t register_count) {
|
||||
size_t size = register_count * sizeof(Register);
|
||||
if (active_chunk_) {
|
||||
if (active_chunk_->capacity - active_chunk_->offset < size) {
|
||||
Chunk* next = active_chunk_->next;
|
||||
if (!next) {
|
||||
XEASSERT(size < chunk_size_); // need to support larger chunks
|
||||
next = new Chunk(chunk_size_);
|
||||
next->prev = active_chunk_;
|
||||
active_chunk_->next = next;
|
||||
}
|
||||
next->offset = 0;
|
||||
active_chunk_ = next;
|
||||
}
|
||||
} else {
|
||||
head_chunk_ = active_chunk_ = new Chunk(chunk_size_);
|
||||
}
|
||||
|
||||
uint8_t* p = active_chunk_->buffer + active_chunk_->offset;
|
||||
active_chunk_->offset += size;
|
||||
return (Register*)p;
|
||||
}
|
||||
|
||||
void IVMStack::Free(size_t register_count) {
|
||||
size_t size = register_count * sizeof(Register);
|
||||
if (active_chunk_->offset == size) {
|
||||
// Moving back a chunk.
|
||||
active_chunk_->offset = 0;
|
||||
if (active_chunk_->prev) {
|
||||
active_chunk_ = active_chunk_->prev;
|
||||
}
|
||||
} else {
|
||||
// Still in same chunk.
|
||||
active_chunk_->offset -= size;
|
||||
}
|
||||
}
|
||||
|
||||
IVMStack::Chunk::Chunk(size_t chunk_size) :
|
||||
prev(NULL), next(NULL),
|
||||
capacity(chunk_size), buffer(0), offset(0) {
|
||||
buffer = (uint8_t*)xe_malloc(capacity);
|
||||
}
|
||||
|
||||
IVMStack::Chunk::~Chunk() {
|
||||
if (buffer) {
|
||||
xe_free(buffer);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef ALLOY_BACKEND_IVM_IVM_STACK_H_
|
||||
#define ALLOY_BACKEND_IVM_IVM_STACK_H_
|
||||
|
||||
#include <alloy/core.h>
|
||||
|
||||
#include <alloy/backend/ivm/ivm_intcode.h>
|
||||
|
||||
|
||||
namespace alloy {
|
||||
namespace backend {
|
||||
namespace ivm {
|
||||
|
||||
|
||||
class IVMStack {
|
||||
public:
|
||||
IVMStack();
|
||||
~IVMStack();
|
||||
|
||||
Register* Alloc(size_t register_count);
|
||||
void Free(size_t register_count);
|
||||
|
||||
private:
|
||||
class Chunk {
|
||||
public:
|
||||
Chunk(size_t chunk_size);
|
||||
~Chunk();
|
||||
|
||||
Chunk* prev;
|
||||
Chunk* next;
|
||||
|
||||
size_t capacity;
|
||||
uint8_t* buffer;
|
||||
size_t offset;
|
||||
};
|
||||
|
||||
private:
|
||||
size_t chunk_size_;
|
||||
Chunk* head_chunk_;
|
||||
Chunk* active_chunk_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace ivm
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
|
||||
|
||||
#endif // ALLOY_BACKEND_IVM_IVM_STACK_H_
|
|
@ -8,7 +8,8 @@
|
|||
'ivm_backend.cc',
|
||||
'ivm_backend.h',
|
||||
'ivm_function.cc',
|
||||
'ivm_function.h',
|
||||
'ivm_stack.cc',
|
||||
'ivm_stack.h',
|
||||
'tracing.h',
|
||||
],
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue