Don't create unnecessary entry points

This commit prevents creation of entry points for jumps within the same
page. In interpreted mode, execution is continued on these kinds of
jumps.

Since this prevents the old hotness detection from working efficiently,
hotness detection has also been changed to work based on instruction
counters, and is such more precise (longer basic blocks are compiled
earlier).

This also breaks the old detection loop safety mechanism and causes
Linux to sometimes loop forever on "calibrating delay loop", so
JIT_ALWAYS_USE_LOOP_SAFETY has been set to 1.
This commit is contained in:
Fabian 2018-09-17 18:34:10 -05:00
parent afcce9b371
commit 0798a0b40e
16 changed files with 559 additions and 380 deletions

View file

@ -226,7 +226,11 @@ function gen_instruction_body_after_prefix(encodings, size)
function gen_instruction_body_after_fixed_g(encoding, size)
{
const instruction_prefix = [];
const instruction_postfix = encoding.block_boundary || (!encoding.custom && encoding.e) || encoding.sse || encoding.task_switch_test ? ["after_block_boundary();"] : [];
const instruction_postfix =
(encoding.block_boundary && !encoding.no_block_boundary_in_interpreted) ||
(!encoding.custom && encoding.e) ||
encoding.sse ||
encoding.task_switch_test ? ["after_block_boundary();"] : [];
if(encoding.task_switch_test || encoding.sse)
{

View file

@ -11,8 +11,38 @@ const af = 1 << 4;
const pf = 1 << 2;
const sf = 1 << 7;
// TODO:
// - describe which registers are written and read
// === Types of instructions
//
// create entry | check for compiled code | instruction
// -------------+-------------------------+-----------------------------------------------------------
// 1 | optional | pop ds (may change cpu state)
// | | trigger_ud, div (exception that doesn't generate conditional return from BB)
// | | port io, popf, sti (may call interrupt or continue at next instruction)
// | | hlt
// -------------+-------------------------+-----------------------------------------------------------
// 1 | 1 | call [eax], jmp [eax], int, iret, ret, jmpf, callf, sysenter, sysexit
// | | Special case: normal instruction with fallthough to next page
// | | Special case: after execution of compiled code
// | | -> may create redundant entry points depending on last instruction?
// -------------+-------------------------+-----------------------------------------------------------
// 1 | 0 | rep movs, rep lods, rep stos, rep cmps, rep scas
// | | -> Executed as follows:
// | | - Upto including the first call in compiled mode
// | | - Back to main loop and repeated in interpreted mode (as entry point is after instruction, not on)
// | | - When finished entry pointer *after* instruction is hit and execution continues in compiled mode
// -------------+-------------------------+-----------------------------------------------------------
// 0 | optional | jmp foo, jnz foo
// | | (foo is in the same page as the instruction)
// -------------+-------------------------+-----------------------------------------------------------
// 1 | 1 | call foo
// | | (foo is in the same page as the instruction)
// | | -> The entry point is not created for jumps within
// | | this page, but speculatively for calls from
// | | other pages to the function in this page
// -------------+-------------------------+-----------------------------------------------------------
// 1 | 1 | call foo, jmp foo, jnz foo
// | | (foo is in a different page than the instruction)
// os: the instruction behaves differently depending on the operand size
const encodings = [
@ -177,6 +207,7 @@ const encodings = [
{ opcode: 0xA3, custom: 1, os: 1, immaddr: 1 },
// string instructions aren't jumps, but they modify eip due to how they're implemented
// TODO: The block_boundary on the non-rep instructions can be removed once they're custom
{ opcode: 0xA4, block_boundary: 1, is_string: 1, },
{ opcode: 0xF2A4, block_boundary: 1, is_string: 1, },
{ opcode: 0xF3A4, block_boundary: 1, is_string: 1, },
@ -257,9 +288,9 @@ const encodings = [
{ opcode: 0xE7, block_boundary: 1, os: 1, imm8: 1, skip: 1, },
{ opcode: 0xE8, block_boundary: 1, jump_offset_imm: 1, os: 1, imm1632: 1, custom: 1, skip: 1, }, // call
{ opcode: 0xE9, block_boundary: 1, jump_offset_imm: 1, no_next_instruction: 1, os: 1, imm1632: 1, custom: 1, skip: 1, },
{ opcode: 0xE9, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, no_next_instruction: 1, os: 1, imm1632: 1, custom: 1, skip: 1, },
{ opcode: 0xEA, block_boundary: 1, no_next_instruction: 1, os: 1, imm1632: 1, extra_imm16: 1, skip: 1, }, // jmpf
{ opcode: 0xEB, block_boundary: 1, jump_offset_imm: 1, no_next_instruction: 1, os: 1, imm8s: 1, custom: 1, skip: 1, },
{ opcode: 0xEB, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, no_next_instruction: 1, os: 1, imm8s: 1, custom: 1, skip: 1, },
{ opcode: 0xEC, block_boundary: 1, skip: 1, }, // in
{ opcode: 0xED, block_boundary: 1, os: 1, skip: 1, },
@ -399,22 +430,22 @@ const encodings = [
{ opcode: 0x0F4E, e: 1, os: 1, custom: 1, },
{ opcode: 0x0F4F, e: 1, os: 1, custom: 1, },
{ opcode: 0x0F80, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, },
{ opcode: 0x0F81, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, },
{ opcode: 0x0F82, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, },
{ opcode: 0x0F83, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, },
{ opcode: 0x0F84, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, },
{ opcode: 0x0F85, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, },
{ opcode: 0x0F86, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, },
{ opcode: 0x0F87, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, },
{ opcode: 0x0F88, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, },
{ opcode: 0x0F89, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, },
{ opcode: 0x0F8A, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, },
{ opcode: 0x0F8B, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, },
{ opcode: 0x0F8C, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, },
{ opcode: 0x0F8D, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, },
{ opcode: 0x0F8E, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, },
{ opcode: 0x0F8F, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, },
{ opcode: 0x0F80, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, },
{ opcode: 0x0F81, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, },
{ opcode: 0x0F82, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, },
{ opcode: 0x0F83, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, },
{ opcode: 0x0F84, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, },
{ opcode: 0x0F85, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, },
{ opcode: 0x0F86, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, },
{ opcode: 0x0F87, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, },
{ opcode: 0x0F88, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, },
{ opcode: 0x0F89, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, },
{ opcode: 0x0F8A, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, },
{ opcode: 0x0F8B, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, },
{ opcode: 0x0F8C, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, },
{ opcode: 0x0F8D, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, },
{ opcode: 0x0F8E, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, },
{ opcode: 0x0F8F, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, },
{ opcode: 0x0F90, e: 1, custom: 1, },
{ opcode: 0x0F91, e: 1, custom: 1, },
@ -842,8 +873,8 @@ for(let i = 0; i < 8; i++)
{ opcode: 0x04 | i << 3, eax: 1, imm8: 1, },
{ opcode: 0x05 | i << 3, os: 1, eax: 1, imm1632: 1, },
{ opcode: 0x70 | i, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, os: 1, imm8s: 1, custom: 1, skip: 1, },
{ opcode: 0x78 | i, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, os: 1, imm8s: 1, custom: 1, skip: 1, },
{ opcode: 0x70 | i, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, conditional_jump: 1, os: 1, imm8s: 1, custom: 1, skip: 1, },
{ opcode: 0x78 | i, block_boundary: 1, no_block_boundary_in_interpreted: 1, jump_offset_imm: 1, conditional_jump: 1, os: 1, imm8s: 1, custom: 1, skip: 1, },
{ opcode: 0x80, e: 1, fixed_g: i, imm8: 1, custom: 1, },
{ opcode: 0x81, os: 1, e: 1, fixed_g: i, imm1632: 1, custom: 1, },

View file

@ -8,7 +8,7 @@ use state_flags::CachedStateFlags;
static mut MODULE_PTR: NonNull<JitState> =
unsafe { NonNull::new_unchecked(mem::align_of::<JitState>() as *mut _) };
fn get_module<'a>() -> &'a mut JitState { unsafe { MODULE_PTR.as_mut() } }
pub fn get_module<'a>() -> &'a mut JitState { unsafe { MODULE_PTR.as_mut() } }
#[no_mangle]
/// Called from JS, not C
@ -52,12 +52,18 @@ pub fn codegen_finalize_finished(
)
}
pub fn jit_increase_hotness_and_maybe_compile(phys_address: u32, cs_offset: u32, state_flags: u32) {
pub fn jit_increase_hotness_and_maybe_compile(
phys_address: u32,
cs_offset: u32,
state_flags: u32,
hotness: u32,
) {
::jit::jit_increase_hotness_and_maybe_compile(
get_module(),
phys_address,
cs_offset,
CachedStateFlags::of_u32(state_flags),
hotness,
)
}

View file

@ -68,6 +68,7 @@ pub union reg128 {
}
pub const CHECK_MISSED_ENTRY_POINTS: bool = false;
pub const INTERPRETER_ITERATION_LIMIT: u32 = 1000;
pub const FLAG_CARRY: i32 = 1;
pub const FLAG_PARITY: i32 = 4;
@ -1088,6 +1089,8 @@ pub unsafe fn cycle_internal() {
);
}
else {
::jit::record_entry_point(::c_api::get_module(), phys_addr);
#[cfg(feature = "profiler")]
{
if CHECK_MISSED_ENTRY_POINTS {
@ -1099,17 +1102,20 @@ pub unsafe fn cycle_internal() {
dbg_assert!(!must_not_fault);
must_not_fault = true
}
::c_api::jit_increase_hotness_and_maybe_compile(
phys_addr,
get_seg_cs() as u32,
state_flags as u32,
);
if DEBUG {
dbg_assert!(must_not_fault);
must_not_fault = false
}
let initial_tsc = *timestamp_counter;
jit_run_interpreted(phys_addr as i32);
::c_api::jit_increase_hotness_and_maybe_compile(
phys_addr,
get_seg_cs() as u32,
state_flags as u32,
*timestamp_counter - initial_tsc,
);
profiler::stat_increment_by(
S_RUN_INTERPRETED_STEPS,
(*timestamp_counter - initial_tsc) as u64,
@ -1118,6 +1124,7 @@ pub unsafe fn cycle_internal() {
}
else {
*previous_ip = *instruction_pointer;
let opcode = return_on_pagefault!(read_imm8());
*timestamp_counter += 1;
dbg_assert!(*prefixes == 0);
@ -1155,7 +1162,15 @@ unsafe fn jit_run_interpreted(phys_addr: i32) {
run_instruction(opcode | (*is_32 as i32) << 8);
dbg_assert!(*prefixes == 0);
while !jit_block_boundary && 0 != same_page(*previous_ip, *instruction_pointer) as i32 {
// We need to limit the number of iterations here as jumps within the same page are not counted
// as block boundaries for the interpreter (as they don't create an entry point and don't need
// a check if the jump target may have compiled code)
let mut i = 0;
while !jit_block_boundary
&& same_page(*previous_ip, *instruction_pointer)
&& i < INTERPRETER_ITERATION_LIMIT
{
*previous_ip = *instruction_pointer;
let opcode = return_on_pagefault!(read_imm8());
@ -1190,6 +1205,8 @@ unsafe fn jit_run_interpreted(phys_addr: i32) {
dbg_assert!(*prefixes == 0);
run_instruction(opcode | (*is_32 as i32) << 8);
dbg_assert!(*prefixes == 0);
i += 1;
}
}

View file

@ -22,9 +22,9 @@ pub const CHECK_JIT_CACHE_ARRAY_INVARIANTS: bool = false;
pub const JIT_MAX_ITERATIONS_PER_FUNCTION: u32 = 10000;
pub const JIT_ALWAYS_USE_LOOP_SAFETY: bool = false;
pub const JIT_ALWAYS_USE_LOOP_SAFETY: bool = true;
pub const JIT_THRESHOLD: u32 = 10 * 2500;
pub const JIT_THRESHOLD: u32 = 8 * 10000;
const CONDITION_FUNCTIONS: [&str; 16] = [
"test_o", "test_no", "test_b", "test_nb", "test_z", "test_nz", "test_be", "test_nbe", "test_s",
@ -433,7 +433,7 @@ pub fn jit_find_cache_entry(phys_address: u32, state_flags: CachedStateFlags) ->
cached_code::NONE
}
fn record_entry_point(ctx: &mut JitState, phys_address: u32) {
pub fn record_entry_point(ctx: &mut JitState, phys_address: u32) {
if is_near_end_of_page(phys_address) {
return;
}
@ -1174,11 +1174,11 @@ pub fn jit_increase_hotness_and_maybe_compile(
phys_address: u32,
cs_offset: u32,
state_flags: CachedStateFlags,
hotness: u32,
) {
record_entry_point(ctx, phys_address);
let page = Page::page_of(phys_address);
let address_hash = jit_hot_hash_page(page) as usize;
ctx.hot_code_addresses[address_hash] += 1;
ctx.hot_code_addresses[address_hash] += hotness;
if ctx.hot_code_addresses[address_hash] >= JIT_THRESHOLD {
ctx.hot_code_addresses[address_hash] = 0;
jit_analyze_and_generate(ctx, page, cs_offset, state_flags)

View file

@ -13,15 +13,26 @@
(import "e" "safe_read32s_slow_jit" (func $e.safe_read32s_slow_jit (type $t5)))
(import "e" "m" (memory $e.m 256))
(func $f (export "f") (type $t1) (param $p0 i32)
(local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32)
(local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32)
(set_local $p0
(get_local $p0))
(set_local $l0
(i32.const 10000))
(loop $L0
(block $B1
(block $B2
(block $B3
(block $B4
(br_table $B4 $B3 $B2 $B1
(set_local $l0
(i32.add
(get_local $l0)
(i32.const -1)))
(if $I1
(i32.eqz
(get_local $l0))
(then
(return)))
(block $B2
(block $B3
(block $B4
(block $B5
(br_table $B5 $B4 $B3 $B2
(get_local $p0)))
(i32.store
(i32.const 560)
@ -33,47 +44,47 @@
(i32.load
(i32.const 556))
(i32.const 5)))
(set_local $l0
(set_local $l1
(i32.sub
(i32.load
(i32.const 556))
(i32.load
(i32.const 740))))
(set_local $l2
(set_local $l3
(i32.add
(tee_local $l1
(tee_local $l2
(i32.sub
(i32.load
(i32.const 20))
(i32.const 4)))
(i32.load
(i32.const 744))))
(if $I5
(if $I6
(i32.and
(i32.eq
(i32.and
(tee_local $l3
(tee_local $l4
(i32.load offset=4194304
(i32.shl
(i32.shr_u
(get_local $l2)
(get_local $l3)
(i32.const 12))
(i32.const 2))))
(i32.const 4075))
(i32.const 1))
(i32.le_s
(i32.and
(get_local $l2)
(get_local $l3)
(i32.const 4095))
(i32.const 4092)))
(then
(i32.store offset=20221952 align=1
(i32.xor
(i32.and
(get_local $l3)
(get_local $l4)
(i32.const -4096))
(get_local $l2))
(get_local $l0)))
(get_local $l3))
(get_local $l1)))
(else
(i32.store
(i32.const 560)
@ -84,16 +95,16 @@
(i32.const -4096))
(i32.const 0)))
(call $e.safe_write32_slow_jit
(get_local $l2)
(get_local $l0))
(if $I6
(get_local $l3)
(get_local $l1))
(if $I7
(i32.load8_u
(i32.const 540))
(then
(return)))))
(i32.store
(i32.const 20)
(get_local $l1))
(get_local $l2))
(i32.store
(i32.const 556)
(i32.add
@ -143,17 +154,17 @@
(i32.const 556)
(i32.load
(i32.const 740))
(if $I7 (result i32)
(if $I8 (result i32)
(i32.and
(i32.eq
(i32.and
(tee_local $l2
(tee_local $l3
(i32.load offset=4194304
(i32.shl
(i32.shr_u
(tee_local $l1
(tee_local $l2
(i32.add
(tee_local $l0
(tee_local $l1
(i32.load
(i32.const 20)))
(i32.load
@ -164,16 +175,16 @@
(i32.const 1))
(i32.le_s
(i32.and
(get_local $l1)
(get_local $l2)
(i32.const 4095))
(i32.const 4092)))
(then
(i32.load offset=20221952 align=1
(i32.xor
(i32.and
(get_local $l2)
(get_local $l3)
(i32.const -4096))
(get_local $l1))))
(get_local $l2))))
(else
(i32.store
(i32.const 560)
@ -184,8 +195,8 @@
(i32.const -4096))
(i32.const 7)))
(call $e.safe_read32s_slow_jit
(get_local $l1))
(if $I8
(get_local $l2))
(if $I9
(i32.load8_u
(i32.const 540))
(then
@ -193,7 +204,7 @@
(i32.store
(i32.const 20)
(i32.add
(get_local $l0)
(get_local $l1)
(i32.const 4)))
(i32.add)
(i32.store)

View file

@ -14,15 +14,26 @@
(import "e" "instr_F4" (func $e.instr_F4 (type $t0)))
(import "e" "m" (memory $e.m 256))
(func $f (export "f") (type $t1) (param $p0 i32)
(local $l0 i32)
(local $l0 i32) (local $l1 i32)
(set_local $p0
(get_local $p0))
(set_local $l0
(i32.const 10000))
(loop $L0
(block $B1
(block $B2
(block $B3
(block $B4
(br_table $B4 $B3 $B2 $B1
(set_local $l0
(i32.add
(get_local $l0)
(i32.const -1)))
(if $I1
(i32.eqz
(get_local $l0))
(then
(return)))
(block $B2
(block $B3
(block $B4
(block $B5
(br_table $B5 $B4 $B3 $B2
(get_local $p0)))
(call $e.cmp32
(i32.load
@ -46,7 +57,7 @@
(i32.load
(i32.const 664))
(i32.const 2)))
(if $I5
(if $I6
(call $e.test_nle)
(then
(i32.store

View file

@ -11,14 +11,25 @@
(import "e" "instr_F4" (func $e.instr_F4 (type $t0)))
(import "e" "m" (memory $e.m 256))
(func $f (export "f") (type $t1) (param $p0 i32)
(local $l0 i32)
(local $l0 i32) (local $l1 i32)
(set_local $p0
(get_local $p0))
(set_local $l0
(i32.const 10000))
(loop $L0
(block $B1
(block $B2
(block $B3
(br_table $B3 $B2 $B1
(set_local $l0
(i32.add
(get_local $l0)
(i32.const -1)))
(if $I1
(i32.eqz
(get_local $l0))
(then
(return)))
(block $B2
(block $B3
(block $B4
(br_table $B4 $B3 $B2
(get_local $p0)))
(i32.store
(i32.const 560)

View file

@ -13,76 +13,40 @@
(import "e" "instr_F4" (func $e.instr_F4 (type $t0)))
(import "e" "m" (memory $e.m 256))
(func $f (export "f") (type $t1) (param $p0 i32)
(local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32)
(local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32)
(set_local $p0
(get_local $p0))
(set_local $l0
(i32.const 10000))
(loop $L0
(block $B1
(block $B2
(br_table $B2 $B1
(set_local $l0
(i32.add
(get_local $l0)
(i32.const -1)))
(if $I1
(i32.eqz
(get_local $l0))
(then
(return)))
(block $B2
(block $B3
(br_table $B3 $B2
(get_local $p0)))
(call $e.instr16_B8
(i32.const 51966))
(i32.store16
(i32.const 8)
(if $I3 (result i32)
(if $I4 (result i32)
(i32.and
(i32.eq
(i32.and
(tee_local $l1
(i32.load offset=4194304
(i32.shl
(i32.shr_u
(tee_local $l0
(i32.add
(i32.const 32)
(call $e.get_seg
(i32.const 3))))
(i32.const 12))
(i32.const 2))))
(i32.const 4041))
(i32.const 1))
(i32.le_s
(i32.and
(get_local $l0)
(i32.const 4095))
(i32.const 4094)))
(then
(i32.load16_u offset=20221952 align=1
(i32.xor
(i32.and
(get_local $l1)
(i32.const -4096))
(get_local $l0))))
(else
(i32.store
(i32.const 560)
(i32.or
(i32.and
(i32.load
(i32.const 556))
(i32.const -4096))
(i32.const 3)))
(call $e.safe_read16_slow_jit
(get_local $l0))
(if $I4
(i32.load8_u
(i32.const 540))
(then
(return))))))
(i32.store16
(i32.const 12)
(if $I5 (result i32)
(i32.and
(i32.eq
(i32.and
(tee_local $l0
(tee_local $l2
(i32.load offset=4194304
(i32.shl
(i32.shr_u
(tee_local $l1
(i32.add
(i32.const 36)
(i32.const 32)
(call $e.get_seg
(i32.const 3))))
(i32.const 12))
@ -98,7 +62,7 @@
(i32.load16_u offset=20221952 align=1
(i32.xor
(i32.and
(get_local $l0)
(get_local $l2)
(i32.const -4096))
(get_local $l1))))
(else
@ -109,10 +73,57 @@
(i32.load
(i32.const 556))
(i32.const -4096))
(i32.const 7)))
(i32.const 3)))
(call $e.safe_read16_slow_jit
(get_local $l1))
(if $I6
(if $I5
(i32.load8_u
(i32.const 540))
(then
(return))))))
(i32.store16
(i32.const 12)
(if $I6 (result i32)
(i32.and
(i32.eq
(i32.and
(tee_local $l1
(i32.load offset=4194304
(i32.shl
(i32.shr_u
(tee_local $l2
(i32.add
(i32.const 36)
(call $e.get_seg
(i32.const 3))))
(i32.const 12))
(i32.const 2))))
(i32.const 4041))
(i32.const 1))
(i32.le_s
(i32.and
(get_local $l2)
(i32.const 4095))
(i32.const 4094)))
(then
(i32.load16_u offset=20221952 align=1
(i32.xor
(i32.and
(get_local $l1)
(i32.const -4096))
(get_local $l2))))
(else
(i32.store
(i32.const 560)
(i32.or
(i32.and
(i32.load
(i32.const 556))
(i32.const -4096))
(i32.const 7)))
(call $e.safe_read16_slow_jit
(get_local $l2))
(if $I7
(i32.load8_u
(i32.const 540))
(then
@ -123,7 +134,7 @@
(i32.store16
(i32.const 28)
(i32.const 32))
(set_local $l0
(set_local $l1
(i32.add
(i32.and
(i32.add
@ -134,71 +145,14 @@
(i32.const 65535))
(call $e.get_seg
(i32.const 3))))
(set_local $l1
(set_local $l2
(i32.load16_u
(i32.const 4)))
(if $I7
(if $I8
(i32.and
(i32.eq
(i32.and
(tee_local $l2
(i32.load offset=4194304
(i32.shl
(i32.shr_u
(get_local $l0)
(i32.const 12))
(i32.const 2))))
(i32.const 4075))
(i32.const 1))
(i32.le_s
(i32.and
(get_local $l0)
(i32.const 4095))
(i32.const 4094)))
(then
(i32.store16 offset=20221952 align=1
(i32.xor
(i32.and
(get_local $l2)
(i32.const -4096))
(get_local $l0))
(get_local $l1)))
(else
(i32.store
(i32.const 560)
(i32.or
(i32.and
(i32.load
(i32.const 556))
(i32.const -4096))
(i32.const 19)))
(call $e.safe_write16_slow_jit
(get_local $l0)
(get_local $l1))
(if $I8
(i32.load8_u
(i32.const 540))
(then
(return)))))
(set_local $l1
(i32.add
(i32.and
(i32.add
(i32.load16_u
(i32.const 16))
(i32.load16_u
(i32.const 28)))
(i32.const 65535))
(call $e.get_seg
(i32.const 3))))
(set_local $l0
(i32.load16_u
(i32.const 8)))
(if $I9
(i32.and
(i32.eq
(i32.and
(tee_local $l2
(tee_local $l3
(i32.load offset=4194304
(i32.shl
(i32.shr_u
@ -216,10 +170,67 @@
(i32.store16 offset=20221952 align=1
(i32.xor
(i32.and
(get_local $l2)
(get_local $l3)
(i32.const -4096))
(get_local $l1))
(get_local $l0)))
(get_local $l2)))
(else
(i32.store
(i32.const 560)
(i32.or
(i32.and
(i32.load
(i32.const 556))
(i32.const -4096))
(i32.const 19)))
(call $e.safe_write16_slow_jit
(get_local $l1)
(get_local $l2))
(if $I9
(i32.load8_u
(i32.const 540))
(then
(return)))))
(set_local $l2
(i32.add
(i32.and
(i32.add
(i32.load16_u
(i32.const 16))
(i32.load16_u
(i32.const 28)))
(i32.const 65535))
(call $e.get_seg
(i32.const 3))))
(set_local $l1
(i32.load16_u
(i32.const 8)))
(if $I10
(i32.and
(i32.eq
(i32.and
(tee_local $l3
(i32.load offset=4194304
(i32.shl
(i32.shr_u
(get_local $l2)
(i32.const 12))
(i32.const 2))))
(i32.const 4075))
(i32.const 1))
(i32.le_s
(i32.and
(get_local $l2)
(i32.const 4095))
(i32.const 4094)))
(then
(i32.store16 offset=20221952 align=1
(i32.xor
(i32.and
(get_local $l3)
(i32.const -4096))
(get_local $l2))
(get_local $l1)))
(else
(i32.store
(i32.const 560)
@ -230,9 +241,9 @@
(i32.const -4096))
(i32.const 21)))
(call $e.safe_write16_slow_jit
(get_local $l1)
(get_local $l0))
(if $I10
(get_local $l2)
(get_local $l1))
(if $I11
(i32.load8_u
(i32.const 540))
(then

View file

@ -12,15 +12,26 @@
(import "e" "instr_F4" (func $e.instr_F4 (type $t0)))
(import "e" "m" (memory $e.m 256))
(func $f (export "f") (type $t1) (param $p0 i32)
(local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32)
(local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32)
(set_local $p0
(get_local $p0))
(set_local $l0
(i32.const 10000))
(loop $L0
(block $B1
(block $B2
(br_table $B2 $B1
(set_local $l0
(i32.add
(get_local $l0)
(i32.const -1)))
(if $I1
(i32.eqz
(get_local $l0))
(then
(return)))
(block $B2
(block $B3
(br_table $B3 $B2
(get_local $p0)))
(set_local $l0
(set_local $l1
(i32.add
(i32.add
(i32.load
@ -28,68 +39,14 @@
(i32.const 32))
(call $e.get_seg
(i32.const 3))))
(set_local $l1
(set_local $l2
(i32.load
(i32.const 4)))
(if $I3
(if $I4
(i32.and
(i32.eq
(i32.and
(tee_local $l2
(i32.load offset=4194304
(i32.shl
(i32.shr_u
(get_local $l0)
(i32.const 12))
(i32.const 2))))
(i32.const 4075))
(i32.const 1))
(i32.le_s
(i32.and
(get_local $l0)
(i32.const 4095))
(i32.const 4092)))
(then
(i32.store offset=20221952 align=1
(i32.xor
(i32.and
(get_local $l2)
(i32.const -4096))
(get_local $l0))
(get_local $l1)))
(else
(i32.store
(i32.const 560)
(i32.or
(i32.and
(i32.load
(i32.const 556))
(i32.const -4096))
(i32.const 0)))
(call $e.safe_write32_slow_jit
(get_local $l0)
(get_local $l1))
(if $I4
(i32.load8_u
(i32.const 540))
(then
(return)))))
(set_local $l1
(i32.add
(i32.add
(i32.load
(i32.const 12))
(i32.const 28))
(call $e.get_seg
(i32.const 3))))
(set_local $l0
(i32.load
(i32.const 8)))
(if $I5
(i32.and
(i32.eq
(i32.and
(tee_local $l2
(tee_local $l3
(i32.load offset=4194304
(i32.shl
(i32.shr_u
@ -107,10 +64,64 @@
(i32.store offset=20221952 align=1
(i32.xor
(i32.and
(get_local $l2)
(get_local $l3)
(i32.const -4096))
(get_local $l1))
(get_local $l0)))
(get_local $l2)))
(else
(i32.store
(i32.const 560)
(i32.or
(i32.and
(i32.load
(i32.const 556))
(i32.const -4096))
(i32.const 0)))
(call $e.safe_write32_slow_jit
(get_local $l1)
(get_local $l2))
(if $I5
(i32.load8_u
(i32.const 540))
(then
(return)))))
(set_local $l2
(i32.add
(i32.add
(i32.load
(i32.const 12))
(i32.const 28))
(call $e.get_seg
(i32.const 3))))
(set_local $l1
(i32.load
(i32.const 8)))
(if $I6
(i32.and
(i32.eq
(i32.and
(tee_local $l3
(i32.load offset=4194304
(i32.shl
(i32.shr_u
(get_local $l2)
(i32.const 12))
(i32.const 2))))
(i32.const 4075))
(i32.const 1))
(i32.le_s
(i32.and
(get_local $l2)
(i32.const 4095))
(i32.const 4092)))
(then
(i32.store offset=20221952 align=1
(i32.xor
(i32.and
(get_local $l3)
(i32.const -4096))
(get_local $l2))
(get_local $l1)))
(else
(i32.store
(i32.const 560)
@ -121,70 +132,20 @@
(i32.const -4096))
(i32.const 6)))
(call $e.safe_write32_slow_jit
(get_local $l1)
(get_local $l0))
(if $I6
(get_local $l2)
(get_local $l1))
(if $I7
(i32.load8_u
(i32.const 540))
(then
(return)))))
(i32.store
(i32.const 28)
(if $I7 (result i32)
(if $I8 (result i32)
(i32.and
(i32.eq
(i32.and
(tee_local $l1
(i32.load offset=4194304
(i32.shl
(i32.shr_u
(tee_local $l0
(i32.add
(i32.add
(i32.load
(i32.const 16))
(i32.const 28))
(call $e.get_seg
(i32.const 3))))
(i32.const 12))
(i32.const 2))))
(i32.const 4041))
(i32.const 1))
(i32.le_s
(i32.and
(get_local $l0)
(i32.const 4095))
(i32.const 4092)))
(then
(i32.load offset=20221952 align=1
(i32.xor
(i32.and
(get_local $l1)
(i32.const -4096))
(get_local $l0))))
(else
(i32.store
(i32.const 560)
(i32.or
(i32.and
(i32.load
(i32.const 556))
(i32.const -4096))
(i32.const 12)))
(call $e.safe_read32s_slow_jit
(get_local $l0))
(if $I8
(i32.load8_u
(i32.const 540))
(then
(return))))))
(i32.store
(i32.const 32)
(if $I9 (result i32)
(i32.and
(i32.eq
(i32.and
(tee_local $l0
(tee_local $l2
(i32.load offset=4194304
(i32.shl
(i32.shr_u
@ -192,8 +153,8 @@
(i32.add
(i32.add
(i32.load
(i32.const 12))
(i32.const 32))
(i32.const 16))
(i32.const 28))
(call $e.get_seg
(i32.const 3))))
(i32.const 12))
@ -209,7 +170,7 @@
(i32.load offset=20221952 align=1
(i32.xor
(i32.and
(get_local $l0)
(get_local $l2)
(i32.const -4096))
(get_local $l1))))
(else
@ -220,10 +181,60 @@
(i32.load
(i32.const 556))
(i32.const -4096))
(i32.const 18)))
(i32.const 12)))
(call $e.safe_read32s_slow_jit
(get_local $l1))
(if $I10
(if $I9
(i32.load8_u
(i32.const 540))
(then
(return))))))
(i32.store
(i32.const 32)
(if $I10 (result i32)
(i32.and
(i32.eq
(i32.and
(tee_local $l1
(i32.load offset=4194304
(i32.shl
(i32.shr_u
(tee_local $l2
(i32.add
(i32.add
(i32.load
(i32.const 12))
(i32.const 32))
(call $e.get_seg
(i32.const 3))))
(i32.const 12))
(i32.const 2))))
(i32.const 4041))
(i32.const 1))
(i32.le_s
(i32.and
(get_local $l2)
(i32.const 4095))
(i32.const 4092)))
(then
(i32.load offset=20221952 align=1
(i32.xor
(i32.and
(get_local $l1)
(i32.const -4096))
(get_local $l2))))
(else
(i32.store
(i32.const 560)
(i32.or
(i32.and
(i32.load
(i32.const 556))
(i32.const -4096))
(i32.const 18)))
(call $e.safe_read32s_slow_jit
(get_local $l2))
(if $I11
(i32.load8_u
(i32.const 540))
(then

View file

@ -14,13 +14,24 @@
(import "e" "instr_F4" (func $e.instr_F4 (type $t0)))
(import "e" "m" (memory $e.m 256))
(func $f (export "f") (type $t1) (param $p0 i32)
(local $l0 i32)
(local $l0 i32) (local $l1 i32)
(set_local $p0
(get_local $p0))
(set_local $l0
(i32.const 10000))
(loop $L0
(block $B1
(block $B2
(br_table $B2 $B1
(set_local $l0
(i32.add
(get_local $l0)
(i32.const -1)))
(if $I1
(i32.eqz
(get_local $l0))
(then
(return)))
(block $B2
(block $B3
(br_table $B3 $B2
(get_local $p0)))
(call $e.instr32_B8
(i32.const -889270259))

View file

@ -11,26 +11,37 @@
(import "e" "instr_F4" (func $e.instr_F4 (type $t0)))
(import "e" "m" (memory $e.m 256))
(func $f (export "f") (type $t1) (param $p0 i32)
(local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32)
(local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32)
(set_local $p0
(get_local $p0))
(set_local $l0
(i32.const 10000))
(loop $L0
(block $B1
(block $B2
(br_table $B2 $B1
(set_local $l0
(i32.add
(get_local $l0)
(i32.const -1)))
(if $I1
(i32.eqz
(get_local $l0))
(then
(return)))
(block $B2
(block $B3
(br_table $B3 $B2
(get_local $p0)))
(i32.const 4)
(if $I3 (result i32)
(if $I4 (result i32)
(i32.and
(i32.eq
(i32.and
(tee_local $l2
(tee_local $l3
(i32.load offset=4194304
(i32.shl
(i32.shr_u
(tee_local $l1
(tee_local $l2
(i32.add
(tee_local $l0
(tee_local $l1
(i32.load
(i32.const 20)))
(i32.load
@ -41,16 +52,16 @@
(i32.const 1))
(i32.le_s
(i32.and
(get_local $l1)
(get_local $l2)
(i32.const 4095))
(i32.const 4092)))
(then
(i32.load offset=20221952 align=1
(i32.xor
(i32.and
(get_local $l2)
(get_local $l3)
(i32.const -4096))
(get_local $l1))))
(get_local $l2))))
(else
(i32.store
(i32.const 560)
@ -61,8 +72,8 @@
(i32.const -4096))
(i32.const 0)))
(call $e.safe_read32s_slow_jit
(get_local $l1))
(if $I4
(get_local $l2))
(if $I5
(i32.load8_u
(i32.const 540))
(then
@ -70,7 +81,7 @@
(i32.store
(i32.const 20)
(i32.add
(get_local $l0)
(get_local $l1)
(i32.const 4)))
(i32.store)
(i32.store

View file

@ -11,52 +11,63 @@
(import "e" "instr_F4" (func $e.instr_F4 (type $t0)))
(import "e" "m" (memory $e.m 256))
(func $f (export "f") (type $t1) (param $p0 i32)
(local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32)
(local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 i32)
(set_local $p0
(get_local $p0))
(set_local $l0
(i32.const 10000))
(loop $L0
(block $B1
(block $B2
(br_table $B2 $B1
(set_local $l0
(i32.add
(get_local $l0)
(i32.const -1)))
(if $I1
(i32.eqz
(get_local $l0))
(then
(return)))
(block $B2
(block $B3
(br_table $B3 $B2
(get_local $p0)))
(set_local $l0
(set_local $l1
(i32.load
(i32.const 4)))
(set_local $l2
(set_local $l3
(i32.add
(tee_local $l1
(tee_local $l2
(i32.sub
(i32.load
(i32.const 20))
(i32.const 4)))
(i32.load
(i32.const 744))))
(if $I3
(if $I4
(i32.and
(i32.eq
(i32.and
(tee_local $l3
(tee_local $l4
(i32.load offset=4194304
(i32.shl
(i32.shr_u
(get_local $l2)
(get_local $l3)
(i32.const 12))
(i32.const 2))))
(i32.const 4075))
(i32.const 1))
(i32.le_s
(i32.and
(get_local $l2)
(get_local $l3)
(i32.const 4095))
(i32.const 4092)))
(then
(i32.store offset=20221952 align=1
(i32.xor
(i32.and
(get_local $l3)
(get_local $l4)
(i32.const -4096))
(get_local $l2))
(get_local $l0)))
(get_local $l3))
(get_local $l1)))
(else
(i32.store
(i32.const 560)
@ -67,16 +78,16 @@
(i32.const -4096))
(i32.const 0)))
(call $e.safe_write32_slow_jit
(get_local $l2)
(get_local $l0))
(if $I4
(get_local $l3)
(get_local $l1))
(if $I5
(i32.load8_u
(i32.const 540))
(then
(return)))))
(i32.store
(i32.const 20)
(get_local $l1))
(get_local $l2))
(i32.store
(i32.const 560)
(i32.add

View file

@ -12,14 +12,25 @@
(import "e" "instr_F4" (func $e.instr_F4 (type $t0)))
(import "e" "m" (memory $e.m 256))
(func $f (export "f") (type $t1) (param $p0 i32)
(local $l0 i32)
(local $l0 i32) (local $l1 i32)
(set_local $p0
(get_local $p0))
(set_local $l0
(i32.const 10000))
(loop $L0
(block $B1
(block $B2
(block $B3
(br_table $B3 $B2 $B1
(set_local $l0
(i32.add
(get_local $l0)
(i32.const -1)))
(if $I1
(i32.eqz
(get_local $l0))
(then
(return)))
(block $B2
(block $B3
(block $B4
(br_table $B4 $B3 $B2
(get_local $p0)))
(i32.store
(i32.const 560)
@ -31,7 +42,7 @@
(i32.load
(i32.const 556))
(i32.const 2)))
(if $I4
(if $I5
(i32.and
(i32.load
(i32.const 580))

View file

@ -12,14 +12,25 @@
(import "e" "instr_F4" (func $e.instr_F4 (type $t0)))
(import "e" "m" (memory $e.m 256))
(func $f (export "f") (type $t1) (param $p0 i32)
(local $l0 i32)
(local $l0 i32) (local $l1 i32)
(set_local $p0
(get_local $p0))
(set_local $l0
(i32.const 10000))
(loop $L0
(block $B1
(block $B2
(block $B3
(br_table $B3 $B2 $B1
(set_local $l0
(i32.add
(get_local $l0)
(i32.const -1)))
(if $I1
(i32.eqz
(get_local $l0))
(then
(return)))
(block $B2
(block $B3
(block $B4
(br_table $B4 $B3 $B2
(get_local $p0)))
(i32.store
(i32.const 560)
@ -37,7 +48,7 @@
(i32.load
(i32.const 648))
(i32.const 32)))
(if $I4
(if $I5
(i32.and
(i32.load
(i32.const 580))

View file

@ -13,15 +13,26 @@
(import "e" "instr_F4" (func $e.instr_F4 (type $t0)))
(import "e" "m" (memory $e.m 256))
(func $f (export "f") (type $t1) (param $p0 i32)
(local $l0 i32)
(local $l0 i32) (local $l1 i32)
(set_local $p0
(get_local $p0))
(set_local $l0
(i32.const 10000))
(loop $L0
(block $B1
(block $B2
(block $B3
(block $B4
(br_table $B4 $B3 $B2 $B1
(set_local $l0
(i32.add
(get_local $l0)
(i32.const -1)))
(if $I1
(i32.eqz
(get_local $l0))
(then
(return)))
(block $B2
(block $B3
(block $B4
(block $B5
(br_table $B5 $B4 $B3 $B2
(get_local $p0)))
(call $e.cmp32
(i32.load
@ -45,7 +56,7 @@
(i32.load
(i32.const 664))
(i32.const 2)))
(if $I5
(if $I6
(call $e.test_z)
(then
(i32.store