@@ -11,7 +11,7 @@ use crate::memory::Memory;
11
11
use crate :: { Error , ISA_A , ISA_B , ISA_MOP , RISCV_PAGESIZE } ;
12
12
13
13
const RISCV_PAGESIZE_MASK : u64 = RISCV_PAGESIZE as u64 - 1 ;
14
- const INSTRUCTION_CACHE_SIZE : usize = 2048 ;
14
+ const INSTRUCTION_CACHE_SIZE : usize = 4096 ;
15
15
16
16
pub trait InstDecoder {
17
17
fn decode < M : Memory > ( & mut self , memory : & mut M , pc : u64 ) -> Result < Instruction , Error > ;
@@ -105,14 +105,14 @@ impl Decoder {
105
105
let instruction_cache_key = {
106
106
// according to RISC-V instruction encoding, the lowest bit in PC will always be zero
107
107
let pc = pc >> 1 ;
108
- // This indexing strategy optimizes instruction cache utilization by improving the distribution of addresses.
109
- // - `pc >> 5`: Incorporates higher bits to ensure a more even spread across cache indices.
110
- // - `pc << 1`: Spreads lower-bit information into higher positions, enhancing variability.
111
- // - `^` (XOR): Further randomizes index distribution, reducing cache conflicts and improving hit rates.
112
- //
113
- // This approach helps balance cache efficiency between local execution and remote function calls,
114
- // reducing hotspots and improving overall performance .
115
- ( ( pc >> 5 ) ^ ( pc << 1 ) ) as usize % INSTRUCTION_CACHE_SIZE
108
+ // Here we try to balance between local code and remote code. At times,
109
+ // we can find the code jumping to a remote function(e.g., memcpy or
110
+ // alloc), then resumes execution at a local location. Previous cache
111
+ // key only optimizes for local operations, while this new cache key
112
+ // balances the code between a 8192-byte local region, and certain remote
113
+ // code region. Notice the value 12 and 8 here are chosen by empirical
114
+ // evidence .
115
+ ( ( pc & 0xFF ) | ( pc >> 12 << 8 ) ) as usize % INSTRUCTION_CACHE_SIZE
116
116
} ;
117
117
let cached_instruction = self . instructions_cache [ instruction_cache_key] ;
118
118
if cached_instruction. 0 == pc {
0 commit comments