diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml index a8067ed9..bf8116b0 100644 --- a/.github/workflows/develop.yml +++ b/.github/workflows/develop.yml @@ -89,7 +89,7 @@ jobs: ln -snf .. ckb-vm-test-suite/ckb-vm docker run --rm -v `pwd`:/code nervos/ckb-riscv-gnu-toolchain:bionic-20210804 cp -r /riscv /code/riscv cd ckb-vm-test-suite - git checkout 898edc351eeb4de974ca4f0ff8d1e4943a95aecb + git checkout 2be7dcb0fda7ab41932813632fd1904e8cecf1f0 git submodule update --init --recursive RISCV=`pwd`/../riscv ./test.sh @@ -161,7 +161,7 @@ jobs: ln -snf .. ckb-vm-test-suite/ckb-vm docker run --rm -v `pwd`:/code nervos/ckb-riscv-gnu-toolchain:bionic-20210804 cp -r /riscv /code/riscv cd ckb-vm-test-suite - git checkout 898edc351eeb4de974ca4f0ff8d1e4943a95aecb + git checkout 2be7dcb0fda7ab41932813632fd1904e8cecf1f0 git submodule update --init --recursive RISCV=`pwd`/../riscv ./test.sh --build-only cd .. diff --git a/benches/vm_benchmark.rs b/benches/vm_benchmark.rs index e2e14960..e9db7cc3 100644 --- a/benches/vm_benchmark.rs +++ b/benches/vm_benchmark.rs @@ -4,13 +4,13 @@ extern crate criterion; use bytes::Bytes; #[cfg(has_asm)] use ckb_vm::{ - decoder::build_decoder, + decoder::{DefaultDecoder, InstDecoder}, machine::{ asm::{ traces::{MemoizedDynamicTraceDecoder, MemoizedFixedTraceDecoder}, - AsmCoreMachine, AsmMachine, + AbstractAsmMachine, AsmCoreMachine, AsmDefaultMachineBuilder, AsmMachine, }, - DefaultMachineBuilder, VERSION0, VERSION2, + AbstractDefaultMachineBuilder, DefaultMachineRunner, SupportMachine, VERSION0, VERSION2, }, ISA_B, ISA_IMC, ISA_MOP, }; @@ -45,7 +45,7 @@ fn asm_benchmark(c: &mut Criterion) { ].into_iter().map(|a| Ok(a.into())); b.iter(|| { let asm_core = AsmCoreMachine::new(ISA_IMC, VERSION0, u64::MAX); - let core = DefaultMachineBuilder::new(asm_core).build(); + let core = AsmDefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine.load_program(&buffer, args.clone()).unwrap(); machine.run().unwrap() @@ -66,7 +66,7 @@ fn mop_benchmark(c: &mut Criterion) { ].into_iter().map(|a| Ok(a.into())); b.iter(|| { let asm_core = AsmCoreMachine::new(ISA_IMC | ISA_B | ISA_MOP, VERSION2, u64::MAX); - let core = DefaultMachineBuilder::>::new(asm_core) + let core = AsmDefaultMachineBuilder::new(asm_core) .build(); let mut machine = AsmMachine::new(core); machine.load_program(&buffer, args.clone()).unwrap(); @@ -88,19 +88,19 @@ fn mop_memoized_benchmark(c: &mut Criterion) { "foo", "bar", ].into_iter().map(|a| Ok(a.into())); - let mut decoder = MemoizedFixedTraceDecoder::new(build_decoder::(isa, version)); + let mut decoder = MemoizedFixedTraceDecoder::new::(isa, version); let asm_core = AsmCoreMachine::new(isa, version, u64::MAX); - let core = DefaultMachineBuilder::>::new(asm_core) + let core = AbstractDefaultMachineBuilder::<_, MemoizedFixedTraceDecoder>::new(asm_core) .build(); - let mut machine = AsmMachine::new(core); + let mut machine = AbstractAsmMachine::new(core); machine.load_program(&buffer, args.clone()).unwrap(); machine.run_with_decoder(&mut decoder).unwrap(); b.iter(|| { let asm_core = AsmCoreMachine::new(isa, version, u64::MAX); - let core = DefaultMachineBuilder::>::new(asm_core) + let core = AbstractDefaultMachineBuilder::<_, MemoizedFixedTraceDecoder>::new(asm_core) .build(); - let mut machine = AsmMachine::new(core); + let mut machine = AbstractAsmMachine::new(core); machine.load_program(&buffer, args.clone()).unwrap(); decoder.clear_traces(); machine.run_with_decoder(&mut decoder).unwrap() @@ -121,19 +121,19 @@ fn mop_memoized_dynamic_benchmark(c: &mut Criterion) { "foo", "bar", ].into_iter().map(|a| Ok(a.into())); - let mut decoder = MemoizedDynamicTraceDecoder::new(build_decoder::(isa, version)); + let mut decoder = MemoizedDynamicTraceDecoder::new::(isa, version); let asm_core = AsmCoreMachine::new(isa, version, u64::MAX); - let core = DefaultMachineBuilder::>::new(asm_core) + let core = AbstractDefaultMachineBuilder::<_, MemoizedDynamicTraceDecoder>::new(asm_core) .build(); - let mut machine = AsmMachine::new(core); + let mut machine = AbstractAsmMachine::new(core); machine.load_program(&buffer, args.clone()).unwrap(); machine.run_with_decoder(&mut decoder).unwrap(); b.iter(|| { let asm_core = AsmCoreMachine::new(isa, version, u64::MAX); - let core = DefaultMachineBuilder::>::new(asm_core) + let core = AbstractDefaultMachineBuilder::<_, MemoizedDynamicTraceDecoder>::new(asm_core) .build(); - let mut machine = AsmMachine::new(core); + let mut machine = AbstractAsmMachine::new(core); machine.load_program(&buffer, args.clone()).unwrap(); decoder.clear_traces(); machine.run_with_decoder(&mut decoder).unwrap() diff --git a/definitions/src/asm.rs b/definitions/src/asm.rs index 7a99e5c3..060e7fe8 100644 --- a/definitions/src/asm.rs +++ b/definitions/src/asm.rs @@ -1,8 +1,5 @@ -use crate::{ - instructions::Instruction, DEFAULT_MEMORY_SIZE, MEMORY_FRAMESIZE, MEMORY_FRAME_SHIFTS, - RISCV_GENERAL_REGISTER_NUMBER, RISCV_PAGESIZE, -}; -use std::alloc::{alloc, alloc_zeroed, dealloc, Layout}; +use crate::{instructions::Instruction, RISCV_GENERAL_REGISTER_NUMBER}; +use std::alloc::{dealloc, Layout}; // The number of trace items to keep pub const TRACE_SIZE: usize = 8192; @@ -117,49 +114,6 @@ impl Drop for AsmCoreMachine { } impl AsmCoreMachine { - pub fn new(isa: u8, version: u32, max_cycles: u64) -> Box { - Self::new_with_memory(isa, version, max_cycles, DEFAULT_MEMORY_SIZE) - } - - pub fn new_with_memory( - isa: u8, - version: u32, - max_cycles: u64, - memory_size: usize, - ) -> Box { - assert_ne!(memory_size, 0); - assert_eq!(memory_size % RISCV_PAGESIZE, 0); - assert_eq!(memory_size % (1 << MEMORY_FRAME_SHIFTS), 0); - let mut machine = unsafe { - let layout = Layout::new::(); - let raw_allocation = alloc_zeroed(layout) as *mut AsmCoreMachine; - Box::from_raw(raw_allocation) - }; - machine.max_cycles = max_cycles; - if cfg!(feature = "enable-chaos-mode-by-default") { - machine.chaos_mode = 1; - } - machine.load_reservation_address = u64::MAX; - machine.version = version; - machine.isa = isa; - - machine.memory_size = memory_size as u64; - machine.frames_size = (memory_size / MEMORY_FRAMESIZE) as u64; - machine.flags_size = (memory_size / RISCV_PAGESIZE) as u64; - - machine.last_read_frame = u64::MAX; - machine.last_write_page = u64::MAX; - - let memory_layout = Layout::array::(machine.memory_size as usize).unwrap(); - machine.memory_ptr = unsafe { alloc(memory_layout) } as u64; - let flags_layout = Layout::array::(machine.flags_size as usize).unwrap(); - machine.flags_ptr = unsafe { alloc_zeroed(flags_layout) } as u64; - let frames_layout = Layout::array::(machine.frames_size as usize).unwrap(); - machine.frames_ptr = unsafe { alloc_zeroed(frames_layout) } as u64; - - machine - } - pub fn set_max_cycles(&mut self, cycles: u64) { self.max_cycles = cycles; } diff --git a/definitions/src/generate_asm_constants.rs b/definitions/src/generate_asm_constants.rs index 8735c5a0..4e8fe2b0 100644 --- a/definitions/src/generate_asm_constants.rs +++ b/definitions/src/generate_asm_constants.rs @@ -11,6 +11,7 @@ use ckb_vm_definitions::{ MEMORY_FRAMESIZE, MEMORY_FRAME_PAGE_SHIFTS, MEMORY_FRAME_SHIFTS, RISCV_PAGESIZE, RISCV_PAGE_SHIFTS, }; +use std::alloc::{alloc, Layout}; use std::mem::{size_of, zeroed}; macro_rules! print_inst_label { @@ -129,7 +130,15 @@ fn main() { ); println!(); - let m: Box = AsmCoreMachine::new(0, 0, 0); + // We don't need a fully initialized AsmCoreMachine, only a dummy + // structure here will do. + let m: Box = unsafe { + let machine_size = std::mem::size_of::(); + + let layout = Layout::array::(machine_size).unwrap(); + let raw_allocation = alloc(layout) as *mut AsmCoreMachine; + Box::from_raw(raw_allocation) + }; let m_address = &*m as *const AsmCoreMachine as usize; println!( "#define CKB_VM_ASM_ASM_CORE_MACHINE_OFFSET_REGISTERS {}", diff --git a/examples/check_real_memory.rs b/examples/check_real_memory.rs index c3a7b9fd..a2ee6ef4 100644 --- a/examples/check_real_memory.rs +++ b/examples/check_real_memory.rs @@ -7,8 +7,8 @@ use std::process::{id, Command}; #[cfg(has_asm)] use ckb_vm::{ machine::{ - asm::{AsmCoreMachine, AsmMachine}, - DefaultMachineBuilder, VERSION0, + asm::{AsmCoreMachine, AsmDefaultMachineBuilder, AsmMachine}, + DefaultMachineRunner, SupportMachine, VERSION0, }, ISA_IMC, }; @@ -126,7 +126,7 @@ fn check_interpreter(memory_size: usize) -> Result<(), ()> { let result = run_with_memory::>( &Bytes::from(BIN_PATH_BUFFER), &vec![Bytes::from(BIN_NAME)], - SparseMemory::new_with_memory(memory_size), + memory_size, ); assert!(result.is_ok()); assert_eq!(result.unwrap(), 0); @@ -146,7 +146,7 @@ fn check_falt(memory_size: usize) -> Result<(), ()> { let result = run_with_memory::>( &Bytes::from(BIN_PATH_BUFFER), &vec![Bytes::from(BIN_NAME)], - FlatMemory::new_with_memory(memory_size), + memory_size, ); assert!(result.is_ok()); assert_eq!(result.unwrap(), 0); @@ -164,8 +164,13 @@ fn check_asm(memory_size: usize) -> Result<(), ()> { ); println!("Base memory: {}", get_current_memory()); for _ in 0..G_CHECK_LOOP { - let asm_core = AsmCoreMachine::new_with_memory(ISA_IMC, VERSION0, u64::MAX, memory_size); - let core = DefaultMachineBuilder::new(asm_core).build(); + let asm_core = ::new_with_memory( + ISA_IMC, + VERSION0, + u64::MAX, + memory_size, + ); + let core = AsmDefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine .load_program( @@ -191,8 +196,13 @@ fn check_asm_in_thread(memory_size: usize) -> Result<(), ()> { ); println!("Base memory: {}", get_current_memory()); for _ in 0..G_CHECK_LOOP { - let asm_core = AsmCoreMachine::new_with_memory(ISA_IMC, VERSION0, u64::MAX, memory_size); - let core = DefaultMachineBuilder::new(asm_core).build(); + let asm_core = ::new_with_memory( + ISA_IMC, + VERSION0, + u64::MAX, + memory_size, + ); + let core = AsmDefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine .load_program( diff --git a/examples/ckb_vm_runner.rs b/examples/ckb_vm_runner.rs index ac539e82..6e6a096c 100644 --- a/examples/ckb_vm_runner.rs +++ b/examples/ckb_vm_runner.rs @@ -1,6 +1,8 @@ use ckb_vm::cost_model::estimate_cycles; use ckb_vm::registers::{A0, A7}; -use ckb_vm::{Bytes, CoreMachine, Memory, Register, SupportMachine, Syscalls}; +use ckb_vm::{ + Bytes, CoreMachine, DefaultMachineRunner, Memory, Register, SupportMachine, Syscalls, +}; pub struct DebugSyscall {} @@ -39,12 +41,12 @@ impl Syscalls for DebugSyscall { #[cfg(has_asm)] fn main_asm(code: Bytes, args: Vec) -> Result<(), Box> { - let asm_core = ckb_vm::machine::asm::AsmCoreMachine::new( + let asm_core = ::new( ckb_vm::ISA_IMC | ckb_vm::ISA_B | ckb_vm::ISA_MOP, ckb_vm::machine::VERSION2, u64::MAX, ); - let core = ckb_vm::DefaultMachineBuilder::new(asm_core) + let core = ckb_vm::machine::asm::AsmDefaultMachineBuilder::new(asm_core) .instruction_cycle_func(Box::new(estimate_cycles)) .syscall(Box::new(DebugSyscall {})) .build(); @@ -68,7 +70,7 @@ fn main_int(code: Bytes, args: Vec) -> Result<(), Box(isa: u8, version: u32) -> Self; fn decode(&mut self, memory: &mut M, pc: u64) -> Result; fn reset_instructions_cache(&mut self) -> Result<(), Error>; } -pub struct Decoder { +pub struct DefaultDecoder { factories: Vec, mop: bool, version: u32, @@ -30,9 +31,10 @@ pub struct Decoder { instructions_cache: Vec<(u64, u64)>, } -impl Decoder { - pub fn new(mop: bool, version: u32) -> Decoder { - Decoder { +impl DefaultDecoder { + /// Creates an empty decoder with no instruction factory + pub fn empty(mop: bool, version: u32) -> Self { + Self { factories: vec![], mop, version, @@ -860,7 +862,21 @@ impl Decoder { } } -impl InstDecoder for Decoder { +impl InstDecoder for DefaultDecoder { + fn new(isa: u8, version: u32) -> Self { + let mut decoder = Self::empty(isa & ISA_MOP != 0, version); + decoder.add_instruction_factory(rvc::factory::); + decoder.add_instruction_factory(i::factory::); + decoder.add_instruction_factory(m::factory::); + if isa & ISA_B != 0 { + decoder.add_instruction_factory(b::factory::); + } + if isa & ISA_A != 0 { + decoder.add_instruction_factory(a::factory::); + } + decoder + } + fn decode(&mut self, memory: &mut M, pc: u64) -> Result { if self.mop { self.decode_mop(memory, pc) @@ -874,17 +890,3 @@ impl InstDecoder for Decoder { Ok(()) } } - -pub fn build_decoder(isa: u8, version: u32) -> Decoder { - let mut decoder = Decoder::new(isa & ISA_MOP != 0, version); - decoder.add_instruction_factory(rvc::factory::); - decoder.add_instruction_factory(i::factory::); - decoder.add_instruction_factory(m::factory::); - if isa & ISA_B != 0 { - decoder.add_instruction_factory(b::factory::); - } - if isa & ISA_A != 0 { - decoder.add_instruction_factory(a::factory::); - } - decoder -} diff --git a/src/lib.rs b/src/lib.rs index 2bd98eca..06608028 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -21,8 +21,9 @@ pub use crate::{ debugger::Debugger, instructions::{Instruction, Register}, machine::{ - trace::TraceMachine, CoreMachine, DefaultCoreMachine, DefaultMachine, - DefaultMachineBuilder, FlattenedArgsReader, InstructionCycleFunc, Machine, SupportMachine, + trace::TraceMachine, CoreMachine, DefaultCoreMachine, DefaultMachine, DefaultMachineRunner, + FlattenedArgsReader, InstructionCycleFunc, Machine, RustDefaultMachineBuilder, + SupportMachine, }, memory::{flat::FlatMemory, sparse::SparseMemory, wxorx::WXorXMemory, Memory}, syscalls::Syscalls, @@ -36,33 +37,22 @@ pub use ckb_vm_definitions::{ pub use error::Error; -pub fn run + Default>( - program: &Bytes, - args: &[Bytes], -) -> Result { - let core_machine = DefaultCoreMachine::>::new_with_memory( - ISA_IMC | ISA_B | ISA_MOP, - machine::VERSION2, - u64::MAX, - WXorXMemory::new(M::default()), - ); - let mut machine = TraceMachine::new(DefaultMachineBuilder::new(core_machine).build()); - machine.load_program(program, args.iter().map(|e| Ok(e.clone())))?; - machine.run() +pub fn run>(program: &Bytes, args: &[Bytes]) -> Result { + run_with_memory::(program, args, DEFAULT_MEMORY_SIZE) } pub fn run_with_memory>( program: &Bytes, args: &[Bytes], - memory: M, + memory_size: usize, ) -> Result { let core_machine = DefaultCoreMachine::>::new_with_memory( ISA_IMC | ISA_B | ISA_MOP, machine::VERSION2, u64::MAX, - WXorXMemory::new(memory), + memory_size, ); - let mut machine = TraceMachine::new(DefaultMachineBuilder::new(core_machine).build()); + let mut machine = TraceMachine::new(RustDefaultMachineBuilder::new(core_machine).build()); machine.load_program(program, args.iter().map(|e| Ok(e.clone())))?; machine.run() } diff --git a/src/machine/asm/mod.rs b/src/machine/asm/mod.rs index c0f6a0fb..48c1eda6 100644 --- a/src/machine/asm/mod.rs +++ b/src/machine/asm/mod.rs @@ -9,29 +9,31 @@ use ckb_vm_definitions::{ RET_EBREAK, RET_ECALL, RET_INVALID_PERMISSION, RET_MAX_CYCLES_EXCEEDED, RET_OUT_OF_BOUND, RET_PAUSE, RET_SLOWPATH, }, - ISA_MOP, MEMORY_FRAME_PAGE_SHIFTS, RISCV_GENERAL_REGISTER_NUMBER, RISCV_PAGE_SHIFTS, + ISA_MOP, MEMORY_FRAMESIZE, MEMORY_FRAME_PAGE_SHIFTS, RISCV_GENERAL_REGISTER_NUMBER, + RISCV_PAGE_SHIFTS, }; use rand::{prelude::RngCore, SeedableRng}; +use std::alloc::{alloc, alloc_zeroed, Layout}; +use std::mem::MaybeUninit; use std::os::raw::c_uchar; use crate::{ - decoder::{build_decoder, InstDecoder}, elf::ProgramMetadata, error::OutOfBoundKind, instructions::execute_instruction, machine::{ asm::traces::{decode_fixed_trace, SimpleFixedTraceDecoder, TraceDecoder}, - VERSION0, + AbstractDefaultMachineBuilder, VERSION0, }, memory::{ check_no_overflow, fill_page_data, get_page_indices, memset, round_page_down, round_page_up, FLAG_DIRTY, FLAG_EXECUTABLE, FLAG_FREEZED, FLAG_WRITABLE, FLAG_WXORX_BIT, }, - CoreMachine, DefaultMachine, Error, Machine, Memory, SupportMachine, MEMORY_FRAME_SHIFTS, - RISCV_PAGESIZE, + CoreMachine, DefaultMachine, DefaultMachineRunner, Error, Machine, Memory, SupportMachine, + MEMORY_FRAME_SHIFTS, RISCV_PAGESIZE, }; -impl CoreMachine for Box { +impl CoreMachine for AsmCoreMachine { type REG = u64; type MEM = Self; @@ -119,7 +121,7 @@ fn check_permission(memory: &mut M, page: u64, flag: u8) -> Result<() // check whether a memory address is writable or not and mark it as dirty, `size` should be 1, 2, 4 or 8 fn check_memory_writable( - machine: &mut Box, + machine: &mut AsmCoreMachine, addr: u64, size: usize, ) -> Result<(), Error> { @@ -152,7 +154,7 @@ fn check_memory_writable( // check whether a memory address is executable, `size` should be 2 or 4 fn check_memory_executable( - machine: &mut Box, + machine: &mut AsmCoreMachine, addr: u64, size: usize, ) -> Result<(), Error> { @@ -183,11 +185,7 @@ fn check_memory_executable( } // check whether a memory address is initialized, `size` should be 1, 2, 4 or 8 -fn check_memory_inited( - machine: &mut Box, - addr: u64, - size: usize, -) -> Result<(), Error> { +fn check_memory_inited(machine: &mut AsmCoreMachine, addr: u64, size: usize) -> Result<(), Error> { debug_assert!(size == 1 || size == 2 || size == 4 || size == 8); let page = addr >> RISCV_PAGE_SHIFTS; if page as usize >= machine.memory_pages() { @@ -213,7 +211,7 @@ fn check_memory_inited( // A newtype supporting fast store_byte / store_bytes without memory // permission checking -struct FastMemory<'a>(&'a mut Box); +struct FastMemory<'a>(&'a mut AsmCoreMachine); impl<'a> FastMemory<'a> { fn prepare_memory(&mut self, addr: u64, size: u64) -> Result<(), Error> { @@ -251,6 +249,10 @@ impl<'a> FastMemory<'a> { impl<'a> Memory for FastMemory<'a> { type REG = u64; + fn new(_memory_size: usize) -> Self { + unreachable!() + } + fn store_bytes(&mut self, addr: u64, value: &[u8]) -> Result<(), Error> { if value.is_empty() { return Ok(()); @@ -271,10 +273,6 @@ impl<'a> Memory for FastMemory<'a> { Ok(()) } - fn reset_memory(&mut self) -> Result<(), Error> { - unreachable!() - } - fn init_pages( &mut self, _addr: u64, @@ -355,18 +353,11 @@ impl<'a> Memory for FastMemory<'a> { } } -impl Memory for Box { +impl Memory for AsmCoreMachine { type REG = u64; - fn reset_memory(&mut self) -> Result<(), Error> { - let slice = cast_ptr_to_slice_mut(self, self.flags_ptr, 0, self.flags_size as usize); - memset(slice, 0); - let slice = cast_ptr_to_slice_mut(self, self.frames_ptr, 0, self.frames_size as usize); - memset(slice, 0); - self.load_reservation_address = u64::MAX; - self.last_read_frame = u64::MAX; - self.last_write_page = u64::MAX; - Ok(()) + fn new(_memory_size: usize) -> Self { + unreachable!() } fn init_pages( @@ -600,7 +591,44 @@ impl Memory for Box { } } -impl SupportMachine for Box { +impl SupportMachine for AsmCoreMachine { + fn new_with_memory( + isa: u8, + version: u32, + max_cycles: u64, + memory_size: usize, + ) -> AsmCoreMachine { + assert_ne!(memory_size, 0); + assert_eq!(memory_size % RISCV_PAGESIZE, 0); + assert_eq!(memory_size % (1 << MEMORY_FRAME_SHIFTS), 0); + + let mut machine: AsmCoreMachine = unsafe { MaybeUninit::zeroed().assume_init() }; + + machine.max_cycles = max_cycles; + if cfg!(feature = "enable-chaos-mode-by-default") { + machine.chaos_mode = 1; + } + machine.load_reservation_address = u64::MAX; + machine.version = version; + machine.isa = isa; + + machine.memory_size = memory_size as u64; + machine.frames_size = (memory_size / MEMORY_FRAMESIZE) as u64; + machine.flags_size = (memory_size / RISCV_PAGESIZE) as u64; + + machine.last_read_frame = u64::MAX; + machine.last_write_page = u64::MAX; + + let memory_layout = Layout::array::(machine.memory_size as usize).unwrap(); + machine.memory_ptr = unsafe { alloc(memory_layout) } as u64; + let flags_layout = Layout::array::(machine.flags_size as usize).unwrap(); + machine.flags_ptr = unsafe { alloc_zeroed(flags_layout) } as u64; + let frames_layout = Layout::array::(machine.frames_size as usize).unwrap(); + machine.frames_ptr = unsafe { alloc_zeroed(frames_layout) } as u64; + + machine + } + fn cycles(&self) -> u64 { self.cycles } @@ -623,7 +651,17 @@ impl SupportMachine for Box { self.cycles = 0; self.max_cycles = max_cycles; self.reset_signal = 1; - self.reset_memory() + + // Reset memory + let slice = cast_ptr_to_slice_mut(self, self.flags_ptr, 0, self.flags_size as usize); + memset(slice, 0); + let slice = cast_ptr_to_slice_mut(self, self.frames_ptr, 0, self.frames_size as usize); + memset(slice, 0); + self.load_reservation_address = u64::MAX; + self.last_read_frame = u64::MAX; + self.last_write_page = u64::MAX; + + Ok(()) } fn reset_signal(&mut self) -> bool { @@ -653,44 +691,34 @@ extern "C" { pub fn ckb_vm_asm_labels(); } -pub struct AsmMachine { - pub machine: DefaultMachine>, -} +/// This builder only works with assembly VMs +pub type AsmDefaultMachineBuilder = + AbstractDefaultMachineBuilder; +pub type AsmDefaultMachine = DefaultMachine; -impl AsmMachine { - pub fn new(machine: DefaultMachine>) -> Self { - Self { machine } - } +pub type AsmMachine = AbstractAsmMachine; - pub fn set_max_cycles(&mut self, cycles: u64) { - self.machine.inner.max_cycles = cycles; - } +pub struct AbstractAsmMachine { + pub machine: DefaultMachine, +} - pub fn load_program( - &mut self, - program: &Bytes, - args: impl ExactSizeIterator>, - ) -> Result { - self.machine.load_program(program, args) +impl DefaultMachineRunner for AbstractAsmMachine { + type Inner = AsmCoreMachine; + type Decoder = Decoder; + + fn new(machine: DefaultMachine) -> Self { + Self { machine } } - pub fn load_program_with_metadata( - &mut self, - program: &Bytes, - metadata: &ProgramMetadata, - args: impl ExactSizeIterator>, - ) -> Result { - self.machine - .load_program_with_metadata(program, metadata, args) + fn machine(&self) -> &DefaultMachine { + &self.machine } - pub fn run(&mut self) -> Result { - let decoder = build_decoder::(self.machine.isa(), self.machine.version()); - let mut decoder = SimpleFixedTraceDecoder::new(decoder); - self.run_with_decoder(&mut decoder) + fn machine_mut(&mut self) -> &mut DefaultMachine { + &mut self.machine } - pub fn run_with_decoder(&mut self, decoder: &mut D) -> Result { + fn run_with_decoder(&mut self, decoder: &mut Self::Decoder) -> Result { if self.machine.isa() & ISA_MOP != 0 && self.machine.version() == VERSION0 { return Err(Error::InvalidVersion); } @@ -706,7 +734,7 @@ impl AsmMachine { fixed_traces: decoder.fixed_traces(), fixed_trace_mask: decoder.fixed_trace_size().wrapping_sub(1), }; - ckb_vm_x64_execute(&mut **self.machine.inner_mut(), &data as *const _) + ckb_vm_x64_execute(&mut *self.machine.inner_mut(), &data as *const _) }; match result { RET_DECODE_TRACE => decoder.prepare_traces(&mut self.machine)?, @@ -740,8 +768,32 @@ impl AsmMachine { } Ok(self.machine.exit_code()) } +} + +impl AbstractAsmMachine { + pub fn set_max_cycles(&mut self, cycles: u64) { + self.machine.inner.max_cycles = cycles; + } + + pub fn load_program( + &mut self, + program: &Bytes, + args: impl ExactSizeIterator>, + ) -> Result { + self.machine.load_program(program, args) + } + + pub fn load_program_with_metadata( + &mut self, + program: &Bytes, + metadata: &ProgramMetadata, + args: impl ExactSizeIterator>, + ) -> Result { + self.machine + .load_program_with_metadata(program, metadata, args) + } - pub fn step(&mut self, decoder: &mut D) -> Result<(), Error> { + pub fn step(&mut self, decoder: &mut Decoder) -> Result<(), Error> { // Decode only one instruction into a trace let (trace, _) = decode_fixed_trace(decoder, &mut self.machine, Some(1))?; @@ -751,7 +803,7 @@ impl AsmMachine { fixed_traces: &trace as *const FixedTrace, fixed_trace_mask: 0, }; - ckb_vm_x64_execute(&mut **self.machine.inner_mut(), &data as *const _) + ckb_vm_x64_execute(&mut *self.machine.inner_mut(), &data as *const _) }; match result { RET_DECODE_TRACE => (), diff --git a/src/machine/asm/traces.rs b/src/machine/asm/traces.rs index edcc603f..099cf884 100644 --- a/src/machine/asm/traces.rs +++ b/src/machine/asm/traces.rs @@ -5,7 +5,7 @@ use crate::{ Instruction, InstructionOpcode, OP_CUSTOM_ASM_TRACE_JUMP, OP_CUSTOM_TRACE_END, }, }, - decoder::InstDecoder, + decoder::{DefaultDecoder, InstDecoder}, error::Error, instructions::{ blank_instruction, extract_opcode, instruction_length, is_basic_block_end_instruction, @@ -16,6 +16,7 @@ use crate::{ CoreMachine, DefaultMachine, }, memory::Memory, + Register, }; use std::alloc::{alloc, alloc_zeroed, Layout}; use std::collections::HashMap; @@ -25,8 +26,10 @@ pub trait TraceDecoder: InstDecoder { fn fixed_trace_size(&self) -> u64; fn prepare_traces( &mut self, - machine: &mut DefaultMachine>, - ) -> Result<(), Error>; + machine: &mut DefaultMachine, + ) -> Result<(), Error> + where + Self: Sized; fn reset(&mut self) -> Result<(), Error>; } @@ -38,9 +41,9 @@ pub fn label_from_fastpath_opcode(opcode: InstructionOpcode) -> u64 { } } -pub fn decode_fixed_trace( +pub fn decode_fixed_trace( decoder: &mut D, - machine: &mut DefaultMachine>, + machine: &mut DefaultMachine, maximum_insts: Option, ) -> Result<(FixedTrace, usize), Error> { let pc = *machine.pc(); @@ -80,21 +83,12 @@ pub fn decode_fixed_trace( /// A simple and naive trace decoder that only works with 8192 fixed traces. /// It serves as the default implementation. -pub struct SimpleFixedTraceDecoder { +pub struct SimpleFixedTraceDecoder { traces: Box<[FixedTrace; TRACE_SIZE]>, decoder: D, } impl SimpleFixedTraceDecoder { - pub fn new(decoder: D) -> Self { - let traces = unsafe { - let layout = Layout::array::(TRACE_SIZE).unwrap(); - let raw_allocation = alloc_zeroed(layout) as *mut _; - Box::from_raw(raw_allocation) - }; - Self { decoder, traces } - } - pub fn clear_traces(&mut self) { for i in 0..TRACE_SIZE { self.traces[i] = FixedTrace::default(); @@ -113,7 +107,7 @@ impl TraceDecoder for SimpleFixedTraceDecoder { fn prepare_traces( &mut self, - machine: &mut DefaultMachine>, + machine: &mut DefaultMachine, ) -> Result<(), Error> { let (trace, _) = decode_fixed_trace(&mut self.decoder, machine, None)?; let slot = calculate_slot(*machine.pc()); @@ -128,6 +122,16 @@ impl TraceDecoder for SimpleFixedTraceDecoder { } impl InstDecoder for SimpleFixedTraceDecoder { + fn new(isa: u8, version: u32) -> Self { + let decoder = D::new::(isa, version); + let traces = unsafe { + let layout = Layout::array::(TRACE_SIZE).unwrap(); + let raw_allocation = alloc_zeroed(layout) as *mut _; + Box::from_raw(raw_allocation) + }; + Self { decoder, traces } + } + fn decode(&mut self, memory: &mut M, pc: u64) -> Result { self.decoder.decode(memory, pc) } @@ -144,13 +148,6 @@ pub struct MemoizedFixedTraceDecoder { } impl MemoizedFixedTraceDecoder { - pub fn new(decoder: D) -> Self { - Self { - inner: SimpleFixedTraceDecoder::new(decoder), - cache: HashMap::default(), - } - } - pub fn clear_traces(&mut self) { self.inner.clear_traces(); } @@ -167,7 +164,7 @@ impl TraceDecoder for MemoizedFixedTraceDecoder { fn prepare_traces( &mut self, - machine: &mut DefaultMachine>, + machine: &mut DefaultMachine, ) -> Result<(), Error> { let pc = *machine.pc(); let slot = calculate_slot(pc); @@ -190,6 +187,13 @@ impl TraceDecoder for MemoizedFixedTraceDecoder { } impl InstDecoder for MemoizedFixedTraceDecoder { + fn new(isa: u8, version: u32) -> Self { + Self { + inner: SimpleFixedTraceDecoder::new::(isa, version), + cache: HashMap::default(), + } + } + fn decode(&mut self, memory: &mut M, pc: u64) -> Result { self.inner.decode(memory, pc) } @@ -286,14 +290,6 @@ pub struct MemoizedDynamicTraceDecoder { } impl MemoizedDynamicTraceDecoder { - pub fn new(decoder: D) -> Self { - Self { - inner: SimpleFixedTraceDecoder::new(decoder), - fixed_cache: HashMap::default(), - dynamic_cache: HashMap::default(), - } - } - pub fn clear_traces(&mut self) { self.inner.clear_traces(); } @@ -301,7 +297,7 @@ impl MemoizedDynamicTraceDecoder { fn find_or_build_dynamic_trace( &mut self, pc: u64, - machine: &mut DefaultMachine>, + machine: &mut DefaultMachine, ) -> Result<*const DynamicTrace, Error> { if let Some(trace) = self.dynamic_cache.get(&pc) { return Ok(trace.as_ref() as *const DynamicTrace); @@ -334,7 +330,7 @@ impl TraceDecoder for MemoizedDynamicTraceDecoder { fn prepare_traces( &mut self, - machine: &mut DefaultMachine>, + machine: &mut DefaultMachine, ) -> Result<(), Error> { let pc = *machine.pc(); let slot = calculate_slot(pc); @@ -374,6 +370,14 @@ impl TraceDecoder for MemoizedDynamicTraceDecoder { } impl InstDecoder for MemoizedDynamicTraceDecoder { + fn new(isa: u8, version: u32) -> Self { + Self { + inner: SimpleFixedTraceDecoder::new::(isa, version), + fixed_cache: HashMap::default(), + dynamic_cache: HashMap::default(), + } + } + fn decode(&mut self, memory: &mut M, pc: u64) -> Result { self.inner.decode(memory, pc) } diff --git a/src/machine/mod.rs b/src/machine/mod.rs index 7f8d4c68..7145cb23 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -3,20 +3,21 @@ pub mod asm; pub mod trace; use std::fmt::{self, Display}; +use std::marker::PhantomData; use std::sync::atomic::{AtomicU8, Ordering}; use std::sync::Arc; use bytes::Bytes; use super::debugger::Debugger; -use super::decoder::{build_decoder, InstDecoder}; +use super::decoder::{DefaultDecoder, InstDecoder}; use super::elf::{parse_elf, LoadingAction, ProgramMetadata}; use super::instructions::{execute, Instruction, Register}; use super::memory::{load_c_string_byte_by_byte, Memory}; use super::syscalls::Syscalls; use super::{ registers::{A0, A7, REGISTER_ABI_NAMES, SP}, - Error, ISA_MOP, RISCV_GENERAL_REGISTER_NUMBER, + Error, DEFAULT_MEMORY_SIZE, ISA_MOP, RISCV_GENERAL_REGISTER_NUMBER, }; // Version 0 is the initial launched CKB VM, it is used in CKB Lina mainnet @@ -62,6 +63,19 @@ pub trait Machine: CoreMachine { /// such as ELF range, cycles which might be needed on Rust side of the logic, /// such as runner or syscall implementations. pub trait SupportMachine: CoreMachine { + /// Instantiate using default memory size + fn new(isa: u8, version: u32, max_cycles: u64) -> Self + where + Self: Sized, + { + Self::new_with_memory(isa, version, max_cycles, DEFAULT_MEMORY_SIZE) + } + + /// Instantiation function + fn new_with_memory(isa: u8, version: u32, max_cycles: u64, memory_size: usize) -> Self + where + Self: Sized; + // Current execution cycles, it's up to the actual implementation to // call add_cycles for each instruction/operation to provide cycles. // The implementation might also choose not to do this to ignore this @@ -262,6 +276,58 @@ pub trait SupportMachine: CoreMachine { fn code(&self) -> &Bytes; } +/// A runner trait providing APIs to drive the included DefaultMachine +pub trait DefaultMachineRunner { + type Inner: SupportMachine; + type Decoder: InstDecoder; + + /// Creates a new runner + fn new(machine: DefaultMachine) -> Self; + + /// Fetches DefaultMachine + fn machine(&self) -> &DefaultMachine; + + /// Fetches mutable DefaultMachine + fn machine_mut(&mut self) -> &mut DefaultMachine; + + /// Runs the VM till paused with a custom decoder + fn run_with_decoder(&mut self, decoder: &mut Self::Decoder) -> Result; + + /// Runs the VM till paused + fn run(&mut self) -> Result { + let mut decoder = Self::Decoder::new::<::REG>( + self.machine().isa(), + self.machine().version(), + ); + self.run_with_decoder(&mut decoder) + } + + /// Fetches the inner SupportMachine for more processing + fn inner_mut(&mut self) -> &mut Self::Inner { + self.machine_mut().inner_mut() + } + + /// Loads program + fn load_program( + &mut self, + program: &Bytes, + args: impl ExactSizeIterator>, + ) -> Result { + self.machine_mut().load_program(program, args) + } + + /// Loads program with lazy loading metadata + fn load_program_with_metadata( + &mut self, + program: &Bytes, + metadata: &ProgramMetadata, + args: impl ExactSizeIterator>, + ) -> Result { + self.machine_mut() + .load_program_with_metadata(program, metadata, args) + } +} + #[derive(Default)] pub struct DefaultCoreMachine { registers: [R; RISCV_GENERAL_REGISTER_NUMBER], @@ -319,6 +385,23 @@ impl> CoreMachine for DefaultCoreMachine { } impl> SupportMachine for DefaultCoreMachine { + fn new_with_memory(isa: u8, version: u32, max_cycles: u64, memory_size: usize) -> Self { + Self { + registers: Default::default(), + pc: Default::default(), + next_pc: Default::default(), + reset_signal: Default::default(), + memory: M::new(memory_size), + cycles: Default::default(), + max_cycles, + running: Default::default(), + isa, + version, + #[cfg(feature = "pprof")] + code: Default::default(), + } + } + fn cycles(&self) -> u64 { self.cycles } @@ -338,7 +421,7 @@ impl> SupportMachine for DefaultCoreMachine Result<(), Error> { self.registers = Default::default(); self.pc = Default::default(); - self.memory.reset_memory()?; + self.memory = M::new(self.memory().memory_size()); self.cycles = 0; self.max_cycles = max_cycles; self.reset_signal = true; @@ -387,30 +470,7 @@ impl> SupportMachine for DefaultCoreMachine DefaultCoreMachine { - pub fn new(isa: u8, version: u32, max_cycles: u64) -> Self { - Self::new_with_memory(isa, version, max_cycles, M::default()) - } -} - impl DefaultCoreMachine { - pub fn new_with_memory(isa: u8, version: u32, max_cycles: u64, memory: M) -> Self { - Self { - registers: Default::default(), - pc: Default::default(), - next_pc: Default::default(), - reset_signal: Default::default(), - memory, - cycles: Default::default(), - max_cycles, - running: Default::default(), - isa, - version, - #[cfg(feature = "pprof")] - code: Default::default(), - } - } - pub fn set_max_cycles(&mut self, cycles: u64) { self.max_cycles = cycles; } @@ -422,7 +482,7 @@ impl DefaultCoreMachine { pub type InstructionCycleFunc = dyn Fn(Instruction) -> u64 + Send + Sync; -pub struct DefaultMachine { +pub struct DefaultMachine { inner: Inner, pause: Pause, @@ -434,9 +494,10 @@ pub struct DefaultMachine { debugger: Option>>, syscalls: Vec>>, exit_code: i8, + phantom: PhantomData, } -impl CoreMachine for DefaultMachine { +impl CoreMachine for DefaultMachine { type REG = ::REG; type MEM = ::MEM; @@ -477,7 +538,11 @@ impl CoreMachine for DefaultMachine { } } -impl SupportMachine for DefaultMachine { +impl SupportMachine for DefaultMachine { + fn new_with_memory(_isa: u8, _version: u32, _max_cycles: u64, _memory_size: usize) -> Self { + panic!("Please instantiate DefaultMachine using DefaultMachineBuilder!"); + } + fn cycles(&self) -> u64 { self.inner.cycles() } @@ -529,7 +594,7 @@ impl SupportMachine for DefaultMachine { } } -impl Machine for DefaultMachine { +impl Machine for DefaultMachine { fn ecall(&mut self) -> Result<(), Error> { let code = self.registers()[A7].to_u64(); match code { @@ -565,7 +630,7 @@ impl Machine for DefaultMachine { } } -impl Display for DefaultMachine { +impl Display for DefaultMachine { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { writeln!(f, "pc : 0x{:16X}", self.pc().to_u64())?; for (i, name) in REGISTER_ABI_NAMES.iter().enumerate() { @@ -580,7 +645,44 @@ impl Display for DefaultMachine { } } -impl DefaultMachine { +impl DefaultMachineRunner + for DefaultMachine +{ + type Inner = Inner; + type Decoder = Decoder; + + fn new(machine: DefaultMachine) -> Self { + machine + } + + fn machine(&self) -> &DefaultMachine { + self + } + + fn machine_mut(&mut self) -> &mut DefaultMachine { + self + } + + fn run_with_decoder(&mut self, decoder: &mut Self::Decoder) -> Result { + if self.isa() & ISA_MOP != 0 && self.version() == VERSION0 { + return Err(Error::InvalidVersion); + } + self.set_running(true); + while self.running() { + if self.pause.has_interrupted() { + self.pause.free(); + return Err(Error::Pause); + } + if self.reset_signal() { + decoder.reset_instructions_cache()?; + } + self.step(decoder)?; + } + Ok(self.exit_code()) + } +} + +impl DefaultMachine { pub fn load_program( &mut self, program: &Bytes, @@ -657,33 +759,6 @@ impl DefaultMachine { &mut self.inner } - // This is the most naive way of running the VM, it only decodes each - // instruction and run it, no optimization is performed here. It might - // not be practical in production, but it serves as a baseline and - // reference implementation - pub fn run(&mut self) -> Result { - let mut decoder = build_decoder::(self.isa(), self.version()); - self.run_with_decoder(&mut decoder) - } - - pub fn run_with_decoder(&mut self, decoder: &mut D) -> Result { - if self.isa() & ISA_MOP != 0 && self.version() == VERSION0 { - return Err(Error::InvalidVersion); - } - self.set_running(true); - while self.running() { - if self.pause.has_interrupted() { - self.pause.free(); - return Err(Error::Pause); - } - if self.reset_signal() { - decoder.reset_instructions_cache()?; - } - self.step(decoder)?; - } - Ok(self.exit_code()) - } - pub fn step(&mut self, decoder: &mut D) -> Result<(), Error> { let instruction = { let pc = self.pc().to_u64(); @@ -696,15 +771,19 @@ impl DefaultMachine { } } -pub struct DefaultMachineBuilder { +/// This builder only works with Rust VMs +pub type RustDefaultMachineBuilder = AbstractDefaultMachineBuilder; + +pub struct AbstractDefaultMachineBuilder { inner: Inner, instruction_cycle_func: Box, debugger: Option>>, syscalls: Vec>>, pause: Pause, + phantom: PhantomData, } -impl DefaultMachineBuilder { +impl AbstractDefaultMachineBuilder { pub fn new(inner: Inner) -> Self { Self { inner, @@ -712,6 +791,7 @@ impl DefaultMachineBuilder { debugger: None, syscalls: vec![], pause: Pause::new(), + phantom: PhantomData, } } @@ -738,7 +818,7 @@ impl DefaultMachineBuilder { self } - pub fn build(self) -> DefaultMachine { + pub fn build(self) -> DefaultMachine { DefaultMachine { inner: self.inner, pause: self.pause, @@ -746,6 +826,7 @@ impl DefaultMachineBuilder { debugger: self.debugger, syscalls: self.syscalls, exit_code: 0, + phantom: PhantomData, } } } diff --git a/src/machine/trace.rs b/src/machine/trace.rs index 7978272b..769896e3 100644 --- a/src/machine/trace.rs +++ b/src/machine/trace.rs @@ -1,6 +1,6 @@ use super::{ super::{ - decoder::{build_decoder, InstDecoder}, + decoder::{DefaultDecoder, InstDecoder}, elf::ProgramMetadata, instructions::{ execute_with_thread, extract_opcode, handle_invalid_op, instruction_length, @@ -8,7 +8,7 @@ use super::{ }, Error, }, - CoreMachine, DefaultMachine, Machine, SupportMachine, VERSION2, + CoreMachine, DefaultMachine, DefaultMachineRunner, Machine, SupportMachine, VERSION2, }; use bytes::Bytes; @@ -46,14 +46,16 @@ fn calculate_slot(addr: u64) -> usize { (addr as usize >> TRACE_ADDRESS_SHIFTS) & TRACE_MASK } -pub struct TraceMachine { - pub machine: DefaultMachine, +pub type TraceMachine = AbstractTraceMachine; - factory: ThreadFactory>, - traces: Vec>>, +pub struct AbstractTraceMachine { + pub machine: DefaultMachine, + + factory: ThreadFactory>, + traces: Vec>>, } -impl CoreMachine for TraceMachine { +impl CoreMachine for AbstractTraceMachine { type REG = ::REG; type MEM = ::MEM; @@ -94,7 +96,7 @@ impl CoreMachine for TraceMachine { } } -impl Machine for TraceMachine { +impl Machine for AbstractTraceMachine { fn ecall(&mut self) -> Result<(), Error> { self.machine.ecall() } @@ -104,8 +106,13 @@ impl Machine for TraceMachine { } } -impl TraceMachine { - pub fn new(machine: DefaultMachine) -> Self { +impl DefaultMachineRunner + for AbstractTraceMachine +{ + type Inner = Inner; + type Decoder = Decoder; + + fn new(machine: DefaultMachine) -> Self { Self { machine, factory: ThreadFactory::create(), @@ -113,34 +120,15 @@ impl TraceMachine { } } - pub fn load_program( - &mut self, - program: &Bytes, - args: impl ExactSizeIterator>, - ) -> Result { - self.machine.load_program(program, args) + fn machine(&self) -> &DefaultMachine { + &self.machine } - pub fn load_program_with_metadata( - &mut self, - program: &Bytes, - metadata: &ProgramMetadata, - args: impl ExactSizeIterator>, - ) -> Result { - self.machine - .load_program_with_metadata(program, metadata, args) + fn machine_mut(&mut self) -> &mut DefaultMachine { + &mut self.machine } - pub fn set_max_cycles(&mut self, cycles: u64) { - self.machine.inner_mut().set_max_cycles(cycles) - } - - pub fn run(&mut self) -> Result { - let mut decoder = build_decoder::(self.isa(), self.version()); - self.run_with_decoder(&mut decoder) - } - - pub fn run_with_decoder(&mut self, decoder: &mut D) -> Result { + fn run_with_decoder(&mut self, decoder: &mut Self::Decoder) -> Result { self.machine.set_running(true); // For current trace size this is acceptable, however we might want // to tweak the code here if we choose to use a larger trace size or @@ -199,6 +187,30 @@ impl TraceMachine { } } +impl AbstractTraceMachine { + pub fn load_program( + &mut self, + program: &Bytes, + args: impl ExactSizeIterator>, + ) -> Result { + self.machine.load_program(program, args) + } + + pub fn load_program_with_metadata( + &mut self, + program: &Bytes, + metadata: &ProgramMetadata, + args: impl ExactSizeIterator>, + ) -> Result { + self.machine + .load_program_with_metadata(program, metadata, args) + } + + pub fn set_max_cycles(&mut self, cycles: u64) { + self.machine.inner_mut().set_max_cycles(cycles) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/memory/flat.rs b/src/memory/flat.rs index 07160584..b7d6f541 100644 --- a/src/memory/flat.rs +++ b/src/memory/flat.rs @@ -1,6 +1,4 @@ -use super::super::{ - error::OutOfBoundKind, Error, Register, DEFAULT_MEMORY_SIZE, RISCV_PAGESIZE, RISCV_PAGE_SHIFTS, -}; +use super::super::{error::OutOfBoundKind, Error, Register, RISCV_PAGESIZE, RISCV_PAGE_SHIFTS}; use super::{check_no_overflow, fill_page_data, get_page_indices, memset, set_dirty, Memory}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; @@ -32,8 +30,12 @@ impl DerefMut for FlatMemory { } } -impl FlatMemory { - pub fn new_with_memory(memory_size: usize) -> Self { +/// A flat chunk of memory used for RISC-V machine, it lacks all the permission +/// checking logic. +impl Memory for FlatMemory { + type REG = R; + + fn new(memory_size: usize) -> Self { assert!(memory_size % RISCV_PAGESIZE == 0); Self { data: vec![0; memory_size], @@ -44,25 +46,6 @@ impl FlatMemory { _inner: PhantomData, } } -} - -impl Default for FlatMemory { - fn default() -> Self { - Self::new_with_memory(DEFAULT_MEMORY_SIZE) - } -} - -/// A flat chunk of memory used for RISC-V machine, it lacks all the permission -/// checking logic. -impl Memory for FlatMemory { - type REG = R; - - fn reset_memory(&mut self) -> Result<(), Error> { - memset(&mut self.data, 0); - memset(&mut self.flags, 0); - self.load_reservation_address = R::from_u64(u64::MAX); - Ok(()) - } fn init_pages( &mut self, diff --git a/src/memory/mod.rs b/src/memory/mod.rs index e184497d..d72349d0 100644 --- a/src/memory/mod.rs +++ b/src/memory/mod.rs @@ -31,7 +31,7 @@ pub type Page = [u8; RISCV_PAGESIZE]; pub trait Memory { type REG: Register; - fn reset_memory(&mut self) -> Result<(), Error>; + fn new(memory_size: usize) -> Self; fn init_pages( &mut self, diff --git a/src/memory/sparse.rs b/src/memory/sparse.rs index 09cf9178..8c4d54ba 100644 --- a/src/memory/sparse.rs +++ b/src/memory/sparse.rs @@ -1,6 +1,4 @@ -use super::super::{ - error::OutOfBoundKind, Error, Register, DEFAULT_MEMORY_SIZE, RISCV_PAGESIZE, RISCV_PAGE_SHIFTS, -}; +use super::super::{error::OutOfBoundKind, Error, Register, RISCV_PAGESIZE, RISCV_PAGE_SHIFTS}; use super::{check_no_overflow, fill_page_data, memset, round_page_down, Memory, Page, FLAG_DIRTY}; use bytes::Bytes; @@ -67,8 +65,12 @@ impl SparseMemory { } Ok(value) } +} + +impl Memory for SparseMemory { + type REG = R; - pub fn new_with_memory(memory_size: usize) -> Self { + fn new(memory_size: usize) -> Self { assert!(memory_size % RISCV_PAGESIZE == 0); Self { indices: vec![INVALID_PAGE_INDEX; memory_size / RISCV_PAGESIZE], @@ -80,24 +82,6 @@ impl SparseMemory { _inner: PhantomData, } } -} - -impl Default for SparseMemory { - fn default() -> Self { - Self::new_with_memory(DEFAULT_MEMORY_SIZE) - } -} - -impl Memory for SparseMemory { - type REG = R; - - fn reset_memory(&mut self) -> Result<(), Error> { - self.indices = vec![INVALID_PAGE_INDEX; self.indices.len()]; - memset(&mut self.flags, 0); - self.pages.clear(); - self.load_reservation_address = R::from_u64(u64::MAX); - Ok(()) - } fn init_pages( &mut self, diff --git a/src/memory/wxorx.rs b/src/memory/wxorx.rs index 8d773852..e1993c25 100644 --- a/src/memory/wxorx.rs +++ b/src/memory/wxorx.rs @@ -14,23 +14,15 @@ impl WXorXMemory { pub fn inner_mut(&mut self) -> &mut M { &mut self.inner } - - pub fn new(inner: M) -> Self { - Self { inner } - } -} - -impl Default for WXorXMemory { - fn default() -> Self { - Self::new(M::default()) - } } impl Memory for WXorXMemory { type REG = M::REG; - fn reset_memory(&mut self) -> Result<(), Error> { - self.inner.reset_memory() + fn new(memory_size: usize) -> Self { + Self { + inner: M::new(memory_size), + } } fn init_pages( diff --git a/tests/machine_build.rs b/tests/machine_build.rs index 2c50704f..00742108 100644 --- a/tests/machine_build.rs +++ b/tests/machine_build.rs @@ -1,11 +1,12 @@ use bytes::Bytes; use ckb_vm::cost_model::constant_cycles; #[cfg(has_asm)] -use ckb_vm::machine::asm::{AsmCoreMachine, AsmMachine}; +use ckb_vm::machine::asm::{AsmCoreMachine, AsmDefaultMachineBuilder, AsmMachine}; use ckb_vm::machine::{trace::TraceMachine, DefaultCoreMachine}; use ckb_vm::registers::{A0, A7}; use ckb_vm::{ - DefaultMachineBuilder, Error, Register, SparseMemory, SupportMachine, Syscalls, WXorXMemory, + DefaultMachineRunner, Error, Register, RustDefaultMachineBuilder, SparseMemory, SupportMachine, + Syscalls, WXorXMemory, }; pub struct SleepSyscall {} @@ -32,7 +33,7 @@ impl Syscalls for SleepSyscall { pub fn asm(path: &str, args: Vec, version: u32, isa: u8) -> AsmMachine { let buffer: Bytes = std::fs::read(path).unwrap().into(); let asm_core = AsmCoreMachine::new(isa, version, u64::MAX); - let core = DefaultMachineBuilder::>::new(asm_core) + let core = AsmDefaultMachineBuilder::new(asm_core) .instruction_cycle_func(Box::new(constant_cycles)) .syscall(Box::new(SleepSyscall {})) .build(); @@ -53,7 +54,7 @@ pub fn int( let core_machine = DefaultCoreMachine::>>::new(isa, version, u64::MAX); let mut machine = TraceMachine::new( - DefaultMachineBuilder::new(core_machine) + RustDefaultMachineBuilder::new(core_machine) .instruction_cycle_func(Box::new(constant_cycles)) .syscall(Box::new(SleepSyscall {})) .build(), diff --git a/tests/test_a_extension.rs b/tests/test_a_extension.rs index 9ea49d2e..1e8afe41 100644 --- a/tests/test_a_extension.rs +++ b/tests/test_a_extension.rs @@ -1,4 +1,4 @@ -use ckb_vm::{machine::VERSION2, Error, ISA_A, ISA_IMC}; +use ckb_vm::{machine::VERSION2, DefaultMachineRunner, Error, ISA_A, ISA_IMC}; #[cfg(has_asm)] use ckb_vm::{CoreMachine, Memory}; pub mod machine_build; diff --git a/tests/test_asm.rs b/tests/test_asm.rs index d57a63e4..f6a8586b 100644 --- a/tests/test_asm.rs +++ b/tests/test_asm.rs @@ -1,13 +1,17 @@ #![cfg(has_asm)] use ckb_vm::cost_model::constant_cycles; -use ckb_vm::decoder::build_decoder; +use ckb_vm::decoder::{DefaultDecoder, InstDecoder}; use ckb_vm::error::OutOfBoundKind; -use ckb_vm::machine::asm::traces::{MemoizedDynamicTraceDecoder, MemoizedFixedTraceDecoder}; -use ckb_vm::machine::asm::{AsmCoreMachine, AsmMachine}; -use ckb_vm::machine::{CoreMachine, VERSION0, VERSION1, VERSION2}; +use ckb_vm::machine::asm::traces::{ + MemoizedDynamicTraceDecoder, MemoizedFixedTraceDecoder, SimpleFixedTraceDecoder, +}; +use ckb_vm::machine::asm::{ + AbstractAsmMachine, AsmCoreMachine, AsmDefaultMachineBuilder, AsmMachine, +}; +use ckb_vm::machine::{AbstractDefaultMachineBuilder, CoreMachine, VERSION0, VERSION1, VERSION2}; use ckb_vm::memory::Memory; use ckb_vm::registers::{A0, A1, A2, A3, A4, A5, A7}; -use ckb_vm::{Debugger, DefaultMachineBuilder, Error, Register, SupportMachine, Syscalls, ISA_IMC}; +use ckb_vm::{Debugger, DefaultMachineRunner, Error, Register, SupportMachine, Syscalls, ISA_IMC}; use std::fs; use std::sync::atomic::{AtomicU8, Ordering}; use std::sync::Arc; @@ -17,8 +21,8 @@ pub mod machine_build; #[test] pub fn test_asm_simple64() { let buffer = fs::read("tests/programs/simple64").unwrap().into(); - let asm_core = AsmCoreMachine::new(ISA_IMC, VERSION0, u64::MAX); - let core = DefaultMachineBuilder::new(asm_core).build(); + let asm_core = ::new(ISA_IMC, VERSION0, u64::MAX); + let core = AsmDefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine .load_program(&buffer, [Ok("simple".into())].into_iter()) @@ -54,8 +58,8 @@ impl Syscalls for CustomSyscall { #[test] pub fn test_asm_with_custom_syscall() { let buffer = fs::read("tests/programs/syscall64").unwrap().into(); - let asm_core = AsmCoreMachine::new(ISA_IMC, VERSION0, u64::MAX); - let core = DefaultMachineBuilder::new(asm_core) + let asm_core = ::new(ISA_IMC, VERSION0, u64::MAX); + let core = AsmDefaultMachineBuilder::new(asm_core) .syscall(Box::new(CustomSyscall {})) .build(); let mut machine = AsmMachine::new(core); @@ -88,8 +92,8 @@ pub fn test_asm_ebreak() { let buffer = fs::read("tests/programs/ebreak64").unwrap().into(); let value = Arc::new(AtomicU8::new(0)); - let asm_core = AsmCoreMachine::new(ISA_IMC, VERSION0, u64::MAX); - let core = DefaultMachineBuilder::new(asm_core) + let asm_core = ::new(ISA_IMC, VERSION0, u64::MAX); + let core = AsmDefaultMachineBuilder::new(asm_core) .debugger(Box::new(CustomDebugger { value: Arc::clone(&value), })) @@ -107,8 +111,8 @@ pub fn test_asm_ebreak() { #[test] pub fn test_asm_simple_cycles() { let buffer = fs::read("tests/programs/simple64").unwrap().into(); - let asm_core = AsmCoreMachine::new(ISA_IMC, VERSION0, 708); - let core = DefaultMachineBuilder::new(asm_core) + let asm_core = ::new(ISA_IMC, VERSION0, 708); + let core = AsmDefaultMachineBuilder::new(asm_core) .instruction_cycle_func(Box::new(constant_cycles)) .build(); let mut machine = AsmMachine::new(core); @@ -126,8 +130,8 @@ pub fn test_asm_simple_cycles() { pub fn test_asm_simple_max_cycles_reached() { let buffer = fs::read("tests/programs/simple64").unwrap().into(); // Running simple64 should consume 708 cycles using dummy cycle func - let asm_core = AsmCoreMachine::new(ISA_IMC, VERSION0, 700); - let core = DefaultMachineBuilder::>::new(asm_core) + let asm_core = ::new(ISA_IMC, VERSION0, 700); + let core = AsmDefaultMachineBuilder::new(asm_core) .instruction_cycle_func(Box::new(constant_cycles)) .build(); let mut machine = AsmMachine::new(core); @@ -142,8 +146,8 @@ pub fn test_asm_simple_max_cycles_reached() { #[test] pub fn test_asm_trace() { let buffer = fs::read("tests/programs/trace64").unwrap().into(); - let asm_core = AsmCoreMachine::new(ISA_IMC, VERSION0, u64::MAX); - let core = DefaultMachineBuilder::new(asm_core).build(); + let asm_core = ::new(ISA_IMC, VERSION0, u64::MAX); + let core = AsmDefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine .load_program(&buffer, [Ok("simple".into())].into_iter()) @@ -156,8 +160,8 @@ pub fn test_asm_trace() { #[test] pub fn test_asm_jump0() { let buffer = fs::read("tests/programs/jump0_64").unwrap().into(); - let asm_core = AsmCoreMachine::new(ISA_IMC, VERSION0, u64::MAX); - let core = DefaultMachineBuilder::new(asm_core).build(); + let asm_core = ::new(ISA_IMC, VERSION0, u64::MAX); + let core = AsmDefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine .load_program(&buffer, [Ok("jump0_64".into())].into_iter()) @@ -172,8 +176,8 @@ pub fn test_asm_write_large_address() { let buffer = fs::read("tests/programs/write_large_address64") .unwrap() .into(); - let asm_core = AsmCoreMachine::new(ISA_IMC, VERSION0, u64::MAX); - let core = DefaultMachineBuilder::new(asm_core).build(); + let asm_core = ::new(ISA_IMC, VERSION0, u64::MAX); + let core = AsmDefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine .load_program(&buffer, [Ok("write_large_address64".into())].into_iter()) @@ -189,8 +193,8 @@ pub fn test_asm_write_large_address() { #[test] pub fn test_misaligned_jump64() { let buffer = fs::read("tests/programs/misaligned_jump64").unwrap().into(); - let asm_core = AsmCoreMachine::new(ISA_IMC, VERSION0, u64::MAX); - let core = DefaultMachineBuilder::new(asm_core).build(); + let asm_core = ::new(ISA_IMC, VERSION0, u64::MAX); + let core = AsmDefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine .load_program(&buffer, [Ok("misaligned_jump64".into())].into_iter()) @@ -202,8 +206,8 @@ pub fn test_misaligned_jump64() { #[test] pub fn test_mulw64() { let buffer = fs::read("tests/programs/mulw64").unwrap().into(); - let asm_core = AsmCoreMachine::new(ISA_IMC, VERSION0, u64::MAX); - let core = DefaultMachineBuilder::new(asm_core).build(); + let asm_core = ::new(ISA_IMC, VERSION0, u64::MAX); + let core = AsmDefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine .load_program(&buffer, [Ok("mulw64".into())].into_iter()) @@ -216,8 +220,8 @@ pub fn test_mulw64() { #[test] pub fn test_invalid_read64() { let buffer = fs::read("tests/programs/invalid_read64").unwrap().into(); - let asm_core = AsmCoreMachine::new(ISA_IMC, VERSION0, u64::MAX); - let core = DefaultMachineBuilder::new(asm_core).build(); + let asm_core = ::new(ISA_IMC, VERSION0, u64::MAX); + let core = AsmDefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine .load_program(&buffer, [Ok("invalid_read64".into())].into_iter()) @@ -236,8 +240,8 @@ pub fn test_invalid_read64() { #[test] pub fn test_asm_load_elf_crash_64() { let buffer = fs::read("tests/programs/load_elf_crash_64").unwrap().into(); - let asm_core = AsmCoreMachine::new(ISA_IMC, VERSION0, u64::MAX); - let core = DefaultMachineBuilder::new(asm_core).build(); + let asm_core = ::new(ISA_IMC, VERSION0, u64::MAX); + let core = AsmDefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine .load_program(&buffer, [Ok("load_elf_crash_64".into())].into_iter()) @@ -249,8 +253,8 @@ pub fn test_asm_load_elf_crash_64() { #[test] pub fn test_asm_wxorx_crash_64() { let buffer = fs::read("tests/programs/wxorx_crash_64").unwrap().into(); - let asm_core = AsmCoreMachine::new(ISA_IMC, VERSION0, u64::MAX); - let core = DefaultMachineBuilder::new(asm_core).build(); + let asm_core = ::new(ISA_IMC, VERSION0, u64::MAX); + let core = AsmDefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine .load_program(&buffer, [Ok("wxorx_crash_64".into())].into_iter()) @@ -268,8 +272,8 @@ pub fn test_asm_wxorx_crash_64() { #[test] pub fn test_asm_alloc_many() { let buffer = fs::read("tests/programs/alloc_many").unwrap().into(); - let asm_core = AsmCoreMachine::new(ISA_IMC, VERSION0, u64::MAX); - let core = DefaultMachineBuilder::new(asm_core).build(); + let asm_core = ::new(ISA_IMC, VERSION0, u64::MAX); + let core = AsmDefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine .load_program(&buffer, [Ok("alloc_many".into())].into_iter()) @@ -281,10 +285,10 @@ pub fn test_asm_alloc_many() { #[test] pub fn test_asm_chaos_seed() { let buffer = fs::read("tests/programs/read_memory").unwrap().into(); - let mut asm_core1 = AsmCoreMachine::new(ISA_IMC, VERSION1, u64::MAX); + let mut asm_core1 = ::new(ISA_IMC, VERSION1, u64::MAX); asm_core1.chaos_mode = 1; asm_core1.chaos_seed = 100; - let core1 = DefaultMachineBuilder::>::new(asm_core1).build(); + let core1 = AsmDefaultMachineBuilder::new(asm_core1).build(); let mut machine1 = AsmMachine::new(core1); machine1 .load_program(&buffer, [Ok("read_memory".into())].into_iter()) @@ -292,10 +296,10 @@ pub fn test_asm_chaos_seed() { let result1 = machine1.run(); let exit1 = result1.unwrap(); - let mut asm_core2 = AsmCoreMachine::new(ISA_IMC, VERSION1, u64::MAX); + let mut asm_core2 = ::new(ISA_IMC, VERSION1, u64::MAX); asm_core2.chaos_mode = 1; asm_core2.chaos_seed = 100; - let core2 = DefaultMachineBuilder::>::new(asm_core2).build(); + let core2 = AsmDefaultMachineBuilder::new(asm_core2).build(); let mut machine2 = AsmMachine::new(core2); machine2 .load_program(&buffer, [Ok("read_memory".into())].into_iter()) @@ -312,8 +316,8 @@ pub fn test_asm_chaos_seed() { #[test] pub fn test_asm_rvc_pageend() { let buffer = fs::read("tests/programs/rvc_pageend").unwrap().into(); - let asm_core = AsmCoreMachine::new(ISA_IMC, VERSION0, u64::MAX); - let core = DefaultMachineBuilder::new(asm_core).build(); + let asm_core = ::new(ISA_IMC, VERSION0, u64::MAX); + let core = AsmDefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine .load_program(&buffer, [Ok("rvc_pageend".into())].into_iter()) @@ -350,8 +354,8 @@ impl Syscalls for OutOfCyclesSyscall { #[test] pub fn test_asm_outofcycles_in_syscall() { let buffer = fs::read("tests/programs/syscall64").unwrap().into(); - let asm_core = AsmCoreMachine::new(ISA_IMC, VERSION0, 20); - let core = DefaultMachineBuilder::new(asm_core) + let asm_core = ::new(ISA_IMC, VERSION0, 20); + let core = AsmDefaultMachineBuilder::new(asm_core) .instruction_cycle_func(Box::new(constant_cycles)) .syscall(Box::new(OutOfCyclesSyscall {})) .build(); @@ -369,8 +373,8 @@ pub fn test_asm_outofcycles_in_syscall() { #[test] pub fn test_asm_cycles_overflow() { let buffer = fs::read("tests/programs/simple64").unwrap().into(); - let asm_core = AsmCoreMachine::new(ISA_IMC, VERSION0, u64::MAX); - let core = DefaultMachineBuilder::>::new(asm_core) + let asm_core = ::new(ISA_IMC, VERSION0, u64::MAX); + let core = AsmDefaultMachineBuilder::new(asm_core) .instruction_cycle_func(Box::new(constant_cycles)) .build(); let mut machine = AsmMachine::new(core); @@ -388,8 +392,8 @@ pub fn test_decoder_instructions_cache_pc_out_of_bound_timeout() { let buffer = fs::read("tests/programs/decoder_instructions_cache_pc_out_of_bound_timeout") .unwrap() .into(); - let asm_core = AsmCoreMachine::new(ISA_IMC, VERSION0, u64::MAX); - let core = DefaultMachineBuilder::>::new(asm_core) + let asm_core = ::new(ISA_IMC, VERSION0, u64::MAX); + let core = AsmDefaultMachineBuilder::new(asm_core) .instruction_cycle_func(Box::new(constant_cycles)) .build(); let mut machine = AsmMachine::new(core); @@ -408,15 +412,15 @@ pub fn test_decoder_instructions_cache_pc_out_of_bound_timeout() { #[test] fn test_asm_step() { let buffer = fs::read("tests/programs/simple64").unwrap().into(); - let asm_core = AsmCoreMachine::new(ISA_IMC, VERSION0, u64::MAX); - let core = DefaultMachineBuilder::new(asm_core).build(); + let asm_core = ::new(ISA_IMC, VERSION0, u64::MAX); + let core = AsmDefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine .load_program(&buffer, [Ok("simple64".into())].into_iter()) .unwrap(); let result = || -> Result { - let mut decoder = build_decoder::(ISA_IMC, VERSION0); + let mut decoder = SimpleFixedTraceDecoder::new::(ISA_IMC, VERSION0); machine.machine.set_running(true); while machine.machine.running() { machine.step(&mut decoder)?; @@ -431,8 +435,8 @@ fn test_asm_step() { #[test] fn test_asm_thread_safe() { let buffer = fs::read("tests/programs/mulw64").unwrap().into(); - let asm_core = AsmCoreMachine::new(ISA_IMC, VERSION0, u64::MAX); - let core = DefaultMachineBuilder::new(asm_core).build(); + let asm_core = ::new(ISA_IMC, VERSION0, u64::MAX); + let core = AsmDefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine .load_program(&buffer, [Ok("mulw64".into())].into_iter()) @@ -448,8 +452,8 @@ fn test_asm_thread_safe() { #[test] fn test_zero_address() { let buffer = fs::read("tests/programs/zero_address").unwrap().into(); - let asm_core = AsmCoreMachine::new(ISA_IMC, VERSION1, u64::MAX); - let core = DefaultMachineBuilder::new(asm_core).build(); + let asm_core = ::new(ISA_IMC, VERSION1, u64::MAX); + let core = AsmDefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine .load_program(&buffer, [Ok("zero".into())].into_iter()) @@ -464,9 +468,12 @@ fn test_memoized_secp256k1() { let isa = ISA_IMC; let version = VERSION1; let buffer = fs::read("benches/data/secp256k1_bench").unwrap().into(); - let asm_core = AsmCoreMachine::new(isa, version, u64::MAX); - let core = DefaultMachineBuilder::new(asm_core).build(); - let mut machine = AsmMachine::new(core); + let asm_core = ::new(isa, version, u64::MAX); + let core = AbstractDefaultMachineBuilder::<_, MemoizedFixedTraceDecoder>::new( + asm_core, + ) + .build(); + let mut machine = AbstractAsmMachine::new(core); let args = [ "secp256k1_bench", "033f8cf9c4d51a33206a6c1c6b27d2cc5129daa19dbd1fc148d395284f6b26411f", @@ -475,7 +482,7 @@ fn test_memoized_secp256k1() { "bar", ].into_iter().map(|a| Ok(a.into())); machine.load_program(&buffer, args).unwrap(); - let mut decoder = MemoizedFixedTraceDecoder::new(build_decoder::(isa, version)); + let mut decoder = MemoizedFixedTraceDecoder::new::(isa, version); let result = machine.run_with_decoder(&mut decoder); assert_eq!(result.unwrap(), 0); } @@ -485,9 +492,13 @@ fn test_memoized_dynamic_secp256k1() { let isa = ISA_IMC; let version = VERSION1; let buffer = fs::read("benches/data/secp256k1_bench").unwrap().into(); - let asm_core = AsmCoreMachine::new(isa, version, u64::MAX); - let core = DefaultMachineBuilder::new(asm_core).build(); - let mut machine = AsmMachine::new(core); + let asm_core = ::new(isa, version, u64::MAX); + let core = + AbstractDefaultMachineBuilder::<_, MemoizedDynamicTraceDecoder>::new( + asm_core, + ) + .build(); + let mut machine = AbstractAsmMachine::new(core); let args = [ "secp256k1_bench", "033f8cf9c4d51a33206a6c1c6b27d2cc5129daa19dbd1fc148d395284f6b26411f", @@ -496,7 +507,7 @@ fn test_memoized_dynamic_secp256k1() { "bar", ].into_iter().map(|a| Ok(a.into())); machine.load_program(&buffer, args).unwrap(); - let mut decoder = MemoizedDynamicTraceDecoder::new(build_decoder::(isa, version)); + let mut decoder = MemoizedDynamicTraceDecoder::new::(isa, version); let result = machine.run_with_decoder(&mut decoder); assert_eq!(result.unwrap(), 0); } @@ -504,8 +515,13 @@ fn test_memoized_dynamic_secp256k1() { #[test] pub fn test_big_binary() { let buffer = fs::read("tests/programs/big_binary").unwrap().into(); - let asm_core = AsmCoreMachine::new_with_memory(ISA_IMC, VERSION2, u64::MAX, 1024 * 512); - let core = DefaultMachineBuilder::new(asm_core).build(); + let asm_core = ::new_with_memory( + ISA_IMC, + VERSION2, + u64::MAX, + 1024 * 512, + ); + let core = AsmDefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); let result = machine.load_program(&buffer, [Ok("simple".into())].into_iter()); assert_eq!( @@ -520,8 +536,8 @@ fn test_fast_memory_initialization_bug() { let isa = ISA_IMC; let version = VERSION1; let buffer = fs::read("benches/data/secp256k1_bench").unwrap().into(); - let asm_core = AsmCoreMachine::new(isa, version, u64::MAX); - let core = DefaultMachineBuilder::new(asm_core).build(); + let asm_core = ::new(isa, version, u64::MAX); + let core = AsmDefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); unsafe { let memory = machine.machine.inner_mut().memory_ptr as *mut u8; @@ -534,8 +550,8 @@ fn test_fast_memory_initialization_bug() { #[test] pub fn test_memory_load_crash() { let buffer = fs::read("tests/programs/memory_crash").unwrap().into(); - let asm_core = AsmCoreMachine::new(ISA_IMC, VERSION0, u64::MAX); - let core = DefaultMachineBuilder::new(asm_core).build(); + let asm_core = ::new(ISA_IMC, VERSION0, u64::MAX); + let core = AsmDefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); let result = machine.load_program(&buffer, [Ok("memory_crash".into())].into_iter()); assert_eq!(result.unwrap_err(), Error::MemWriteOnExecutablePage(1023)); diff --git a/tests/test_auipc_fusion.rs b/tests/test_auipc_fusion.rs index 65e287c0..b8723a6e 100644 --- a/tests/test_auipc_fusion.rs +++ b/tests/test_auipc_fusion.rs @@ -1,28 +1,29 @@ -use ckb_vm::decoder::{build_decoder, Decoder, InstDecoder}; +use ckb_vm::decoder::{DefaultDecoder, InstDecoder}; use ckb_vm::instructions::{ extract_opcode, instruction_length, set_instruction_length_n, Instruction, Utype, }; #[cfg(has_asm)] -use ckb_vm::machine::asm::{traces::SimpleFixedTraceDecoder, AsmCoreMachine, AsmMachine}; +use ckb_vm::machine::asm::{traces::SimpleFixedTraceDecoder, AbstractAsmMachine, AsmCoreMachine}; use ckb_vm::machine::VERSION1; use ckb_vm::{ - CoreMachine, DefaultCoreMachine, DefaultMachineBuilder, Error, Memory, SparseMemory, ISA_IMC, + machine::AbstractDefaultMachineBuilder, CoreMachine, DefaultCoreMachine, DefaultMachineRunner, + Error, Memory, Register, SparseMemory, SupportMachine, ISA_IMC, }; use ckb_vm_definitions::instructions as insts; use std::fs; // This is simplified from https://github.com/xxuejie/ckb-vm-contrib/blob/main/src/decoder.rs pub struct AuxDecoder { - inner: Decoder, + inner: DefaultDecoder, } -impl AuxDecoder { - pub fn new(inner: Decoder) -> Self { - Self { inner } +impl InstDecoder for AuxDecoder { + fn new(isa: u8, version: u32) -> Self { + Self { + inner: DefaultDecoder::new::(isa, version), + } } -} -impl InstDecoder for AuxDecoder { fn decode(&mut self, memory: &mut M, pc: u64) -> Result { let head_inst = self.inner.decode(memory, pc)?; match extract_opcode(head_inst) { @@ -56,12 +57,12 @@ pub fn test_rust_auipc_fusion() { let core_machine = DefaultCoreMachine::>::new(ISA_IMC, VERSION1, u64::MAX); - let mut machine = DefaultMachineBuilder::new(core_machine).build(); + let mut machine = AbstractDefaultMachineBuilder::<_, AuxDecoder>::new(core_machine).build(); machine .load_program(&buffer, [Ok("auipc_no_sign_extend".into())].into_iter()) .unwrap(); - let mut decoder = AuxDecoder::new(build_decoder::(machine.isa(), machine.version())); + let mut decoder = AuxDecoder::new::(machine.isa(), machine.version()); let result = machine.run_with_decoder(&mut decoder).unwrap(); assert_eq!(result, 0); } @@ -73,18 +74,19 @@ pub fn test_asm_auipc_fusion() { .unwrap() .into(); - let asm_core = AsmCoreMachine::new(ISA_IMC, VERSION1, u64::MAX); - let core = DefaultMachineBuilder::>::new(asm_core).build(); - let mut machine = AsmMachine::new(core); + let asm_core = ::new(ISA_IMC, VERSION1, u64::MAX); + let core = + AbstractDefaultMachineBuilder::<_, SimpleFixedTraceDecoder>::new(asm_core) + .build(); + let mut machine = AbstractAsmMachine::new(core); machine .load_program(&buffer, [Ok("auipc_no_sign_extend".into())].into_iter()) .unwrap(); - let decoder = AuxDecoder::new(build_decoder::( + let mut decoder = SimpleFixedTraceDecoder::::new::( machine.machine.isa(), machine.machine.version(), - )); - let mut decoder = SimpleFixedTraceDecoder::new(decoder); + ); let result = machine.run_with_decoder(&mut decoder).expect("run"); assert_eq!(result, 0); diff --git a/tests/test_b_extension.rs b/tests/test_b_extension.rs index bab7d931..346ee31f 100644 --- a/tests/test_b_extension.rs +++ b/tests/test_b_extension.rs @@ -2,6 +2,8 @@ use ckb_vm::{machine::VERSION1, ISA_B, ISA_IMC}; pub mod machine_build; +use ckb_vm::DefaultMachineRunner; + #[test] pub fn test_clzw_bug() { let mut machine = diff --git a/tests/test_dy_memory.rs b/tests/test_dy_memory.rs index 21094e12..81a83b2a 100644 --- a/tests/test_dy_memory.rs +++ b/tests/test_dy_memory.rs @@ -2,10 +2,10 @@ use ckb_vm::{error::OutOfBoundKind, run_with_memory, FlatMemory, SparseMemory}; #[cfg(has_asm)] use ckb_vm::{ machine::{ - asm::{AsmCoreMachine, AsmMachine}, - DefaultMachineBuilder, VERSION0, VERSION2, + asm::{AsmCoreMachine, AsmDefaultMachineBuilder, AsmMachine}, + VERSION0, VERSION2, }, - ISA_B, ISA_IMC, ISA_MOP, + DefaultMachineRunner, SupportMachine, ISA_B, ISA_IMC, ISA_MOP, }; use std::fs; @@ -14,7 +14,7 @@ fn run_memory_suc(memory_size: usize, bin_path: String, bin_name: String) { let result = run_with_memory::>( &buffer, &vec![bin_name.clone().into()], - SparseMemory::new_with_memory(memory_size), + memory_size, ); assert!(result.is_ok()); assert_eq!(result.unwrap(), 0); @@ -22,7 +22,7 @@ fn run_memory_suc(memory_size: usize, bin_path: String, bin_name: String) { let result = run_with_memory::>( &buffer, &vec![bin_name.clone().into()], - FlatMemory::new_with_memory(memory_size), + memory_size, ); assert!(result.is_ok()); assert_eq!(result.unwrap(), 0); @@ -30,7 +30,7 @@ fn run_memory_suc(memory_size: usize, bin_path: String, bin_name: String) { #[cfg(has_asm)] { let asm_core = AsmCoreMachine::new_with_memory(ISA_IMC, VERSION0, u64::MAX, memory_size); - let core = DefaultMachineBuilder::new(asm_core).build(); + let core = AsmDefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine .load_program(&buffer, [Ok(bin_name.into())].into_iter()) @@ -54,22 +54,16 @@ fn test_dy_memory() { fn test_memory_out_of_bounds() { let memory_size = 1024 * 256; let buffer = fs::read("tests/programs/alloc_many").unwrap().into(); - let result = run_with_memory::>( - &buffer, - &vec!["alloc_many".into()], - SparseMemory::new_with_memory(memory_size), - ); + let result = + run_with_memory::>(&buffer, &vec!["alloc_many".into()], memory_size); assert!(result.is_err()); assert_eq!( ckb_vm::Error::MemOutOfBound(0xfffffffffff3ffb8, OutOfBoundKind::Memory), result.err().unwrap() ); - let result = run_with_memory::>( - &buffer, - &vec!["alloc_many".into()], - FlatMemory::new_with_memory(memory_size), - ); + let result = + run_with_memory::>(&buffer, &vec!["alloc_many".into()], memory_size); assert!(result.is_err()); assert_eq!( ckb_vm::Error::MemOutOfBound(0xfffffffffff3ffb8, OutOfBoundKind::Memory), @@ -84,7 +78,7 @@ fn test_memory_out_of_bounds() { u64::MAX, memory_size, ); - let core = DefaultMachineBuilder::new(asm_core).build(); + let core = AsmDefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine .load_program(&buffer, [Ok("alloc_many".into())].into_iter()) diff --git a/tests/test_misc.rs b/tests/test_misc.rs index 3d36f2fe..dad1cb00 100644 --- a/tests/test_misc.rs +++ b/tests/test_misc.rs @@ -3,9 +3,9 @@ use ckb_vm::error::OutOfBoundKind; use ckb_vm::machine::{VERSION0, VERSION1, VERSION2}; use ckb_vm::registers::{A0, A1, A2, A3, A4, A5, A7}; use ckb_vm::{ - run, CoreMachine, Debugger, DefaultCoreMachine, DefaultMachineBuilder, Error, FlatMemory, - Memory, Register, SparseMemory, SupportMachine, Syscalls, WXorXMemory, DEFAULT_MEMORY_SIZE, - ISA_B, ISA_IMC, RISCV_PAGESIZE, + run, CoreMachine, Debugger, DefaultCoreMachine, DefaultMachineRunner, Error, FlatMemory, + Memory, Register, RustDefaultMachineBuilder, SparseMemory, SupportMachine, Syscalls, + WXorXMemory, DEFAULT_MEMORY_SIZE, ISA_B, ISA_IMC, RISCV_PAGESIZE, }; #[cfg(has_asm)] use ckb_vm_definitions::asm::AsmCoreMachine; @@ -59,7 +59,7 @@ pub fn test_custom_syscall() { let buffer = fs::read("tests/programs/syscall64").unwrap().into(); let core_machine = DefaultCoreMachine::>::new(ISA_IMC, VERSION0, u64::MAX); - let mut machine = DefaultMachineBuilder::new(core_machine) + let mut machine = RustDefaultMachineBuilder::new(core_machine) .syscall(Box::new(CustomSyscall {})) .build(); machine @@ -92,7 +92,7 @@ pub fn test_ebreak() { let value = Arc::new(AtomicU8::new(0)); let core_machine = DefaultCoreMachine::>::new(ISA_IMC, VERSION0, u64::MAX); - let mut machine = DefaultMachineBuilder::new(core_machine) + let mut machine = RustDefaultMachineBuilder::new(core_machine) .debugger(Box::new(CustomDebugger { value: Arc::clone(&value), })) @@ -202,7 +202,7 @@ pub fn test_wxorx_crash_64() { pub fn test_flat_crash_64() { let buffer = fs::read("tests/programs/flat_crash_64").unwrap().into(); let core_machine = DefaultCoreMachine::>::new(ISA_IMC, VERSION0, u64::MAX); - let mut machine = DefaultMachineBuilder::new(core_machine).build(); + let mut machine = RustDefaultMachineBuilder::new(core_machine).build(); let result = machine.load_program(&buffer, [Ok("flat_crash_64".into())].into_iter()); assert_eq!( result.err(), @@ -212,11 +212,15 @@ pub fn test_flat_crash_64() { #[test] pub fn test_memory_store_empty_bytes() { - assert_memory_store_empty_bytes(&mut FlatMemory::::default()); - assert_memory_store_empty_bytes(&mut SparseMemory::::default()); - assert_memory_store_empty_bytes(&mut WXorXMemory::>::default()); + assert_memory_store_empty_bytes(&mut FlatMemory::::new(DEFAULT_MEMORY_SIZE)); + assert_memory_store_empty_bytes(&mut SparseMemory::::new(DEFAULT_MEMORY_SIZE)); + assert_memory_store_empty_bytes(&mut WXorXMemory::>::new( + DEFAULT_MEMORY_SIZE, + )); #[cfg(has_asm)] - assert_memory_store_empty_bytes(&mut AsmCoreMachine::new(ISA_IMC, VERSION0, 200_000)); + assert_memory_store_empty_bytes(&mut ::new( + ISA_IMC, VERSION0, 200_000, + )); } fn assert_memory_store_empty_bytes(memory: &mut M) { @@ -242,19 +246,14 @@ fn assert_memory_load_bytes_all( ) { assert_memory_load_bytes( rng, - &mut SparseMemory::::new_with_memory(max_memory), + &mut SparseMemory::::new(max_memory), buf_size, addr, ); + assert_memory_load_bytes(rng, &mut FlatMemory::::new(max_memory), buf_size, addr); assert_memory_load_bytes( rng, - &mut FlatMemory::::new_with_memory(max_memory), - buf_size, - addr, - ); - assert_memory_load_bytes( - rng, - &mut WXorXMemory::new(FlatMemory::::new_with_memory(max_memory)), + &mut WXorXMemory::>::new(max_memory), buf_size, addr, ); @@ -262,7 +261,7 @@ fn assert_memory_load_bytes_all( #[cfg(has_asm)] assert_memory_load_bytes( rng, - &mut AsmCoreMachine::new(ISA_IMC, VERSION0, 200_000), + &mut ::new(ISA_IMC, VERSION0, 200_000), buf_size, addr, ); @@ -367,7 +366,7 @@ pub fn test_rvc_pageend() { let buffer = fs::read("tests/programs/rvc_pageend").unwrap().into(); let core_machine = DefaultCoreMachine::>::new(ISA_IMC, VERSION0, u64::MAX); - let mut machine = DefaultMachineBuilder::new(core_machine).build(); + let mut machine = RustDefaultMachineBuilder::new(core_machine).build(); machine .load_program(&buffer, [Ok("rvc_end".into())].into_iter()) .unwrap(); @@ -418,7 +417,7 @@ impl Syscalls for OutOfCyclesSyscall { pub fn test_outofcycles_in_syscall() { let buffer = fs::read("tests/programs/syscall64").unwrap().into(); let core_machine = DefaultCoreMachine::>::new(ISA_IMC, VERSION0, 20); - let mut machine = DefaultMachineBuilder::new(core_machine) + let mut machine = RustDefaultMachineBuilder::new(core_machine) .instruction_cycle_func(Box::new(constant_cycles)) .syscall(Box::new(OutOfCyclesSyscall {})) .build(); diff --git a/tests/test_mop.rs b/tests/test_mop.rs index d06f5340..1cd39ab9 100644 --- a/tests/test_mop.rs +++ b/tests/test_mop.rs @@ -2,7 +2,10 @@ pub mod machine_build; use bytes::Bytes; use ckb_vm::error::OutOfBoundKind; use ckb_vm::machine::{VERSION1, VERSION2}; -use ckb_vm::{registers::A0, CoreMachine, Error, SupportMachine, ISA_B, ISA_IMC, ISA_MOP}; +use ckb_vm::{ + registers::A0, CoreMachine, DefaultMachineRunner, Error, SupportMachine, ISA_B, ISA_IMC, + ISA_MOP, +}; #[test] #[cfg_attr(miri, ignore)] diff --git a/tests/test_reset.rs b/tests/test_reset.rs index b4eff886..3ec60c2f 100644 --- a/tests/test_reset.rs +++ b/tests/test_reset.rs @@ -1,11 +1,11 @@ use bytes::Bytes; use ckb_vm::cost_model::constant_cycles; #[cfg(has_asm)] -use ckb_vm::machine::asm::{AsmCoreMachine, AsmMachine}; -use ckb_vm::machine::{DefaultCoreMachine, DefaultMachineBuilder, VERSION1}; +use ckb_vm::machine::asm::{AsmCoreMachine, AsmDefaultMachineBuilder, AsmMachine}; +use ckb_vm::machine::{DefaultCoreMachine, RustDefaultMachineBuilder, VERSION1}; use ckb_vm::{ - registers::A7, Error, Register, SparseMemory, SupportMachine, Syscalls, TraceMachine, - WXorXMemory, DEFAULT_MEMORY_SIZE, ISA_IMC, ISA_MOP, + registers::A7, DefaultMachineRunner, Error, Register, SparseMemory, SupportMachine, Syscalls, + TraceMachine, WXorXMemory, DEFAULT_MEMORY_SIZE, ISA_IMC, ISA_MOP, }; #[allow(dead_code)] @@ -48,7 +48,7 @@ fn test_reset_int() { VERSION1, u64::MAX, ); - let mut machine = DefaultMachineBuilder::new(core_machine) + let mut machine = RustDefaultMachineBuilder::new(core_machine) .instruction_cycle_func(Box::new(constant_cycles)) .syscall(Box::new(CustomSyscall {})) .build(); @@ -71,7 +71,7 @@ fn test_reset_int_with_trace() { u64::MAX, ); let mut machine = TraceMachine::new( - DefaultMachineBuilder::new(core_machine) + RustDefaultMachineBuilder::new(core_machine) .instruction_cycle_func(Box::new(constant_cycles)) .syscall(Box::new(CustomSyscall {})) .build(), @@ -91,7 +91,7 @@ fn test_reset_asm() { let code = Bytes::from(code_data); let asm_core = AsmCoreMachine::new(ISA_IMC | ISA_MOP, VERSION1, u64::MAX); - let core = DefaultMachineBuilder::>::new(asm_core) + let core = AsmDefaultMachineBuilder::new(asm_core) .instruction_cycle_func(Box::new(constant_cycles)) .syscall(Box::new(CustomSyscall {})) .build(); diff --git a/tests/test_resume.rs b/tests/test_resume.rs index ee957ef9..d7b32626 100644 --- a/tests/test_resume.rs +++ b/tests/test_resume.rs @@ -2,14 +2,15 @@ pub mod machine_build; use bytes::Bytes; use ckb_vm::cost_model::constant_cycles; -use ckb_vm::machine::asm::{AsmCoreMachine, AsmMachine}; +use ckb_vm::machine::asm::{AsmCoreMachine, AsmDefaultMachineBuilder, AsmMachine}; use ckb_vm::machine::trace::TraceMachine; use ckb_vm::machine::{ - DefaultCoreMachine, DefaultMachine, SupportMachine, VERSION0, VERSION1, VERSION2, + DefaultCoreMachine, DefaultMachine, DefaultMachineRunner, SupportMachine, VERSION0, VERSION1, + VERSION2, }; use ckb_vm::memory::{sparse::SparseMemory, wxorx::WXorXMemory}; use ckb_vm::snapshot::{make_snapshot, resume, Snapshot}; -use ckb_vm::{DefaultMachineBuilder, Error, ISA_A, ISA_IMC}; +use ckb_vm::{Error, RustDefaultMachineBuilder, ISA_A, ISA_IMC}; use std::fs::File; use std::io::Read; @@ -208,8 +209,9 @@ impl MachineTy { fn build(self, version: u32, max_cycles: u64) -> Machine { match self { MachineTy::Asm => { - let asm_core1 = AsmCoreMachine::new(ISA_IMC, version, max_cycles); - let core1 = DefaultMachineBuilder::>::new(asm_core1) + let asm_core1 = + ::new(ISA_IMC, version, max_cycles); + let core1 = AsmDefaultMachineBuilder::new(asm_core1) .instruction_cycle_func(Box::new(constant_cycles)) .build(); Machine::Asm(AsmMachine::new(core1)) @@ -219,9 +221,9 @@ impl MachineTy { ISA_IMC, version, max_cycles, ); Machine::Interpreter( - DefaultMachineBuilder::>>>::new( - core_machine1, - ) + RustDefaultMachineBuilder::< + DefaultCoreMachine>>, + >::new(core_machine1) .instruction_cycle_func(Box::new(constant_cycles)) .build(), ) @@ -230,15 +232,13 @@ impl MachineTy { let core_machine1 = DefaultCoreMachine::>>::new( ISA_IMC, version, max_cycles, ); - Machine::InterpreterWithTrace( - TraceMachine::new( - DefaultMachineBuilder::< - DefaultCoreMachine>>, - >::new(core_machine1) - .instruction_cycle_func(Box::new(constant_cycles)) - .build(), - ), - ) + Machine::InterpreterWithTrace(TraceMachine::new( + RustDefaultMachineBuilder::< + DefaultCoreMachine>>, + >::new(core_machine1) + .instruction_cycle_func(Box::new(constant_cycles)) + .build(), + )) } } } @@ -316,7 +316,7 @@ pub fn test_sc_after_snapshot() { let snap = make_snapshot(&mut machine).unwrap(); let mut machine_new = TraceMachine::new( - DefaultMachineBuilder::new( + RustDefaultMachineBuilder::new( DefaultCoreMachine::>>::new( ISA_IMC | ISA_A, VERSION2, diff --git a/tests/test_resume2.rs b/tests/test_resume2.rs index c898c6da..dfcb1510 100644 --- a/tests/test_resume2.rs +++ b/tests/test_resume2.rs @@ -3,17 +3,18 @@ pub mod machine_build; use bytes::Bytes; use ckb_vm::cost_model::constant_cycles; use ckb_vm::elf::parse_elf; -use ckb_vm::machine::asm::{AsmCoreMachine, AsmMachine}; +use ckb_vm::machine::asm::{AsmCoreMachine, AsmDefaultMachineBuilder, AsmMachine}; use ckb_vm::machine::trace::TraceMachine; use ckb_vm::machine::{ - CoreMachine, DefaultCoreMachine, DefaultMachine, SupportMachine, VERSION0, VERSION1, VERSION2, + CoreMachine, DefaultCoreMachine, DefaultMachine, DefaultMachineRunner, SupportMachine, + VERSION0, VERSION1, VERSION2, }; use ckb_vm::memory::{sparse::SparseMemory, wxorx::WXorXMemory}; use ckb_vm::registers::{A0, A1, A7}; use ckb_vm::snapshot2::{DataSource, Snapshot2, Snapshot2Context}; #[allow(unused_imports)] use ckb_vm::Memory; -use ckb_vm::{DefaultMachineBuilder, Error, Register, Syscalls, ISA_A, ISA_IMC}; +use ckb_vm::{Error, Register, RustDefaultMachineBuilder, Syscalls, ISA_A, ISA_IMC}; use std::collections::HashMap; use std::fs::File; use std::io::Read; @@ -394,8 +395,9 @@ impl MachineTy { match self { MachineTy::Asm => { let context = Arc::new(Mutex::new(Snapshot2Context::new(data_source))); - let asm_core1 = AsmCoreMachine::new(ISA_IMC | ISA_A, version, 0); - let core1 = DefaultMachineBuilder::>::new(asm_core1) + let asm_core1 = + ::new(ISA_IMC | ISA_A, version, 0); + let core1 = AsmDefaultMachineBuilder::new(asm_core1) .instruction_cycle_func(Box::new(constant_cycles)) .syscall(Box::new(InsertDataSyscall(context.clone()))) .build(); @@ -409,9 +411,9 @@ impl MachineTy { 0, ); Machine::Interpreter( - DefaultMachineBuilder::>>>::new( - core_machine1, - ) + RustDefaultMachineBuilder::< + DefaultCoreMachine>>, + >::new(core_machine1) .instruction_cycle_func(Box::new(constant_cycles)) .syscall(Box::new(InsertDataSyscall(context.clone()))) .build(), @@ -427,7 +429,7 @@ impl MachineTy { ); Machine::InterpreterWithTrace( TraceMachine::new( - DefaultMachineBuilder::< + RustDefaultMachineBuilder::< DefaultCoreMachine>>, >::new(core_machine1) .instruction_cycle_func(Box::new(constant_cycles)) diff --git a/tests/test_signal_pause.rs b/tests/test_signal_pause.rs index ff87059c..1b20ce63 100644 --- a/tests/test_signal_pause.rs +++ b/tests/test_signal_pause.rs @@ -1,5 +1,5 @@ use ckb_vm::machine::VERSION2; -use ckb_vm::{Error, SupportMachine, ISA_B, ISA_IMC}; +use ckb_vm::{DefaultMachineRunner, Error, SupportMachine, ISA_B, ISA_IMC}; use std::sync::atomic::{AtomicU32, Ordering}; use std::sync::Arc; pub mod machine_build; diff --git a/tests/test_simple.rs b/tests/test_simple.rs index b32161cf..132d14f7 100644 --- a/tests/test_simple.rs +++ b/tests/test_simple.rs @@ -1,7 +1,7 @@ use ckb_vm::machine::VERSION0; use ckb_vm::{ - run, DefaultCoreMachine, DefaultMachineBuilder, Error, FlatMemory, Instruction, SparseMemory, - SupportMachine, ISA_IMC, + run, DefaultCoreMachine, DefaultMachineRunner, Error, FlatMemory, Instruction, + RustDefaultMachineBuilder, SparseMemory, SupportMachine, ISA_IMC, }; use std::fs; @@ -38,7 +38,7 @@ pub fn test_simple_cycles() { let buffer = fs::read("tests/programs/simple64").unwrap().into(); let core_machine = DefaultCoreMachine::>::new(ISA_IMC, VERSION0, 708); let mut machine = - DefaultMachineBuilder::>>::new(core_machine) + RustDefaultMachineBuilder::>>::new(core_machine) .instruction_cycle_func(Box::new(dummy_cycle_func)) .build(); machine @@ -57,7 +57,7 @@ pub fn test_simple_max_cycles_reached() { // Running simple64 should consume 708 cycles using dummy cycle func let core_machine = DefaultCoreMachine::>::new(ISA_IMC, VERSION0, 700); let mut machine = - DefaultMachineBuilder::>>::new(core_machine) + RustDefaultMachineBuilder::>>::new(core_machine) .instruction_cycle_func(Box::new(dummy_cycle_func)) .build(); machine @@ -81,7 +81,7 @@ pub fn test_simple_loaded_bytes() { let buffer = fs::read("tests/programs/simple64").unwrap().into(); let core_machine = DefaultCoreMachine::>::new(ISA_IMC, VERSION0, u64::MAX); - let mut machine = DefaultMachineBuilder::new(core_machine).build(); + let mut machine = RustDefaultMachineBuilder::new(core_machine).build(); let bytes = machine .load_program(&buffer, [Ok("simple".into())].into_iter()) .unwrap(); @@ -94,7 +94,7 @@ pub fn test_simple_cycles_overflow() { let core_machine = DefaultCoreMachine::>::new(ISA_IMC, VERSION0, u64::MAX); let mut machine = - DefaultMachineBuilder::>>::new(core_machine) + RustDefaultMachineBuilder::>>::new(core_machine) .instruction_cycle_func(Box::new(dummy_cycle_func)) .build(); machine.set_cycles(u64::MAX - 10); diff --git a/tests/test_spawn.rs b/tests/test_spawn.rs index 9f272aca..f126af33 100644 --- a/tests/test_spawn.rs +++ b/tests/test_spawn.rs @@ -1,13 +1,13 @@ use bytes::Bytes; use ckb_vm::cost_model::constant_cycles; #[cfg(has_asm)] -use ckb_vm::machine::asm::{AsmCoreMachine, AsmMachine}; +use ckb_vm::machine::asm::{AsmCoreMachine, AsmDefaultMachineBuilder, AsmMachine}; use ckb_vm::machine::{trace::TraceMachine, DefaultCoreMachine, VERSION2}; use ckb_vm::memory::load_c_string_byte_by_byte; use ckb_vm::registers::{A0, A1, A2, A7}; use ckb_vm::{ - DefaultMachineBuilder, Error, FlattenedArgsReader, Register, SparseMemory, SupportMachine, - Syscalls, WXorXMemory, ISA_B, ISA_IMC, ISA_MOP, + DefaultMachineRunner, Error, FlattenedArgsReader, Register, RustDefaultMachineBuilder, + SparseMemory, SupportMachine, Syscalls, WXorXMemory, ISA_B, ISA_IMC, ISA_MOP, }; use std::sync::{Arc, Mutex}; @@ -57,7 +57,7 @@ impl Syscalls for IntSpawnSyscall { u64::MAX, ); let mut machine_child = TraceMachine::new( - DefaultMachineBuilder::new(machine_core) + RustDefaultMachineBuilder::new(machine_core) .instruction_cycle_func(Box::new(constant_cycles)) .syscall(Box::new(IntSpawnSyscall { min_sp: self.min_sp.clone(), @@ -104,7 +104,7 @@ impl Syscalls for AsmSpawnSyscall { let args_iter = FlattenedArgsReader::new(machine.memory_mut(), argc.clone(), argv); let buffer: Bytes = std::fs::read(path).unwrap().into(); let machine_core_asm = AsmCoreMachine::new(ISA_IMC | ISA_B | ISA_MOP, VERSION2, u64::MAX); - let machine_core = DefaultMachineBuilder::>::new(machine_core_asm) + let machine_core = AsmDefaultMachineBuilder::new(machine_core_asm) .instruction_cycle_func(Box::new(constant_cycles)) .syscall(Box::new(AsmSpawnSyscall { min_sp: self.min_sp.clone(), @@ -129,7 +129,7 @@ pub fn test_spawn_int() { u64::MAX, ); let mut machine = TraceMachine::new( - DefaultMachineBuilder::new(machine_core) + RustDefaultMachineBuilder::new(machine_core) .instruction_cycle_func(Box::new(constant_cycles)) .syscall(Box::new(IntSpawnSyscall { min_sp: min_sp.clone(), @@ -154,7 +154,7 @@ pub fn test_spawn_asm() { let cur_sp = stack_depth(); let min_sp = Arc::new(Mutex::new(u64::MAX)); let machine_core_asm = AsmCoreMachine::new(ISA_IMC | ISA_B | ISA_MOP, VERSION2, u64::MAX); - let machine_core = DefaultMachineBuilder::>::new(machine_core_asm) + let machine_core = AsmDefaultMachineBuilder::new(machine_core_asm) .instruction_cycle_func(Box::new(constant_cycles)) .syscall(Box::new(AsmSpawnSyscall { min_sp: min_sp.clone(), diff --git a/tests/test_versions.rs b/tests/test_versions.rs index 589fd9cf..6a24d360 100644 --- a/tests/test_versions.rs +++ b/tests/test_versions.rs @@ -1,12 +1,13 @@ #![cfg(has_asm)] use ckb_vm::cost_model::constant_cycles; use ckb_vm::error::OutOfBoundKind; -use ckb_vm::machine::asm::{AsmCoreMachine, AsmMachine}; +use ckb_vm::machine::asm::{AsmCoreMachine, AsmDefaultMachineBuilder, AsmMachine}; use ckb_vm::machine::{VERSION0, VERSION1, VERSION2}; use ckb_vm::memory::{FLAG_DIRTY, FLAG_FREEZED}; use ckb_vm::{ - CoreMachine, DefaultCoreMachine, DefaultMachine, DefaultMachineBuilder, Error, Memory, - SparseMemory, TraceMachine, WXorXMemory, ISA_B, ISA_IMC, ISA_MOP, RISCV_PAGESIZE, + CoreMachine, DefaultCoreMachine, DefaultMachine, DefaultMachineRunner, Error, Memory, + RustDefaultMachineBuilder, SparseMemory, SupportMachine, TraceMachine, WXorXMemory, ISA_B, + ISA_IMC, ISA_MOP, RISCV_PAGESIZE, }; use std::fs; @@ -20,7 +21,7 @@ fn create_rust_machine( let buffer = fs::read(path).unwrap().into(); let core_machine = DefaultCoreMachine::::new(ISA_IMC, version, u64::MAX); let mut machine = - DefaultMachineBuilder::>::new(core_machine).build(); + RustDefaultMachineBuilder::>::new(core_machine).build(); machine .load_program(&buffer, [Ok(program.into())].into_iter()) .unwrap(); @@ -30,8 +31,8 @@ fn create_rust_machine( fn create_asm_machine(program: String, version: u32) -> AsmMachine { let path = format!("tests/programs/{}", program); let buffer = fs::read(path).unwrap().into(); - let asm_core = AsmCoreMachine::new(ISA_IMC, version, u64::MAX); - let core = DefaultMachineBuilder::>::new(asm_core).build(); + let asm_core = ::new(ISA_IMC, version, u64::MAX); + let core = AsmDefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); machine .load_program(&buffer, [Ok(program.into())].into_iter()) @@ -245,7 +246,7 @@ pub fn test_rust_version0_unaligned64() { .into(); let core_machine = DefaultCoreMachine::::new(ISA_IMC, VERSION0, u64::MAX); let mut machine = - DefaultMachineBuilder::>::new(core_machine).build(); + RustDefaultMachineBuilder::>::new(core_machine).build(); let result = machine.load_program(&buffer, [Ok(program.into())].into_iter()); assert!(result.is_err()); assert_eq!(result.err(), Some(Error::MemWriteOnExecutablePage(16))); @@ -265,8 +266,8 @@ pub fn test_asm_version0_unaligned64() { let buffer = fs::read(format!("tests/programs/{}", program)) .unwrap() .into(); - let asm_core = AsmCoreMachine::new(ISA_IMC, VERSION0, u64::MAX); - let core = DefaultMachineBuilder::>::new(asm_core).build(); + let asm_core = ::new(ISA_IMC, VERSION0, u64::MAX); + let core = AsmDefaultMachineBuilder::new(asm_core).build(); let mut machine = AsmMachine::new(core); let result = machine.load_program(&buffer, [Ok(program.into())].into_iter()); assert!(result.is_err()); @@ -345,8 +346,9 @@ pub fn test_asm_version1_asm_trace_bug() { let buffer = fs::read("tests/programs/asm_trace_bug").unwrap().into(); let mut machine = { - let asm_core = AsmCoreMachine::new(ISA_IMC | ISA_B | ISA_MOP, VERSION1, 2000); - let machine = DefaultMachineBuilder::>::new(asm_core) + let asm_core = + ::new(ISA_IMC | ISA_B | ISA_MOP, VERSION1, 2000); + let machine = AsmDefaultMachineBuilder::new(asm_core) .instruction_cycle_func(Box::new(constant_cycles)) .build(); AsmMachine::new(machine) @@ -362,8 +364,9 @@ pub fn test_asm_version2_asm_trace_bug() { let buffer = fs::read("tests/programs/asm_trace_bug").unwrap().into(); let mut machine = { - let asm_core = AsmCoreMachine::new(ISA_IMC | ISA_B | ISA_MOP, VERSION2, 2000); - let machine = DefaultMachineBuilder::>::new(asm_core) + let asm_core = + ::new(ISA_IMC | ISA_B | ISA_MOP, VERSION2, 2000); + let machine = AsmDefaultMachineBuilder::new(asm_core) .instruction_cycle_func(Box::new(constant_cycles)) .build(); AsmMachine::new(machine) @@ -388,7 +391,7 @@ pub fn test_trace_version1_asm_trace_bug() { 2000, ); TraceMachine::new( - DefaultMachineBuilder::new(core_machine) + RustDefaultMachineBuilder::new(core_machine) .instruction_cycle_func(Box::new(constant_cycles)) .build(), ) @@ -410,7 +413,7 @@ pub fn test_trace_version2_asm_trace_bug() { 2000, ); TraceMachine::new( - DefaultMachineBuilder::new(core_machine) + RustDefaultMachineBuilder::new(core_machine) .instruction_cycle_func(Box::new(constant_cycles)) .build(), )