profiler: Keep track of fast/slow path for jitted memory access
This commit is contained in:
parent
b70a5c081a
commit
bf895ff1b2
|
@ -30,18 +30,18 @@ const print_stats = {
|
|||
"RUN_FROM_CACHE",
|
||||
"RUN_FROM_CACHE_STEPS",
|
||||
"TRIGGER_CPU_EXCEPTION",
|
||||
"SAFE_READ32_FAST",
|
||||
"SAFE_READ32_SLOW_PAGE_CROSSED",
|
||||
"SAFE_READ32_SLOW_NOT_VALID",
|
||||
"SAFE_READ32_SLOW_NOT_USER",
|
||||
"SAFE_READ32_SLOW_IN_MAPPED_RANGE",
|
||||
"SAFE_WRITE32_FAST",
|
||||
"SAFE_WRITE32_SLOW_PAGE_CROSSED",
|
||||
"SAFE_WRITE32_SLOW_NOT_VALID",
|
||||
"SAFE_WRITE32_SLOW_NOT_USER",
|
||||
"SAFE_WRITE32_SLOW_IN_MAPPED_RANGE",
|
||||
"SAFE_WRITE32_SLOW_READ_ONLY",
|
||||
"SAFE_WRITE32_SLOW_HAS_CODE",
|
||||
"SAFE_READ_FAST",
|
||||
"SAFE_READ_SLOW_PAGE_CROSSED",
|
||||
"SAFE_READ_SLOW_NOT_VALID",
|
||||
"SAFE_READ_SLOW_NOT_USER",
|
||||
"SAFE_READ_SLOW_IN_MAPPED_RANGE",
|
||||
"SAFE_WRITE_FAST",
|
||||
"SAFE_WRITE_SLOW_PAGE_CROSSED",
|
||||
"SAFE_WRITE_SLOW_NOT_VALID",
|
||||
"SAFE_WRITE_SLOW_NOT_USER",
|
||||
"SAFE_WRITE_SLOW_IN_MAPPED_RANGE",
|
||||
"SAFE_WRITE_SLOW_READ_ONLY",
|
||||
"SAFE_WRITE_SLOW_HAS_CODE",
|
||||
"DO_RUN",
|
||||
"DO_MANY_CYCLES",
|
||||
"CYCLE_INTERNAL",
|
||||
|
|
|
@ -2,6 +2,7 @@ use cpu::BitSize;
|
|||
use global_pointers;
|
||||
use jit::JitContext;
|
||||
use modrm;
|
||||
use profiler;
|
||||
use regs;
|
||||
use tlb::{TLB_GLOBAL, TLB_HAS_CODE, TLB_NO_USER, TLB_READONLY, TLB_VALID};
|
||||
use wasmgen::module_init;
|
||||
|
@ -281,6 +282,11 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize) {
|
|||
// Pseudo:
|
||||
// if(can_use_fast_path) leave_on_stack(mem8[entry & ~0xFFF ^ address]);
|
||||
builder.instruction_body.if_i32();
|
||||
|
||||
if cfg!(feature = "profiler") {
|
||||
gen_profiler_stat_increment(builder, profiler::stat::S_SAFE_READ_FAST);
|
||||
}
|
||||
|
||||
builder.instruction_body.get_local(&entry_local);
|
||||
builder.instruction_body.const_i32(!0xFFF);
|
||||
builder.instruction_body.and_i32();
|
||||
|
@ -313,6 +319,12 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize) {
|
|||
// }
|
||||
builder.instruction_body.else_();
|
||||
|
||||
if cfg!(feature = "profiler") {
|
||||
builder.instruction_body.get_local(&address_local);
|
||||
builder.instruction_body.get_local(&entry_local);
|
||||
gen_call_fn2(builder, "report_safe_read_jit_slow");
|
||||
}
|
||||
|
||||
builder
|
||||
.instruction_body
|
||||
.const_i32(global_pointers::PREVIOUS_IP as i32);
|
||||
|
@ -410,14 +422,16 @@ fn gen_safe_write(
|
|||
// phys_addr = entry & ~0xFFF ^ address;
|
||||
builder.instruction_body.if_void();
|
||||
|
||||
if cfg!(feature = "profiler") {
|
||||
gen_profiler_stat_increment(builder, profiler::stat::S_SAFE_WRITE_FAST);
|
||||
}
|
||||
|
||||
builder.instruction_body.get_local(&entry_local);
|
||||
builder.instruction_body.const_i32(!0xFFF);
|
||||
builder.instruction_body.and_i32();
|
||||
builder.instruction_body.get_local(&address_local);
|
||||
builder.instruction_body.xor_i32();
|
||||
|
||||
builder.free_local(entry_local);
|
||||
|
||||
// Pseudo:
|
||||
// /* continued within can_use_fast_path branch */
|
||||
// mem8[phys_addr] = value;
|
||||
|
@ -447,6 +461,12 @@ fn gen_safe_write(
|
|||
// }
|
||||
builder.instruction_body.else_();
|
||||
|
||||
if cfg!(feature = "profiler") {
|
||||
builder.instruction_body.get_local(&address_local);
|
||||
builder.instruction_body.get_local(&entry_local);
|
||||
gen_call_fn2(builder, "report_safe_write_jit_slow");
|
||||
}
|
||||
|
||||
builder
|
||||
.instruction_body
|
||||
.const_i32(global_pointers::PREVIOUS_IP as i32);
|
||||
|
@ -486,6 +506,8 @@ fn gen_safe_write(
|
|||
builder.instruction_body.block_end();
|
||||
|
||||
builder.instruction_body.block_end();
|
||||
|
||||
builder.free_local(entry_local);
|
||||
}
|
||||
|
||||
pub fn gen_clear_prefixes(ctx: &mut JitContext) {
|
||||
|
@ -840,6 +862,11 @@ pub fn gen_safe_read_write(
|
|||
// Pseudo:
|
||||
// if(can_use_fast_path) leave_on_stack(mem8[entry & ~0xFFF ^ address]);
|
||||
ctx.builder.instruction_body.if_void();
|
||||
|
||||
if cfg!(feature = "profiler") {
|
||||
gen_profiler_stat_increment(ctx.builder, profiler::stat::S_SAFE_WRITE_FAST);
|
||||
}
|
||||
|
||||
ctx.builder.instruction_body.get_local(&entry_local);
|
||||
ctx.builder.instruction_body.const_i32(!0xFFF);
|
||||
ctx.builder.instruction_body.and_i32();
|
||||
|
@ -864,8 +891,6 @@ pub fn gen_safe_read_write(
|
|||
},
|
||||
}
|
||||
|
||||
ctx.builder.free_local(entry_local);
|
||||
|
||||
f(ctx);
|
||||
|
||||
match bits {
|
||||
|
@ -891,6 +916,12 @@ pub fn gen_safe_read_write(
|
|||
// }
|
||||
ctx.builder.instruction_body.else_();
|
||||
|
||||
if cfg!(feature = "profiler") {
|
||||
ctx.builder.instruction_body.get_local(&address_local);
|
||||
ctx.builder.instruction_body.get_local(&entry_local);
|
||||
gen_call_fn2(ctx.builder, "report_safe_write_jit_slow");
|
||||
}
|
||||
|
||||
ctx.builder
|
||||
.instruction_body
|
||||
.const_i32(global_pointers::PREVIOUS_IP as i32);
|
||||
|
@ -920,4 +951,11 @@ pub fn gen_safe_read_write(
|
|||
ctx.builder.instruction_body.block_end();
|
||||
|
||||
ctx.builder.instruction_body.block_end();
|
||||
|
||||
ctx.builder.free_local(entry_local);
|
||||
}
|
||||
|
||||
pub fn gen_profiler_stat_increment(builder: &mut WasmBuilder, stat: profiler::stat) {
|
||||
let addr = unsafe { profiler::stat_array.as_mut_ptr().offset(stat as isize) } as u32;
|
||||
gen_increment_variable(builder, addr, 1)
|
||||
}
|
||||
|
|
|
@ -1060,7 +1060,7 @@ pub unsafe fn safe_read32s(mut address: i32) -> Result<i32, ()> {
|
|||
let mut info_bits: i32 = entry & 4095 & !TLB_READONLY & !TLB_GLOBAL & !TLB_HAS_CODE;
|
||||
if info_bits == TLB_VALID && address & 4095 <= 4096 - 4 {
|
||||
if false {
|
||||
profiler::stat_increment(S_SAFE_READ32_FAST);
|
||||
profiler::stat_increment(S_SAFE_READ_FAST);
|
||||
}
|
||||
// - not in memory mapped area
|
||||
// - can be accessed from any cpl
|
||||
|
@ -1071,16 +1071,16 @@ pub unsafe fn safe_read32s(mut address: i32) -> Result<i32, ()> {
|
|||
else {
|
||||
if false {
|
||||
if address & 4095 > 4096 - 4 {
|
||||
profiler::stat_increment(S_SAFE_READ32_SLOW_PAGE_CROSSED);
|
||||
profiler::stat_increment(S_SAFE_READ_SLOW_PAGE_CROSSED);
|
||||
}
|
||||
else if info_bits & TLB_VALID == 0 {
|
||||
profiler::stat_increment(S_SAFE_READ32_SLOW_NOT_VALID);
|
||||
profiler::stat_increment(S_SAFE_READ_SLOW_NOT_VALID);
|
||||
}
|
||||
else if 0 != info_bits & TLB_NO_USER {
|
||||
profiler::stat_increment(S_SAFE_READ32_SLOW_NOT_USER);
|
||||
profiler::stat_increment(S_SAFE_READ_SLOW_NOT_USER);
|
||||
}
|
||||
else if 0 != info_bits & TLB_IN_MAPPED_RANGE {
|
||||
profiler::stat_increment(S_SAFE_READ32_SLOW_IN_MAPPED_RANGE);
|
||||
profiler::stat_increment(S_SAFE_READ_SLOW_IN_MAPPED_RANGE);
|
||||
}
|
||||
else {
|
||||
dbg_assert!(0 != 0);
|
||||
|
@ -1090,6 +1090,48 @@ pub unsafe fn safe_read32s(mut address: i32) -> Result<i32, ()> {
|
|||
};
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[cfg(feature = "profiler")]
|
||||
pub fn report_safe_read_jit_slow(address: u32, entry: i32) {
|
||||
if entry & TLB_VALID == 0 {
|
||||
profiler::stat_increment(S_SAFE_READ_SLOW_NOT_VALID);
|
||||
}
|
||||
else if entry & TLB_IN_MAPPED_RANGE != 0 {
|
||||
profiler::stat_increment(S_SAFE_READ_SLOW_IN_MAPPED_RANGE);
|
||||
}
|
||||
else if address & 0xFFF > 0x1000 - 4 {
|
||||
profiler::stat_increment(S_SAFE_READ_SLOW_PAGE_CROSSED);
|
||||
}
|
||||
else {
|
||||
// NOT_USER is not possible since gen_safe_read generates a mask for cpl0
|
||||
dbg_assert!(false);
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[cfg(feature = "profiler")]
|
||||
pub fn report_safe_write_jit_slow(address: u32, entry: i32) {
|
||||
if entry & TLB_VALID == 0 {
|
||||
profiler::stat_increment(S_SAFE_WRITE_SLOW_NOT_VALID);
|
||||
}
|
||||
else if entry & TLB_IN_MAPPED_RANGE != 0 {
|
||||
profiler::stat_increment(S_SAFE_WRITE_SLOW_IN_MAPPED_RANGE);
|
||||
}
|
||||
else if entry & TLB_HAS_CODE != 0 {
|
||||
profiler::stat_increment(S_SAFE_WRITE_SLOW_HAS_CODE);
|
||||
}
|
||||
else if entry & TLB_READONLY != 0 {
|
||||
profiler::stat_increment(S_SAFE_WRITE_SLOW_READ_ONLY);
|
||||
}
|
||||
else if address & 0xFFF > 0x1000 - 4 {
|
||||
profiler::stat_increment(S_SAFE_WRITE_SLOW_PAGE_CROSSED);
|
||||
}
|
||||
else {
|
||||
// NOT_USER is not possible since gen_safe_write generates a mask for for cpl0
|
||||
dbg_assert!(false);
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn safe_read32s_slow(mut addr: i32) -> Result<i32, ()> {
|
||||
if addr & 4095 >= 4093 {
|
||||
return Ok(safe_read16(addr)? | safe_read16(addr + 2)? << 16);
|
||||
|
@ -1210,7 +1252,7 @@ pub unsafe fn safe_write32(mut address: i32, mut value: i32) -> Result<(), ()> {
|
|||
entry & 4095 & !TLB_GLOBAL & !if *cpl as i32 == 3 { 0 } else { TLB_NO_USER };
|
||||
if info_bits == TLB_VALID && address & 4095 <= 4096 - 4 {
|
||||
if false {
|
||||
profiler::stat_increment(S_SAFE_WRITE32_FAST);
|
||||
profiler::stat_increment(S_SAFE_WRITE_FAST);
|
||||
}
|
||||
// - allowed to write in user-mode
|
||||
// - not in memory mapped area
|
||||
|
@ -1223,22 +1265,22 @@ pub unsafe fn safe_write32(mut address: i32, mut value: i32) -> Result<(), ()> {
|
|||
else {
|
||||
if false {
|
||||
if address & 4095 > 4096 - 4 {
|
||||
profiler::stat_increment(S_SAFE_WRITE32_SLOW_PAGE_CROSSED);
|
||||
profiler::stat_increment(S_SAFE_WRITE_SLOW_PAGE_CROSSED);
|
||||
}
|
||||
else if info_bits & TLB_VALID == 0 {
|
||||
profiler::stat_increment(S_SAFE_WRITE32_SLOW_NOT_VALID);
|
||||
profiler::stat_increment(S_SAFE_WRITE_SLOW_NOT_VALID);
|
||||
}
|
||||
else if 0 != info_bits & TLB_NO_USER {
|
||||
profiler::stat_increment(S_SAFE_WRITE32_SLOW_NOT_USER);
|
||||
profiler::stat_increment(S_SAFE_WRITE_SLOW_NOT_USER);
|
||||
}
|
||||
else if 0 != info_bits & TLB_IN_MAPPED_RANGE {
|
||||
profiler::stat_increment(S_SAFE_WRITE32_SLOW_IN_MAPPED_RANGE);
|
||||
profiler::stat_increment(S_SAFE_WRITE_SLOW_IN_MAPPED_RANGE);
|
||||
}
|
||||
else if 0 != info_bits & TLB_READONLY {
|
||||
profiler::stat_increment(S_SAFE_WRITE32_SLOW_READ_ONLY);
|
||||
profiler::stat_increment(S_SAFE_WRITE_SLOW_READ_ONLY);
|
||||
}
|
||||
else if 0 != info_bits & TLB_HAS_CODE {
|
||||
profiler::stat_increment(S_SAFE_WRITE32_SLOW_HAS_CODE);
|
||||
profiler::stat_increment(S_SAFE_WRITE_SLOW_HAS_CODE);
|
||||
}
|
||||
else {
|
||||
dbg_assert!(0 != 0);
|
||||
|
|
|
@ -20,19 +20,19 @@ pub enum stat {
|
|||
|
||||
S_TRIGGER_CPU_EXCEPTION,
|
||||
|
||||
S_SAFE_READ32_FAST,
|
||||
S_SAFE_READ32_SLOW_PAGE_CROSSED,
|
||||
S_SAFE_READ32_SLOW_NOT_VALID,
|
||||
S_SAFE_READ32_SLOW_NOT_USER,
|
||||
S_SAFE_READ32_SLOW_IN_MAPPED_RANGE,
|
||||
S_SAFE_READ_FAST,
|
||||
S_SAFE_READ_SLOW_PAGE_CROSSED,
|
||||
S_SAFE_READ_SLOW_NOT_VALID,
|
||||
S_SAFE_READ_SLOW_NOT_USER,
|
||||
S_SAFE_READ_SLOW_IN_MAPPED_RANGE,
|
||||
|
||||
S_SAFE_WRITE32_FAST,
|
||||
S_SAFE_WRITE32_SLOW_PAGE_CROSSED,
|
||||
S_SAFE_WRITE32_SLOW_NOT_VALID,
|
||||
S_SAFE_WRITE32_SLOW_NOT_USER,
|
||||
S_SAFE_WRITE32_SLOW_IN_MAPPED_RANGE,
|
||||
S_SAFE_WRITE32_SLOW_READ_ONLY,
|
||||
S_SAFE_WRITE32_SLOW_HAS_CODE,
|
||||
S_SAFE_WRITE_FAST,
|
||||
S_SAFE_WRITE_SLOW_PAGE_CROSSED,
|
||||
S_SAFE_WRITE_SLOW_NOT_VALID,
|
||||
S_SAFE_WRITE_SLOW_NOT_USER,
|
||||
S_SAFE_WRITE_SLOW_IN_MAPPED_RANGE,
|
||||
S_SAFE_WRITE_SLOW_READ_ONLY,
|
||||
S_SAFE_WRITE_SLOW_HAS_CODE,
|
||||
|
||||
S_DO_RUN,
|
||||
S_DO_MANY_CYCLES,
|
||||
|
|
Loading…
Reference in a new issue