Browse Source

Fix 32-bit wrap-around for profiler and opstats

Fabian 2 years ago
parent
commit
199b1ceb49

+ 1 - 1
Makefile

@@ -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

+ 1 - 1
src/rust/codegen.rs

@@ -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) {

+ 26 - 16
src/rust/cpu/cpu.rs

@@ -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

+ 0 - 6
src/rust/cpu/global_pointers.rs

@@ -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

+ 1 - 1
src/rust/jit.rs

@@ -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);

+ 32 - 15
src/rust/opstats.rs

@@ -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 }
 }

+ 1 - 1
src/rust/profiler.rs

@@ -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); }

+ 6 - 5
src/rust/wasmgen/wasm_builder.rs

@@ -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); }