BlockOfCode: Detect space remaining

We also clear the code cache when we run out of space.

This closes #111.
This commit is contained in:
MerryMage 2017-12-03 14:32:01 +00:00
parent 80c56aa89d
commit ea4c3292d5
3 changed files with 27 additions and 0 deletions

View file

@ -57,6 +57,25 @@ void BlockOfCode::ClearCache() {
SetCodePtr(near_code_begin); SetCodePtr(near_code_begin);
} }
size_t BlockOfCode::SpaceRemaining() const {
// This function provides an underestimate of near-code-size but that's okay.
// (Why? The maximum size of near code should be measured from near_code_begin, not top_.)
// These are offsets from Xbyak::CodeArray::top_.
std::size_t far_code_offset, near_code_offset;
if (in_far_code) {
near_code_offset = static_cast<const u8*>(near_code_ptr) - getCode();
far_code_offset = getCurr() - getCode();
} else {
near_code_offset = getCurr() - getCode();
far_code_offset = static_cast<const u8*>(far_code_ptr) - getCode();
}
if (far_code_offset > TOTAL_CODE_SIZE)
return 0;
if (near_code_offset > FAR_CODE_OFFSET)
return 0;
return std::min(TOTAL_CODE_SIZE - far_code_offset, FAR_CODE_OFFSET - near_code_offset);
}
size_t BlockOfCode::RunCode(JitState* jit_state, size_t cycles_to_run) const { size_t BlockOfCode::RunCode(JitState* jit_state, size_t cycles_to_run) const {
constexpr size_t max_cycles_to_run = static_cast<size_t>(std::numeric_limits<decltype(jit_state->cycles_remaining)>::max()); constexpr size_t max_cycles_to_run = static_cast<size_t>(std::numeric_limits<decltype(jit_state->cycles_remaining)>::max());
ASSERT(cycles_to_run <= max_cycles_to_run); ASSERT(cycles_to_run <= max_cycles_to_run);

View file

@ -28,6 +28,8 @@ public:
/// Clears this block of code and resets code pointer to beginning. /// Clears this block of code and resets code pointer to beginning.
void ClearCache(); void ClearCache();
/// Calculates how much space is remaining to use. This is the minimum of near code and far code.
size_t SpaceRemaining() const;
/// Runs emulated code for approximately `cycles_to_run` cycles. /// Runs emulated code for approximately `cycles_to_run` cycles.
size_t RunCode(JitState* jit_state, size_t cycles_to_run) const; size_t RunCode(JitState* jit_state, size_t cycles_to_run) const;

View file

@ -141,6 +141,12 @@ private:
if (block) if (block)
return *block; return *block;
constexpr size_t MINIMUM_REMAINING_CODESIZE = 1 * 1024 * 1024;
if (block_of_code.SpaceRemaining() < MINIMUM_REMAINING_CODESIZE) {
invalidate_entire_cache = true;
PerformCacheInvalidation();
}
IR::Block ir_block = Arm::Translate(descriptor, callbacks.memory.ReadCode); IR::Block ir_block = Arm::Translate(descriptor, callbacks.memory.ReadCode);
Optimization::GetSetElimination(ir_block); Optimization::GetSetElimination(ir_block);
Optimization::DeadCodeElimination(ir_block); Optimization::DeadCodeElimination(ir_block);