Reworked VirtualMachineMemoryBuffer to extend ArrayBufferCursor.

This commit is contained in:
jtuu 2019-10-11 10:49:47 +03:00
parent aad45b0929
commit 2909b1bb3e

View File

@ -74,6 +74,8 @@ import {
Kind, Kind,
} from "../opcodes"; } from "../opcodes";
import Logger from "js-logger"; import Logger from "js-logger";
import { ArrayBufferCursor } from "../../../core/data_formats/cursor/ArrayBufferCursor";
import { Endianness } from "../../../core/data_formats/Endianness";
const logger = Logger.get("quest_editor/scripting/vm"); const logger = Logger.get("quest_editor/scripting/vm");
@ -167,7 +169,7 @@ function ranges_overlap(a: Range, b: Range): boolean {
return a[0] <= b[1] && b[0] <= a[1]; return a[0] <= b[1] && b[0] <= a[1];
} }
class VirtualMachineMemoryBuffer extends ArrayBuffer { class VirtualMachineMemoryBuffer extends ArrayBufferCursor {
/** /**
* The memory this buffer belongs to. * The memory this buffer belongs to.
*/ */
@ -178,7 +180,7 @@ class VirtualMachineMemoryBuffer extends ArrayBuffer {
public readonly address: number; public readonly address: number;
constructor(memory: VirtualMachineMemory, address: number, size: number) { constructor(memory: VirtualMachineMemory, address: number, size: number) {
super(size); super(new ArrayBuffer(size), Endianness.Little);
this.memory = memory; this.memory = memory;
this.address = address; this.address = address;
} }
@ -190,6 +192,10 @@ class VirtualMachineMemoryBuffer extends ArrayBuffer {
public free(): void { public free(): void {
this.memory.free(this.address); this.memory.free(this.address);
} }
public zero(): void {
new Uint32Array(this.backing_buffer).fill(0);
}
} }
/** /**
@ -374,12 +380,10 @@ class VirtualMachineMemory {
export class VirtualMachine { export class VirtualMachine {
private memory = new VirtualMachineMemory(); private memory = new VirtualMachineMemory();
private register_store = this.memory.allocate( private registers = this.memory.allocate(
REGISTER_SIZE * REGISTER_COUNT, REGISTER_SIZE * REGISTER_COUNT,
REGISTERS_BASE_ADDRESS, REGISTERS_BASE_ADDRESS,
)!; )!;
private register_uint8_view = new Uint8Array(this.register_store);
private registers = new DataView(this.register_store);
private object_code: Segment[] = []; private object_code: Segment[] = [];
private label_to_seg_idx: Map<number, number> = new Map(); private label_to_seg_idx: Map<number, number> = new Map();
private thread: Thread[] = []; private thread: Thread[] = [];
@ -764,19 +768,19 @@ export class VirtualMachine {
} }
private get_sint(reg: number): number { private get_sint(reg: number): number {
return this.registers.getInt32(REGISTER_SIZE * reg); return this.registers.i32_at(REGISTER_SIZE * reg);
} }
private set_sint(reg: number, value: number): void { private set_sint(reg: number, value: number): void {
this.registers.setInt32(REGISTER_SIZE * reg, value); this.registers.write_i32_at(REGISTER_SIZE * reg, value);
} }
private get_uint(reg: number): number { private get_uint(reg: number): number {
return this.registers.getUint32(REGISTER_SIZE * reg); return this.registers.u32_at(REGISTER_SIZE * reg);
} }
private set_uint(reg: number, value: number): void { private set_uint(reg: number, value: number): void {
this.registers.setUint32(REGISTER_SIZE * reg, value); this.registers.write_u32_at(REGISTER_SIZE * reg, value);
} }
private do_numeric_op_with_register( private do_numeric_op_with_register(
@ -958,11 +962,11 @@ export class VirtualMachine {
} }
private clear_registers(): void { private clear_registers(): void {
this.register_uint8_view.fill(0); this.registers.zero();
} }
private get_register_address(reg: number): number { private get_register_address(reg: number): number {
return this.register_store.address + reg * REGISTER_SIZE; return this.registers.address + reg * REGISTER_SIZE;
} }
} }
@ -978,9 +982,8 @@ class Thread {
*/ */
public call_stack: ExecutionLocation[] = []; public call_stack: ExecutionLocation[] = [];
private arg_stack_buf: VirtualMachineMemoryBuffer; private arg_stack: VirtualMachineMemoryBuffer;
private arg_stack_counter: number = 0; private arg_stack_counter: number = 0;
private arg_stack: DataView;
private arg_stack_types: ArgStackTypeList = Array(ARG_STACK_LENGTH).fill( private arg_stack_types: ArgStackTypeList = Array(ARG_STACK_LENGTH).fill(
Kind.Any, Kind.Any,
) as ArgStackTypeList; ) as ArgStackTypeList;
@ -993,14 +996,13 @@ class Thread {
constructor( constructor(
next: ExecutionLocation, next: ExecutionLocation,
arg_stack_buf: VirtualMachineMemoryBuffer, arg_stack: VirtualMachineMemoryBuffer,
global: boolean, global: boolean,
) { ) {
this.call_stack = [next]; this.call_stack = [next];
this.global = global; this.global = global;
this.arg_stack_buf = arg_stack_buf; this.arg_stack = arg_stack;
this.arg_stack = new DataView(arg_stack_buf);
} }
public call_stack_top(): ExecutionLocation { public call_stack_top(): ExecutionLocation {
@ -1012,7 +1014,7 @@ class Thread {
throw new Error("Argument stack: Stack overflow"); throw new Error("Argument stack: Stack overflow");
} }
this.arg_stack.setUint32(this.arg_stack_counter * ARG_STACK_SLOT_SIZE, data, true); this.arg_stack.write_u32_at(this.arg_stack_counter * ARG_STACK_SLOT_SIZE, data);
this.arg_stack_types[this.arg_stack_counter] = type; this.arg_stack_types[this.arg_stack_counter] = type;
this.arg_stack_counter++; this.arg_stack_counter++;
@ -1034,14 +1036,14 @@ class Thread {
switch (param.type.kind) { switch (param.type.kind) {
case Kind.Byte: case Kind.Byte:
args.push(this.arg_stack.getUint8(i)); args.push(this.arg_stack.u8_at(i * ARG_STACK_SLOT_SIZE));
break; break;
case Kind.Word: case Kind.Word:
args.push(this.arg_stack.getUint16(i, true)); args.push(this.arg_stack.u16_at(i * ARG_STACK_SLOT_SIZE));
break; break;
case Kind.DWord: case Kind.DWord:
case Kind.String: case Kind.String:
args.push(this.arg_stack.getUint32(i, true)); args.push(this.arg_stack.u32_at(i * ARG_STACK_SLOT_SIZE));
break; break;
default: default:
throw new Error(`Unhandled param kind: Kind.${Kind[param.type.kind]}`); throw new Error(`Unhandled param kind: Kind.${Kind[param.type.kind]}`);
@ -1054,6 +1056,6 @@ class Thread {
} }
public dispose(): void { public dispose(): void {
this.arg_stack_buf.free(); this.arg_stack.free();
} }
} }