[A64] Add thread-safe atomics to A64Function
Also adds some bounds check to LookupFunction. Co-Authored-By: Reality <reality@xenios.jp>
This commit is contained in:
@@ -26,18 +26,19 @@ A64Function::~A64Function() {
|
||||
}
|
||||
|
||||
void A64Function::Setup(uint8_t* machine_code, size_t machine_code_length) {
|
||||
machine_code_ = machine_code;
|
||||
machine_code_length_ = machine_code_length;
|
||||
machine_code_length_.store(machine_code_length, std::memory_order_relaxed);
|
||||
machine_code_.store(machine_code, std::memory_order_release);
|
||||
}
|
||||
|
||||
bool A64Function::CallImpl(ThreadState* thread_state, uint32_t return_address) {
|
||||
auto backend =
|
||||
reinterpret_cast<A64Backend*>(thread_state->processor()->backend());
|
||||
auto thunk = backend->host_to_guest_thunk();
|
||||
if (!thunk || !machine_code_) {
|
||||
auto* code = machine_code_.load(std::memory_order_acquire);
|
||||
if (!thunk || !code) {
|
||||
return false;
|
||||
}
|
||||
thunk(machine_code_, thread_state->context(),
|
||||
thunk(code, thread_state->context(),
|
||||
reinterpret_cast<void*>(uintptr_t(return_address)));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#ifndef XENIA_CPU_BACKEND_A64_A64_FUNCTION_H_
|
||||
#define XENIA_CPU_BACKEND_A64_A64_FUNCTION_H_
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include "xenia/cpu/function.h"
|
||||
#include "xenia/cpu/thread_state.h"
|
||||
|
||||
@@ -23,8 +25,12 @@ class A64Function : public GuestFunction {
|
||||
A64Function(Module* module, uint32_t address);
|
||||
~A64Function() override;
|
||||
|
||||
uint8_t* machine_code() const override { return machine_code_; }
|
||||
size_t machine_code_length() const override { return machine_code_length_; }
|
||||
uint8_t* machine_code() const override {
|
||||
return machine_code_.load(std::memory_order_acquire);
|
||||
}
|
||||
size_t machine_code_length() const override {
|
||||
return machine_code_length_.load(std::memory_order_acquire);
|
||||
}
|
||||
|
||||
void Setup(uint8_t* machine_code, size_t machine_code_length);
|
||||
|
||||
@@ -32,8 +38,8 @@ class A64Function : public GuestFunction {
|
||||
bool CallImpl(ThreadState* thread_state, uint32_t return_address) override;
|
||||
|
||||
private:
|
||||
uint8_t* machine_code_ = nullptr;
|
||||
size_t machine_code_length_ = 0;
|
||||
std::atomic<uint8_t*> machine_code_{nullptr};
|
||||
std::atomic<size_t> machine_code_length_{0};
|
||||
};
|
||||
|
||||
} // namespace a64
|
||||
|
||||
@@ -234,7 +234,15 @@ class CodeCacheBase : public CodeCache {
|
||||
}
|
||||
|
||||
GuestFunction* LookupFunction(uint64_t host_pc) override {
|
||||
uint32_t key = uint32_t(host_pc - kGeneratedCodeExecuteBase);
|
||||
if (generated_code_map_.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
const uint64_t code_base = execute_base_address();
|
||||
const uint64_t code_end = code_base + total_size();
|
||||
if (host_pc < code_base || host_pc >= code_end) {
|
||||
return nullptr;
|
||||
}
|
||||
uint32_t key = uint32_t(host_pc - code_base);
|
||||
void* fn_entry = std::bsearch(
|
||||
&key, generated_code_map_.data(), generated_code_map_.size(),
|
||||
sizeof(std::pair<uint32_t, Function*>),
|
||||
|
||||
Reference in New Issue
Block a user