From 4438b7e93059b4ea2c0c71009f84f26948289cd9 Mon Sep 17 00:00:00 2001 From: Saagar Jha Date: Sun, 14 Jun 2020 14:16:31 -0700 Subject: [PATCH] Put jit_frame directly in cpu_state, saving a copy On CPU-bound code this should be a free 2x speedup --- emu/cpu.h | 6 ++++++ jit/frame.h | 6 ++++-- jit/jit.c | 18 ++++++++---------- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/emu/cpu.h b/emu/cpu.h index 6915048dd1..67a293fd20 100644 --- a/emu/cpu.h +++ b/emu/cpu.h @@ -5,6 +5,7 @@ #include "misc.h" #include "emu/float80.h" #include "emu/memory.h" +#include "jit/frame.h" struct cpu_state; struct tlb; @@ -26,8 +27,13 @@ static_assert(sizeof(union xmm_reg) == 16, "xmm_reg size"); static_assert(sizeof(union mm_reg) == 8, "mm_reg size"); struct cpu_state { + // DO NOT MOVE THIS! + // ...or do, i'm a comment, not a cop + struct jit_frame frame; + struct mem *mem; struct jit *jit; + long cycle; // general registers diff --git a/jit/frame.h b/jit/frame.h index f94e1e494d..73f270a733 100644 --- a/jit/frame.h +++ b/jit/frame.h @@ -1,14 +1,16 @@ -#include "emu/cpu.h" +#ifndef JIT_FRAME_H +#define JIT_FRAME_H // keep in sync with asm #define JIT_RETURN_CACHE_SIZE 4096 #define JIT_RETURN_CACHE_HASH(x) ((x) & 0xFFF0) >> 4) struct jit_frame { - struct cpu_state cpu; void *bp; addr_t value_addr; uint64_t value[2]; // buffer for crosspage crap struct jit_block *last_block; long ret_cache[JIT_RETURN_CACHE_SIZE]; // a map of ip to pointer-to-call-gadget-arguments }; + +#endif diff --git a/jit/jit.c b/jit/jit.c index 3fd7628fcd..422d547da6 100644 --- a/jit/jit.c +++ b/jit/jit.c @@ -158,7 +158,7 @@ static void jit_free_jetsam(struct jit *jit) { } } -int jit_enter(struct jit_block *block, struct jit_frame *frame, struct tlb *tlb); +int jit_enter(struct jit_block *block, struct cpu_state *cpu, struct tlb *tlb); static inline size_t jit_cache_hash(addr_t ip) { return (ip ^ (ip >> 12)) % JIT_CACHE_SIZE; @@ -167,11 +167,11 @@ static inline size_t jit_cache_hash(addr_t ip) { static int cpu_step_to_interrupt(struct cpu_state *cpu, struct tlb *tlb) { struct jit *jit = cpu->mem->jit; struct jit_block *cache[JIT_CACHE_SIZE] = {}; - struct jit_frame frame = {.cpu = *cpu, .ret_cache = {}}; + cpu->frame = (struct jit_frame){}; int interrupt = INT_NONE; while (interrupt == INT_NONE) { - addr_t ip = frame.cpu.eip; + addr_t ip = cpu->eip; size_t cache_index = jit_cache_hash(ip); struct jit_block *block = cache[cache_index]; if (block == NULL || block->addr != ip) { @@ -186,7 +186,7 @@ static int cpu_step_to_interrupt(struct cpu_state *cpu, struct tlb *tlb) { cache[cache_index] = block; unlock(&jit->lock); } - struct jit_block *last_block = frame.last_block; + struct jit_block *last_block = cpu->frame.last_block; if (last_block != NULL && (last_block->jump_ip[0] != NULL || last_block->jump_ip[1] != NULL)) { @@ -205,15 +205,14 @@ static int cpu_step_to_interrupt(struct cpu_state *cpu, struct tlb *tlb) { unlock(&jit->lock); } - frame.last_block = block; + cpu->frame.last_block = block; // block may be jetsam, but that's ok, because it can't be freed until // every thread on this jit is not executing anything TRACE("%d %08x --- cycle %ld\n", current->pid, ip, cpu->cycle); - interrupt = jit_enter(block, &frame, tlb); - *cpu = frame.cpu; + interrupt = jit_enter(block, cpu, tlb); if (interrupt == INT_NONE && ++cpu->cycle % (1 << 10) == 0) interrupt = INT_TIMER; } @@ -229,9 +228,8 @@ static int cpu_single_step(struct cpu_state *cpu, struct tlb *tlb) { gen_end(&state); struct jit_block *block = state.block; - struct jit_frame frame = {.cpu = *cpu}; - int interrupt = jit_enter(block, &frame, tlb); - *cpu = frame.cpu; + cpu->frame = (struct jit_frame){}; + int interrupt = jit_enter(block, cpu, tlb); jit_block_free(NULL, block); if (interrupt == INT_NONE) interrupt = INT_DEBUG;