Clean up
This commit is contained in:
parent
30f7442d4d
commit
5e21d68d83
|
@ -245,7 +245,6 @@ function V86Starter(options)
|
|||
"_get_time": () => Date.now(),
|
||||
|
||||
"_codegen_finalize": (cache_index, virt_start, start, end) => cpu.codegen_finalize(cache_index, virt_start, start, end),
|
||||
"_codegen_call_cache": (start) => cpu.codegen_call_cache(start),
|
||||
};
|
||||
|
||||
let wasm_file = DEBUG ? "v86-debug.wasm" : "v86.wasm";
|
||||
|
|
39
src/cpu.js
39
src/cpu.js
|
@ -20,10 +20,6 @@ function CPU(bus, wm, codegen)
|
|||
|
||||
this.memory_size = new Uint32Array(wm.memory.buffer, 812, 1);
|
||||
|
||||
// XXX: Replace with wasm table
|
||||
// XXX: Not garbage collected currently
|
||||
this.instr_cache = Object.create(null);
|
||||
|
||||
// Note: Currently unused (degrades performance and not required by any OS
|
||||
// that we support)
|
||||
this.a20_enabled = new Int32Array(wm.memory.buffer, 552, 1);
|
||||
|
@ -1375,22 +1371,11 @@ CPU.prototype.run_instruction_0f = function()
|
|||
|
||||
var seen_code = {};
|
||||
|
||||
CPU.prototype.codegen_call_cache = function(start)
|
||||
{
|
||||
//const before = this.instruction_pointer[0];
|
||||
//dbg_log("calling cached generated code at " + h(before));
|
||||
this.instr_cache[start]();
|
||||
//const after = this.instruction_pointer[0];
|
||||
//dbg_log("cached code block from " + h(before) + " to " + h(after));
|
||||
};
|
||||
|
||||
CPU.prototype.codegen_finalize = function(cache_index, virtual_start, start, end)
|
||||
{
|
||||
dbg_log("finalize");
|
||||
//dbg_log("finalize");
|
||||
const code = this.codegen.get_module_code();
|
||||
|
||||
//this.debug.dump_wasm(code);
|
||||
|
||||
let module;
|
||||
|
||||
if(DEBUG)
|
||||
|
@ -1401,9 +1386,17 @@ CPU.prototype.codegen_finalize = function(cache_index, virtual_start, start, end
|
|||
|
||||
seen_code[start] = true;
|
||||
|
||||
const buffer = new Uint8Array(end - start + 1);
|
||||
if((start ^ end) & ~0xFFF)
|
||||
{
|
||||
dbg_log("truncated disassembly");
|
||||
end = (start | 0xFFF) + 1; // until the end of the page
|
||||
}
|
||||
|
||||
for(let i = start; i < end + 1; i++)
|
||||
dbg_assert(end >= start);
|
||||
|
||||
const buffer = new Uint8Array(end - start);
|
||||
|
||||
for(let i = start; i < end; i++)
|
||||
{
|
||||
buffer[i - start] = this.read8(i);
|
||||
}
|
||||
|
@ -1433,19 +1426,17 @@ CPU.prototype.codegen_finalize = function(cache_index, virtual_start, start, end
|
|||
const instance = new WebAssembly.Instance(module, this.jit_imports);
|
||||
const f = instance.exports["f"];
|
||||
|
||||
this.instr_cache[start] = f;
|
||||
|
||||
// The following will throw if o.exports.f isn't an exported function
|
||||
this.wm.imports["env"].table.set(cache_index, f);
|
||||
|
||||
this.instruction_pointer[0] = virtual_start;
|
||||
|
||||
const before = this.instruction_pointer[0];
|
||||
dbg_log("calling generated code at " + h(before >>> 0));
|
||||
//const before = this.instruction_pointer[0];
|
||||
//dbg_log("calling generated code at " + h(before >>> 0));
|
||||
//debugger;
|
||||
f();
|
||||
const after = this.instruction_pointer[0];
|
||||
dbg_log("code block from " + h(before >>> 0) + " to " + h(after >>> 0));
|
||||
//const after = this.instruction_pointer[0];
|
||||
//dbg_log("code block from " + h(before >>> 0) + " to " + h(after >>> 0));
|
||||
};
|
||||
|
||||
CPU.prototype.dbg_log = function()
|
||||
|
|
|
@ -162,14 +162,15 @@
|
|||
|
||||
#define MXCSR_MASK (0xFFFF & ~(1 << 6))
|
||||
|
||||
// Mask used to map physical address to index in cache array
|
||||
#define JIT_PHYS_MASK 0xFFFF
|
||||
|
||||
#define WASM_TABLE_SIZE 0x10000
|
||||
|
||||
// Mask used to map physical address to index in cache array
|
||||
#define JIT_PHYS_MASK (WASM_TABLE_SIZE - 1)
|
||||
|
||||
#define HASH_PRIME 6151
|
||||
#define JIT_THRESHOLD 10000
|
||||
// XXX: Consider making this the same as page size (12) during perf testing
|
||||
#define DIRTY_ARR_SHIFT 16
|
||||
#define DIRTY_ARR_SHIFT 12
|
||||
#define MAX_INSTR_LEN 15
|
||||
#define MAX_BLOCK_LENGTH ((1 << DIRTY_ARR_SHIFT) - MAX_INSTR_LEN)
|
||||
|
||||
|
|
|
@ -267,7 +267,7 @@ void generate_instruction(int32_t opcode)
|
|||
int32_t instruction_length = end_eip - start_eip;
|
||||
|
||||
assert(instruction_length >= 0 && instruction_length < 16);
|
||||
dbg_log("instruction_length=%d", instruction_length);
|
||||
//dbg_log("instruction_length=%d", instruction_length);
|
||||
|
||||
gen_patch_increment_instruction_pointer(instruction_length);
|
||||
}
|
||||
|
@ -296,6 +296,7 @@ void cycle_internal()
|
|||
|
||||
const bool JIT_ALWAYS = false;
|
||||
const bool JIT_DONT_USE_CACHE = false;
|
||||
const bool JIT_COMPILE_ONLY_AFTER_JUMP = true;
|
||||
|
||||
if(cached && !clean)
|
||||
{
|
||||
|
@ -323,6 +324,7 @@ void cycle_internal()
|
|||
run_instruction(entry->opcode[i] | !!*is_32 << 8);
|
||||
(*timestamp_counter)++;
|
||||
}*/
|
||||
assert(entry->opcode[0] == read8(phys_addr));
|
||||
|
||||
//codegen_call_cache(phys_addr);
|
||||
call_indirect(addr_index);
|
||||
|
@ -333,9 +335,7 @@ void cycle_internal()
|
|||
|
||||
profiler_end(P_RUN_FROM_CACHE);
|
||||
}
|
||||
// A jump just occured indicating the start of a basic block + the
|
||||
// address is hot; let's JIT compile it
|
||||
else if(JIT_ALWAYS || jit_jump == 1 && ++hot_code_addresses[jit_hot_hash(phys_addr)] > JIT_THRESHOLD)
|
||||
else if(JIT_ALWAYS || (!JIT_COMPILE_ONLY_AFTER_JUMP || jit_jump == 1) && ++hot_code_addresses[jit_hot_hash(phys_addr)] > JIT_THRESHOLD)
|
||||
{
|
||||
if(clean && entry->start_addr != 0 && entry->start_addr != phys_addr)
|
||||
{
|
||||
|
@ -353,10 +353,14 @@ void cycle_internal()
|
|||
// Minimize collision based thrashing
|
||||
hot_code_addresses[jit_hot_hash(phys_addr)] = 0;
|
||||
|
||||
// invalidate now, in case generate_instruction raises
|
||||
entry->group_status = group_dirtiness[phys_addr >> DIRTY_ARR_SHIFT] + 1;
|
||||
|
||||
int32_t len = 0;
|
||||
jit_jump = 0;
|
||||
entry->len = 0;
|
||||
|
||||
entry->start_addr = phys_addr;
|
||||
entry->end_addr = phys_addr + 1;
|
||||
int32_t end_addr = phys_addr + 1;
|
||||
entry->is_32 = *is_32;
|
||||
|
||||
//jit_cache_arr[addr_index] = *entry;
|
||||
|
@ -367,37 +371,37 @@ void cycle_internal()
|
|||
// XXX: Artificial limit allows jit_dirty_cache to be
|
||||
// simplified by only dirtying 2 entries based on a mask
|
||||
// (instead of all possible entries)
|
||||
while(jit_jump == 0 && entry->len < 100 &&
|
||||
(entry->end_addr - entry->start_addr) < MAX_BLOCK_LENGTH)
|
||||
while(jit_jump == 0 && len < 50 &&
|
||||
(end_addr - entry->start_addr) < MAX_BLOCK_LENGTH)
|
||||
{
|
||||
*previous_ip = *instruction_pointer;
|
||||
int32_t opcode = read_imm8();
|
||||
|
||||
entry->opcode[entry->len] = opcode;
|
||||
entry->len++;
|
||||
if(len == 0)
|
||||
{
|
||||
entry->opcode[0] = opcode;
|
||||
}
|
||||
len++;
|
||||
|
||||
generate_instruction(opcode | !!*is_32 << 8);
|
||||
|
||||
entry->end_addr = *eip_phys ^ *instruction_pointer;
|
||||
end_addr = *eip_phys ^ *instruction_pointer;
|
||||
}
|
||||
|
||||
gen_increment_timestamp_counter(entry->len);
|
||||
gen_increment_timestamp_counter(len);
|
||||
|
||||
entry->len = len;
|
||||
|
||||
jit_jump = 0;
|
||||
|
||||
gen_finish();
|
||||
jit_in_progress = false;
|
||||
|
||||
codegen_finalize(addr_index, start_addr, entry->start_addr, entry->end_addr);
|
||||
codegen_finalize(addr_index, start_addr, entry->start_addr, end_addr);
|
||||
|
||||
assert(*prefixes == 0);
|
||||
|
||||
// When the hot instruction is a jmp (backwards),
|
||||
// leave its group_status unupdated, thereby invalidating it
|
||||
//if (entry->end_addr > entry->start_addr)
|
||||
//{
|
||||
entry->group_status = group_dirtiness[phys_addr >> DIRTY_ARR_SHIFT];
|
||||
//}
|
||||
|
||||
profiler_stat_increment(S_COMPILE_SUCCESS);
|
||||
profiler_end(P_GEN_INSTR);
|
||||
|
@ -438,7 +442,7 @@ static void run_prefix_instruction()
|
|||
|
||||
static void jit_prefix_instruction()
|
||||
{
|
||||
dbg_log("jit_prefix_instruction is32=%d", is_osize_32());
|
||||
//dbg_log("jit_prefix_instruction is32=%d", is_osize_32());
|
||||
jit_instruction(read_imm8() | is_osize_32() << 8);
|
||||
}
|
||||
|
||||
|
|
|
@ -33,15 +33,14 @@ struct code_cache {
|
|||
// Address of the start of the basic block
|
||||
uint32_t start_addr;
|
||||
// Address of the instruction immediately after the basic block ends
|
||||
uint32_t end_addr;
|
||||
int32_t opcode[100];
|
||||
int32_t opcode[1]; // TODO: Remove in debug mode
|
||||
int32_t len;
|
||||
int32_t is_32;
|
||||
// Cleanliness status of the entry's "group" (based on
|
||||
// DIRTY_ARR_SHIFT). Value only has meaning in relation with the
|
||||
// group_dirtiness value.
|
||||
uint32_t group_status;
|
||||
} jit_cache_arr[WASM_TABLE_SIZE] = {{0, 0, {0}, 0, 0, 0}};
|
||||
} jit_cache_arr[WASM_TABLE_SIZE] = {{0, {0}, 0, 0, 0}};
|
||||
|
||||
// Flag indicating whether the instruction that just ran was a jump of some sort
|
||||
uint32_t jit_jump = 0;
|
||||
|
|
Loading…
Reference in a new issue