[Base] Make Arena alignment aware
- Add align parameter - Templated Alloc() implicitly aligns type correctly - Rewind may leak padding that was added due to alignment
This commit is contained in:
parent
d8cfeac79f
commit
86722be9ca
|
@ -2,7 +2,7 @@
|
|||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Copyright 2021 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
@ -13,6 +13,7 @@
|
|||
#include <memory>
|
||||
|
||||
#include "xenia/base/assert.h"
|
||||
#include "xenia/base/math.h"
|
||||
|
||||
namespace xe {
|
||||
|
||||
|
@ -45,12 +46,25 @@ void Arena::DebugFill() {
|
|||
}
|
||||
}
|
||||
|
||||
void* Arena::Alloc(size_t size) {
|
||||
void* Arena::Alloc(size_t size, size_t align) {
|
||||
assert_true(
|
||||
xe::bit_count(align) == 1 && align <= 16,
|
||||
"align needs to be a power of 2 and not greater than Chunk alignment");
|
||||
|
||||
// for alignment
|
||||
const auto get_padding = [this, align]() -> size_t {
|
||||
const size_t mask = align - 1;
|
||||
size_t deviation = active_chunk_->offset & mask;
|
||||
return (align - deviation) & mask;
|
||||
};
|
||||
|
||||
if (active_chunk_) {
|
||||
if (active_chunk_->capacity - active_chunk_->offset < size + 4096) {
|
||||
if (active_chunk_->capacity - active_chunk_->offset <
|
||||
size + get_padding() + 4096) {
|
||||
Chunk* next = active_chunk_->next;
|
||||
if (!next) {
|
||||
assert_true(size < chunk_size_, "need to support larger chunks");
|
||||
assert_true(size + get_padding() < chunk_size_,
|
||||
"need to support larger chunks");
|
||||
next = new Chunk(chunk_size_);
|
||||
active_chunk_->next = next;
|
||||
}
|
||||
|
@ -61,8 +75,11 @@ void* Arena::Alloc(size_t size) {
|
|||
head_chunk_ = active_chunk_ = new Chunk(chunk_size_);
|
||||
}
|
||||
|
||||
active_chunk_->offset += get_padding();
|
||||
uint8_t* p = active_chunk_->buffer + active_chunk_->offset;
|
||||
active_chunk_->offset += size;
|
||||
assert_true((reinterpret_cast<size_t>(p) & (align - 1)) == 0,
|
||||
"alignment failed");
|
||||
return p;
|
||||
}
|
||||
|
||||
|
@ -113,6 +130,8 @@ void Arena::CloneContents(void* buffer, size_t buffer_length) {
|
|||
Arena::Chunk::Chunk(size_t chunk_size)
|
||||
: next(nullptr), capacity(chunk_size), buffer(0), offset(0) {
|
||||
buffer = reinterpret_cast<uint8_t*>(malloc(capacity));
|
||||
assert_true((reinterpret_cast<size_t>(buffer) & size_t(15)) == 0,
|
||||
"16 byte alignment required");
|
||||
}
|
||||
|
||||
Arena::Chunk::~Chunk() {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Copyright 2021 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
@ -24,11 +24,13 @@ class Arena {
|
|||
void Reset();
|
||||
void DebugFill();
|
||||
|
||||
void* Alloc(size_t size);
|
||||
void* Alloc(size_t size, size_t align);
|
||||
template <typename T>
|
||||
T* Alloc() {
|
||||
return reinterpret_cast<T*>(Alloc(sizeof(T)));
|
||||
return reinterpret_cast<T*>(Alloc(sizeof(T), alignof(T)));
|
||||
}
|
||||
// When rewinding aligned allocations, any padding that was applied during
|
||||
// allocation will be leaked
|
||||
void Rewind(size_t size);
|
||||
|
||||
void* CloneContents();
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Copyright 2021 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
@ -73,14 +73,14 @@ void DataFlowAnalysisPass::AnalyzeFlow(HIRBuilder* builder,
|
|||
// Stash for value map. We may want to maintain this during building.
|
||||
auto arena = builder->arena();
|
||||
auto value_map = reinterpret_cast<Value**>(
|
||||
arena->Alloc(sizeof(Value*) * max_value_estimate));
|
||||
arena->Alloc(sizeof(Value*) * max_value_estimate, alignof(Value)));
|
||||
|
||||
// Allocate incoming bitvectors for use by blocks. We don't need outgoing
|
||||
// because they are only used during the block iteration.
|
||||
// Mapped by block ordinal.
|
||||
// TODO(benvanik): cache this list, grow as needed, etc.
|
||||
auto incoming_bitvectors =
|
||||
(llvm::BitVector**)arena->Alloc(sizeof(llvm::BitVector*) * block_count);
|
||||
auto incoming_bitvectors = (llvm::BitVector**)arena->Alloc(
|
||||
sizeof(llvm::BitVector*) * block_count, alignof(llvm::BitVector));
|
||||
for (auto n = 0u; n < block_count; n++) {
|
||||
incoming_bitvectors[n] = new llvm::BitVector(max_value_estimate);
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2020 Ben Vanik. All rights reserved. *
|
||||
* Copyright 2021 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
@ -45,7 +45,7 @@ bool FinalizationPass::Run(HIRBuilder* builder) {
|
|||
while (label) {
|
||||
if (!label->name) {
|
||||
const size_t label_len = 6 + 4;
|
||||
char* name = reinterpret_cast<char*>(arena->Alloc(label_len + 1));
|
||||
char* name = reinterpret_cast<char*>(arena->Alloc(label_len + 1, 1));
|
||||
assert_true(label->id <= 9999);
|
||||
auto end = fmt::format_to_n(name, label_len, "_label{}", label->id);
|
||||
name[end.size] = '\0';
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2020 Ben Vanik. All rights reserved. *
|
||||
* Copyright 2021 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
@ -739,7 +739,7 @@ void HIRBuilder::Comment(std::string_view value) {
|
|||
return;
|
||||
}
|
||||
auto size = value.size();
|
||||
auto p = reinterpret_cast<char*>(arena_->Alloc(size + 1));
|
||||
auto p = reinterpret_cast<char*>(arena_->Alloc(size + 1, 1));
|
||||
std::memcpy(p, value.data(), size);
|
||||
p[size] = '\0';
|
||||
Instr* i = AppendInstr(OPCODE_COMMENT_info, 0);
|
||||
|
@ -752,7 +752,7 @@ void HIRBuilder::Comment(const StringBuffer& value) {
|
|||
return;
|
||||
}
|
||||
auto size = value.length();
|
||||
auto p = reinterpret_cast<char*>(arena_->Alloc(size + 1));
|
||||
auto p = reinterpret_cast<char*>(arena_->Alloc(size + 1, 1));
|
||||
std::memcpy(p, value.buffer(), size);
|
||||
p[size] = '\0';
|
||||
Instr* i = AppendInstr(OPCODE_COMMENT_info, 0);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2020 Ben Vanik. All rights reserved. *
|
||||
* Copyright 2021 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
@ -75,7 +75,7 @@ class HIRBuilder {
|
|||
template <typename... Args>
|
||||
void CommentFormat(const std::string_view format, const Args&... args) {
|
||||
static const uint32_t kMaxCommentSize = 1024;
|
||||
char* p = reinterpret_cast<char*>(arena_->Alloc(kMaxCommentSize));
|
||||
char* p = reinterpret_cast<char*>(arena_->Alloc(kMaxCommentSize, 1));
|
||||
auto result = fmt::format_to_n(p, kMaxCommentSize - 1, format, args...);
|
||||
p[result.size] = '\0';
|
||||
size_t rewind = kMaxCommentSize - 1 - result.size;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2020 Ben Vanik. All rights reserved. *
|
||||
* Copyright 2021 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
@ -104,8 +104,8 @@ bool PPCHIRBuilder::Emit(GuestFunction* function, uint32_t flags) {
|
|||
// instruction may have a label assigned to it if it hasn't been hit
|
||||
// yet.
|
||||
size_t list_size = instr_count_ * sizeof(void*);
|
||||
instr_offset_list_ = (Instr**)arena_->Alloc(list_size);
|
||||
label_list_ = (Label**)arena_->Alloc(list_size);
|
||||
instr_offset_list_ = (Instr**)arena_->Alloc(list_size, alignof(void*));
|
||||
label_list_ = (Label**)arena_->Alloc(list_size, alignof(void*));
|
||||
std::memset(instr_offset_list_, 0, list_size);
|
||||
std::memset(label_list_, 0, list_size);
|
||||
|
||||
|
@ -244,7 +244,7 @@ void PPCHIRBuilder::AnnotateLabel(uint32_t address, Label* label) {
|
|||
char name_buffer[13];
|
||||
auto format_result = fmt::format_to_n(name_buffer, 12, "loc_{:08X}", address);
|
||||
name_buffer[format_result.size] = '\0';
|
||||
label->name = (char*)arena_->Alloc(sizeof(name_buffer));
|
||||
label->name = (char*)arena_->Alloc(sizeof(name_buffer), 1);
|
||||
memcpy(label->name, name_buffer, sizeof(name_buffer));
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue