diff --git a/CHANGELOG.md b/CHANGELOG.md index ff13f4e631..cea4cf79a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,12 +4,14 @@ ### 2025-07-17 +- Improve CodeCopy perfomance [#3675](https://github.com/lambdaclass/ethrex/pull/3675) + - Improve sstore perfomance further [#3657](https://github.com/lambdaclass/ethrex/pull/3657) ### 2025-07-16 - Improve levm memory model [#3564](https://github.com/lambdaclass/ethrex/pull/3564) -- + ### 2025-07-15 - Add sstore bench [#3552](https://github.com/lambdaclass/ethrex/pull/3552) diff --git a/crates/vm/levm/src/opcode_handlers/environment.rs b/crates/vm/levm/src/opcode_handlers/environment.rs index 4afdde2881..244f4a3796 100644 --- a/crates/vm/levm/src/opcode_handlers/environment.rs +++ b/crates/vm/levm/src/opcode_handlers/environment.rs @@ -226,18 +226,33 @@ impl<'a> VM<'a> { return Ok(OpcodeResult::Continue { pc_increment: 1 }); } + // Happiest fast path, copy without an intermediate buffer because there is no need to pad 0s and also size doesn't overflow. + if let Some(code_offset_end) = code_offset.checked_add(size) { + if code_offset_end < current_call_frame.bytecode.len() { + #[expect(unsafe_code, reason = "bounds checked beforehand")] + let slice = unsafe { + current_call_frame + .bytecode + .get_unchecked(code_offset..code_offset_end) + }; + current_call_frame + .memory + .store_data(destination_offset, slice)?; + + return Ok(OpcodeResult::Continue { pc_increment: 1 }); + } + } + let mut data = vec![0u8; size]; if code_offset < current_call_frame.bytecode.len() { - for (i, byte) in current_call_frame - .bytecode - .iter() - .skip(code_offset) - .take(size) - .enumerate() - { - if let Some(data_byte) = data.get_mut(i) { - *data_byte = *byte; - } + let diff = current_call_frame.bytecode.len().wrapping_sub(code_offset); + let final_size = size.min(diff); + let end = code_offset.wrapping_add(final_size); + + #[expect(unsafe_code, reason = "bounds checked beforehand")] + unsafe { + data.get_unchecked_mut(..final_size) + .copy_from_slice(current_call_frame.bytecode.get_unchecked(code_offset..end)); } }