Fix 32-bit wrap-around for profiler and opstats

This commit is contained in:
Fabian 2021-05-17 18:25:54 -05:00
parent 1b06e7bd34
commit 199b1ceb49
8 changed files with 68 additions and 46 deletions

View file

@ -69,7 +69,7 @@ CARGO_FLAGS_SAFE=\
--target wasm32-unknown-unknown \
-- \
-C linker=tools/rust-lld-wrapper \
-C link-args="--import-table --global-base=262144 $(STRIP_DEBUG_FLAG)" \
-C link-args="--import-table --global-base=4096 $(STRIP_DEBUG_FLAG)" \
-C link-args="build/softfloat.o" \
-C link-args="build/zstddeclib.o" \
--verbose

View file

@ -2252,7 +2252,7 @@ pub fn gen_profiler_stat_increment(builder: &mut WasmBuilder, stat: profiler::st
return;
}
let addr = unsafe { profiler::stat_array.as_mut_ptr().offset(stat as isize) } as u32;
builder.increment_fixed_i32(addr, 1)
builder.increment_fixed_i64(addr, 1)
}
pub fn gen_debug_track_jit_exit(builder: &mut WasmBuilder, address: u32) {

View file

@ -3784,6 +3784,7 @@ pub unsafe fn vm86_mode() -> bool { return *flags & FLAG_VM == FLAG_VM; }
pub unsafe fn getiopl() -> i32 { return *flags >> 12 & 3; }
#[no_mangle]
#[cfg(feature = "profiler")]
pub unsafe fn get_opstats_buffer(
compiled: bool,
jit_exit: bool,
@ -3793,25 +3794,34 @@ pub unsafe fn get_opstats_buffer(
is_0f: bool,
is_mem: bool,
fixed_g: u8,
) -> u32 {
let index = (is_0f as u32) << 12 | (opcode as u32) << 4 | (is_mem as u32) << 3 | fixed_g as u32;
if compiled {
*opstats_compiled_buffer.offset(index as isize)
}
else if jit_exit {
*opstats_jit_exit_buffer.offset(index as isize)
}
else if unguarded_register {
*opstats_unguarded_register_buffer.offset(index as isize)
}
else if wasm_size {
*opstats_wasm_size.offset(index as isize)
}
else {
*opstats_buffer.offset(index as isize)
) -> f64 {
{
let index = (is_0f as usize) << 12
| (opcode as usize) << 4
| (is_mem as usize) << 3
| fixed_g as usize;
(if compiled {
::opstats::opstats_compiled_buffer[index]
}
else if jit_exit {
::opstats::opstats_jit_exit_buffer[index]
}
else if unguarded_register {
::opstats::opstats_unguarded_register_buffer[index]
}
else if wasm_size {
::opstats::opstats_wasm_size[index]
}
else {
::opstats::opstats_buffer[index]
}) as f64
}
}
#[no_mangle]
#[cfg(not(feature = "profiler"))]
pub unsafe fn get_opstats_buffer() -> f64 { 0.0 }
pub unsafe fn invlpg(addr: i32) {
let page = (addr as u32 >> 12) as i32;
// Note: Doesn't remove this page from valid_tlb_entries: This isn't

View file

@ -67,12 +67,6 @@ pub const sse_scratch_register: *mut reg128 = 1136 as *mut reg128;
pub const fpu_st: *mut F80 = 1152 as *mut F80;
pub const opstats_buffer: *mut u32 = 0x08000 as *mut u32;
pub const opstats_compiled_buffer: *mut u32 = 0x10000 as *mut u32;
pub const opstats_jit_exit_buffer: *mut u32 = 0x18000 as *mut u32;
pub const opstats_unguarded_register_buffer: *mut u32 = 0x20000 as *mut u32;
pub const opstats_wasm_size: *mut u32 = 0x28000 as *mut u32;
pub fn get_reg32_offset(r: u32) -> u32 {
dbg_assert!(r < 8);
(unsafe { reg32.offset(r as isize) }) as u32

View file

@ -1856,7 +1856,7 @@ fn jit_generate_basic_block(ctx: &mut JitContext, block: &BasicBlock) {
let was_block_boundary = instruction_flags & JIT_INSTR_BLOCK_BOUNDARY_FLAG != 0;
let wasm_length = ctx.builder.instruction_body_length() - wasm_length_before;
opstats::record_opstat_size_wasm(instruction, wasm_length as u32);
opstats::record_opstat_size_wasm(instruction, wasm_length as u64);
dbg_assert!((end_eip == stop_addr) == (start_eip == last_instruction_addr));
dbg_assert!(instruction_length < MAX_INSTRUCTION_LENGTH);

View file

@ -1,7 +1,18 @@
use cpu;
use cpu::global_pointers;
use wasmgen::wasm_builder::WasmBuilder;
const SIZE: usize = if cfg!(feature = "profiler") { 8192 } else { 0 };
#[allow(non_upper_case_globals)]
pub static mut opstats_buffer: [u64; SIZE] = [0; SIZE];
#[allow(non_upper_case_globals)]
pub static mut opstats_compiled_buffer: [u64; SIZE] = [0; SIZE];
#[allow(non_upper_case_globals)]
pub static mut opstats_jit_exit_buffer: [u64; SIZE] = [0; SIZE];
#[allow(non_upper_case_globals)]
pub static mut opstats_unguarded_register_buffer: [u64; SIZE] = [0; SIZE];
#[allow(non_upper_case_globals)]
pub static mut opstats_wasm_size: [u64; SIZE] = [0; SIZE];
pub struct Instruction {
pub prefixes: Vec<u8>,
pub opcode: u8,
@ -134,7 +145,10 @@ pub fn gen_opstats(builder: &mut WasmBuilder, opcode: u32) {
for prefix in instruction.prefixes {
let index = (prefix as u32) << 4;
builder.increment_fixed_i32(global_pointers::opstats_buffer as u32 + 4 * index, 1);
builder.increment_fixed_i64(
unsafe { &mut opstats_buffer[index as usize] as *mut _ } as u32,
1,
);
}
let index = (instruction.is_0f as u32) << 12
@ -142,7 +156,10 @@ pub fn gen_opstats(builder: &mut WasmBuilder, opcode: u32) {
| (instruction.is_mem as u32) << 3
| instruction.fixed_g as u32;
builder.increment_fixed_i32(global_pointers::opstats_buffer as u32 + 4 * index, 1);
builder.increment_fixed_i64(
unsafe { &mut opstats_buffer[index as usize] as *mut _ } as u32,
1,
);
}
pub fn record_opstat_compiled(opcode: u32) {
@ -154,7 +171,7 @@ pub fn record_opstat_compiled(opcode: u32) {
for prefix in instruction.prefixes {
let index = (prefix as u32) << 4;
unsafe { *cpu::global_pointers::opstats_compiled_buffer.offset(index as isize) += 1 }
unsafe { opstats_compiled_buffer[index as usize] += 1 }
}
let index = (instruction.is_0f as u32) << 12
@ -162,7 +179,7 @@ pub fn record_opstat_compiled(opcode: u32) {
| (instruction.is_mem as u32) << 3
| instruction.fixed_g as u32;
unsafe { *cpu::global_pointers::opstats_compiled_buffer.offset(index as isize) += 1 }
unsafe { opstats_compiled_buffer[index as usize] += 1 }
}
pub fn record_opstat_jit_exit(opcode: u32) {
@ -174,7 +191,7 @@ pub fn record_opstat_jit_exit(opcode: u32) {
for prefix in instruction.prefixes {
let index = (prefix as u32) << 4;
unsafe { *cpu::global_pointers::opstats_jit_exit_buffer.offset(index as isize) += 1 }
unsafe { opstats_jit_exit_buffer[index as usize] += 1 }
}
let index = (instruction.is_0f as u32) << 12
@ -182,7 +199,7 @@ pub fn record_opstat_jit_exit(opcode: u32) {
| (instruction.is_mem as u32) << 3
| instruction.fixed_g as u32;
unsafe { *cpu::global_pointers::opstats_jit_exit_buffer.offset(index as isize) += 1 }
unsafe { opstats_jit_exit_buffer[index as usize] += 1 }
}
pub fn gen_opstat_unguarded_register(builder: &mut WasmBuilder, opcode: u32) {
@ -194,8 +211,8 @@ pub fn gen_opstat_unguarded_register(builder: &mut WasmBuilder, opcode: u32) {
for prefix in instruction.prefixes {
let index = (prefix as u32) << 4;
builder.increment_fixed_i32(
global_pointers::opstats_unguarded_register_buffer as u32 + 4 * index,
builder.increment_fixed_i64(
unsafe { &mut opstats_unguarded_register_buffer[index as usize] as *mut _ } as u32,
1,
);
}
@ -205,13 +222,13 @@ pub fn gen_opstat_unguarded_register(builder: &mut WasmBuilder, opcode: u32) {
| (instruction.is_mem as u32) << 3
| instruction.fixed_g as u32;
builder.increment_fixed_i32(
global_pointers::opstats_unguarded_register_buffer as u32 + 4 * index,
builder.increment_fixed_i64(
unsafe { &mut opstats_unguarded_register_buffer[index as usize] as *mut _ } as u32,
1,
);
}
pub fn record_opstat_size_wasm(opcode: u32, size: u32) {
pub fn record_opstat_size_wasm(opcode: u32, size: u64) {
if !cfg!(feature = "profiler") {
return;
}
@ -220,7 +237,7 @@ pub fn record_opstat_size_wasm(opcode: u32, size: u32) {
for prefix in instruction.prefixes {
let index = (prefix as u32) << 4;
unsafe { *cpu::global_pointers::opstats_wasm_size.offset(index as isize) += size }
unsafe { opstats_wasm_size[index as usize] += size }
}
let index = (instruction.is_0f as u32) << 12
@ -228,5 +245,5 @@ pub fn record_opstat_size_wasm(opcode: u32, size: u32) {
| (instruction.is_mem as u32) << 3
| instruction.fixed_g as u32;
unsafe { *cpu::global_pointers::opstats_wasm_size.offset(index as isize) += size }
unsafe { opstats_wasm_size[index as usize] += size }
}

View file

@ -112,7 +112,7 @@ pub enum stat {
SEG_OFFSET_NOT_OPTIMISED,
}
#[no_mangle]
#[allow(non_upper_case_globals)]
pub static mut stat_array: [u64; 500] = [0; 500];
pub fn stat_increment(stat: stat) { stat_increment_by(stat, 1); }

View file

@ -761,15 +761,16 @@ impl WasmBuilder {
write_leb_u32(&mut self.instruction_body, byte_offset);
}
pub fn increment_fixed_i32(&mut self, byte_offset: u32, n: i32) {
pub fn increment_fixed_i64(&mut self, byte_offset: u32, n: i64) {
self.const_i32(byte_offset as i32);
self.load_fixed_i32(byte_offset);
self.const_i32(n);
self.add_i32();
self.store_aligned_i32(0);
self.load_fixed_i64(byte_offset);
self.const_i64(n);
self.add_i64();
self.store_aligned_i64(0);
}
pub fn add_i32(&mut self) { self.instruction_body.push(op::OP_I32ADD); }
pub fn add_i64(&mut self) { self.instruction_body.push(op::OP_I64ADD); }
pub fn sub_i32(&mut self) { self.instruction_body.push(op::OP_I32SUB); }
pub fn and_i32(&mut self) { self.instruction_body.push(op::OP_I32AND); }
pub fn or_i32(&mut self) { self.instruction_body.push(op::OP_I32OR); }