X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=deps%2Flightrec%2Fblockcache.c;h=d72d64e0033468b35101c9b37d434c0d5f6a71e8;hb=016c6e93f6db684211f5c8b05433cb500715ba50;hp=70c5aebee4edac2a58a936968ba09373a46800c9;hpb=473f5cc63f9942866e01c7c84d151e8157cdb6ee;p=pcsx_rearmed.git diff --git a/deps/lightrec/blockcache.c b/deps/lightrec/blockcache.c index 70c5aebe..d72d64e0 100644 --- a/deps/lightrec/blockcache.c +++ b/deps/lightrec/blockcache.c @@ -7,6 +7,8 @@ #include "debug.h" #include "lightrec-private.h" #include "memmanager.h" +#include "reaper.h" +#include "recompiler.h" #include #include @@ -99,7 +101,7 @@ void lightrec_unregister_block(struct blockcache *cache, struct block *block) } } - pr_err("Block at PC 0x%x is not in cache\n", block->pc); + pr_err("Block at "PC_FMT" is not in cache\n", block->pc); } static bool lightrec_block_is_old(const struct lightrec_state *state, @@ -117,6 +119,7 @@ static void lightrec_free_blocks(struct blockcache *cache, struct block *block, *next; bool outdated = all; unsigned int i; + u8 old_flags; for (i = 0; i < LUT_SIZE; i++) { for (block = cache->lut[i]; block; block = next) { @@ -130,8 +133,16 @@ static void lightrec_free_blocks(struct blockcache *cache, lightrec_block_is_outdated(state, block); } - if (outdated) { - pr_debug("Freeing outdated block at PC 0x%08x\n", block->pc); + if (!outdated) + continue; + + old_flags = block_set_flags(block, BLOCK_IS_DEAD); + + if (!(old_flags & BLOCK_IS_DEAD)) { + if (ENABLE_THREADED_COMPILER) + lightrec_recompiler_remove(state->rec, block); + + pr_debug("Freeing outdated block at "PC_FMT"\n", block->pc); remove_from_code_lut(cache, block); lightrec_unregister_block(cache, block); lightrec_free_block(state, block); @@ -187,11 +198,27 @@ u32 lightrec_calculate_block_hash(const struct block *block) return hash; } +static void lightrec_reset_lut_offset(struct lightrec_state *state, void *d) +{ + u32 pc = (u32)(uintptr_t) d; + struct block *block; + void *addr; + + block = lightrec_find_block(state->block_cache, pc); + if (!block) + return; + + if (block_has_flag(block, BLOCK_IS_DEAD)) + return; + + addr = block->function ?: state->get_next_block; + lut_write(state, lut_offset(pc), addr); +} + bool lightrec_block_is_outdated(struct lightrec_state *state, struct block *block) { u32 offset = lut_offset(block->pc); bool outdated; - void *addr; if (lut_read(state, offset)) return false; @@ -200,12 +227,24 @@ bool lightrec_block_is_outdated(struct lightrec_state *state, struct block *bloc if (likely(!outdated)) { /* The block was marked as outdated, but the content is still * the same */ - if (block->function) - addr = block->function; - else - addr = state->get_next_block; - lut_write(state, offset, addr); + if (ENABLE_THREADED_COMPILER) { + /* + * When compiling a block that covers ours, the threaded + * compiler will set the LUT entries of the various + * entry points. Therefore we cannot write the LUT here, + * as we would risk overwriting the new entry points. + * Leave it to the reaper to re-install the LUT entries. + */ + + lightrec_reaper_add(state->reaper, + lightrec_reset_lut_offset, + (void *)(uintptr_t) block->pc); + } else if (block->function) { + lut_write(state, offset, block->function); + } else { + lut_write(state, offset, state->get_next_block); + } } return outdated;