Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf: pay base gas of dynamic opcodes in sections #19

Merged
merged 1 commit into from
May 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 35 additions & 42 deletions crates/revm-jit-builtins/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ pub unsafe extern "C" fn __revm_jit_builtin_exp(
spec_id: SpecId,
) -> InstructionResult {
let exponent = exponent_ptr.to_u256();
gas_opt!(ecx, gas::exp_cost(spec_id, exponent));
gas_opt!(ecx, gas::exp_cost(spec_id, exponent).map(|g| g - gas::EXP));
*exponent_ptr = base.to_u256().pow(exponent).into();
InstructionResult::Continue
}
Expand All @@ -101,20 +101,16 @@ pub unsafe extern "C" fn __revm_jit_builtin_keccak256(
ecx: &mut EvmContext<'_>,
rev![offset, len_ptr]: &mut [EvmWord; 2],
) -> InstructionResult {
if *len_ptr == EvmWord::ZERO {
*len_ptr = EvmWord::from_be_bytes(KECCAK_EMPTY.0);
gas!(ecx, gas::KECCAK256);
return InstructionResult::Continue;
}
let len = try_into_usize!(len_ptr.as_u256());
gas_opt!(ecx, gas::keccak256_cost(len as u64));
let offset = try_into_usize!(offset.as_u256());

resize_memory!(ecx, offset, len);

let data = ecx.memory.slice(offset, len);
*len_ptr = EvmWord::from_be_bytes(revm_primitives::keccak256(data).0);

let len = try_into_usize!(len_ptr);
*len_ptr = EvmWord::from_be_bytes(if len == 0 {
KECCAK_EMPTY.0
} else {
gas_opt!(ecx, gas::keccak256_cost(len as u64).map(|g| g - gas::KECCAK256));
let offset = try_into_usize!(offset);
resize_memory!(ecx, offset, len);
let data = ecx.memory.slice(offset, len);
revm_primitives::keccak256(data).0
});
InstructionResult::Continue
}

Expand Down Expand Up @@ -195,10 +191,10 @@ pub unsafe extern "C" fn __revm_jit_builtin_extcodecopy(
spec_id: SpecId,
) -> InstructionResult {
let (code, is_cold) = try_host!(ecx.host.code(address.to_address()));
let len = tri!(usize::try_from(len));
let len = try_into_usize!(len);
gas_opt!(ecx, gas::extcodecopy_cost(spec_id, len as u64, is_cold));
if len != 0 {
let memory_offset = try_into_usize!(memory_offset.as_u256());
let memory_offset = try_into_usize!(memory_offset);
let code_offset = code_offset.to_u256();
let code_offset = as_usize_saturated!(code_offset).min(code.len());
resize_memory!(ecx, memory_offset, len);
Expand All @@ -212,16 +208,16 @@ pub unsafe extern "C" fn __revm_jit_builtin_returndatacopy(
ecx: &mut EvmContext<'_>,
rev![memory_offset, offset, len]: &mut [EvmWord; 3],
) -> InstructionResult {
let len = tri!(usize::try_from(len));
gas_opt!(ecx, gas::verylowcopy_cost(len as u64));
let len = try_into_usize!(len);
gas_opt!(ecx, gas::verylowcopy_cost(len as u64).map(|g| g - gas::VERYLOW));
let data_offset = offset.to_u256();
let data_offset = as_usize_saturated!(data_offset);
let (data_end, overflow) = data_offset.overflowing_add(len);
if overflow || data_end > ecx.return_data.len() {
return InstructionResult::OutOfOffset;
}
if len != 0 {
let memory_offset = try_into_usize!(memory_offset.as_u256());
let memory_offset = try_into_usize!(memory_offset);
resize_memory!(ecx, memory_offset, len);
ecx.memory.set(memory_offset, &ecx.return_data[data_offset..data_end]);
}
Expand Down Expand Up @@ -312,8 +308,7 @@ pub unsafe extern "C" fn __revm_jit_builtin_mload(
ecx: &mut EvmContext<'_>,
offset_ptr: &mut EvmWord,
) -> InstructionResult {
gas!(ecx, gas::VERYLOW);
let offset = try_into_usize!(offset_ptr.as_u256());
let offset = try_into_usize!(offset_ptr);
resize_memory!(ecx, offset, 32);
*offset_ptr = ecx.memory.get_u256(offset).into();
InstructionResult::Continue
Expand All @@ -324,8 +319,7 @@ pub unsafe extern "C" fn __revm_jit_builtin_mstore(
ecx: &mut EvmContext<'_>,
rev![offset, value]: &mut [EvmWord; 2],
) -> InstructionResult {
gas!(ecx, gas::VERYLOW);
let offset = try_into_usize!(offset.as_u256());
let offset = try_into_usize!(offset);
resize_memory!(ecx, offset, 32);
ecx.memory.set(offset, &value.to_be_bytes());
InstructionResult::Continue
Expand All @@ -336,8 +330,7 @@ pub unsafe extern "C" fn __revm_jit_builtin_mstore8(
ecx: &mut EvmContext<'_>,
rev![offset, value]: &mut [EvmWord; 2],
) -> InstructionResult {
gas!(ecx, gas::VERYLOW);
let offset = try_into_usize!(offset.as_u256());
let offset = try_into_usize!(offset);
resize_memory!(ecx, offset, 1);
ecx.memory.set_byte(offset, value.to_u256().byte(0));
InstructionResult::Continue
Expand Down Expand Up @@ -394,11 +387,11 @@ pub unsafe extern "C" fn __revm_jit_builtin_mcopy(
ecx: &mut EvmContext<'_>,
rev![dst, src, len]: &mut [EvmWord; 3],
) -> InstructionResult {
let len = try_into_usize!(len.to_u256());
gas_opt!(ecx, gas::verylowcopy_cost(len as u64));
let len = try_into_usize!(len);
gas_opt!(ecx, gas::verylowcopy_cost(len as u64).map(|g| g - gas::VERYLOW));
if len != 0 {
let dst = try_into_usize!(dst.to_u256());
let src = try_into_usize!(src.to_u256());
let dst = try_into_usize!(dst);
let src = try_into_usize!(src);
resize_memory!(ecx, dst.max(src), len);
ecx.memory.copy(dst, src, len);
}
Expand All @@ -411,13 +404,13 @@ pub unsafe extern "C" fn __revm_jit_builtin_log(
sp: *mut EvmWord,
n: u8,
) -> InstructionResult {
debug_assert!(n <= 4, "invalid log topic count: {n}");
assume!(n <= 4, "invalid log topic count: {n}");
let sp = sp.add(n as usize);
read_words!(sp, offset, len);
let len = tri!(usize::try_from(len));
gas_opt!(ecx, gas::log_cost(n, len as u64));
let len = try_into_usize!(len);
gas_opt!(ecx, gas::LOGDATA.checked_mul(len as u64));
let data = if len != 0 {
let offset = try_into_usize!(offset.as_u256());
let offset = try_into_usize!(offset);
resize_memory!(ecx, offset, len);
Bytes::copy_from_slice(ecx.memory.slice(offset, len))
} else {
Expand Down Expand Up @@ -452,7 +445,7 @@ pub unsafe extern "C" fn __revm_jit_builtin_create(
let mut sp = sp.add(len);
pop!(sp; value, code_offset, len);

let len = tri!(usize::try_from(len));
let len = try_into_usize!(len);
let code = if len != 0 {
if spec_id.is_enabled_in(SpecId::SHANGHAI) {
// Limit is set as double of max contract bytecode size
Expand All @@ -469,7 +462,7 @@ pub unsafe extern "C" fn __revm_jit_builtin_create(
gas!(ecx, gas::initcode_cost(len as u64));
}

let code_offset = try_into_usize!(code_offset.as_u256());
let code_offset = try_into_usize!(code_offset);
resize_memory!(ecx, code_offset, len);
Bytes::copy_from_slice(ecx.memory.slice(code_offset, len))
} else {
Expand Down Expand Up @@ -541,18 +534,18 @@ pub unsafe extern "C" fn __revm_jit_builtin_call(

pop!(sp; in_offset, in_len, out_offset, out_len);

let in_len = try_into_usize!(in_len.to_u256());
let in_len = try_into_usize!(in_len);
let input = if in_len != 0 {
let in_offset = try_into_usize!(in_offset.to_u256());
let in_offset = try_into_usize!(in_offset);
resize_memory!(ecx, in_offset, in_len);
Bytes::copy_from_slice(ecx.memory.slice(in_offset, in_len))
} else {
Bytes::new()
};

let out_len = try_into_usize!(out_len.to_u256());
let out_len = try_into_usize!(out_len);
let out_offset = if out_len != 0 {
let out_offset = try_into_usize!(out_offset.to_u256());
let out_offset = try_into_usize!(out_offset);
resize_memory!(ecx, out_offset, out_len);
out_offset
} else {
Expand Down Expand Up @@ -620,9 +613,9 @@ pub unsafe extern "C" fn __revm_jit_builtin_do_return(
rev![offset, len]: &mut [EvmWord; 2],
result: InstructionResult,
) -> InstructionResult {
let len = try_into_usize!(len.as_u256());
let len = try_into_usize!(len);
let output = if len != 0 {
let offset = try_into_usize!(offset.as_u256());
let offset = try_into_usize!(offset);
resize_memory!(ecx, offset, len);
ecx.memory.slice(offset, len).to_vec().into()
} else {
Expand Down
11 changes: 4 additions & 7 deletions crates/revm-jit-builtins/src/macros.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#[allow(unused_macros)]
macro_rules! tri {
($e:expr) => {
match $e {
Expand Down Expand Up @@ -69,16 +70,12 @@ macro_rules! pop {

macro_rules! try_into_usize {
($x:expr) => {
match $x {
match $x.to_u256().as_limbs() {
x => {
let x = x.as_limbs();
if x[1] != 0 || x[2] != 0 || x[3] != 0 {
if (x[0] > usize::MAX as u64) | (x[1] != 0) | (x[2] != 0) | (x[3] != 0) {
return InstructionResult::InvalidOperandOOG;
}
let Ok(val) = usize::try_from(x[0]) else {
return InstructionResult::InvalidOperandOOG;
};
val
x[0] as usize
}
}
};
Expand Down
9 changes: 5 additions & 4 deletions crates/revm-jit-builtins/src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use revm_interpreter::{as_usize_saturated, gas as rgas, InstructionResult};
use crate::gas;
use revm_interpreter::{as_usize_saturated, InstructionResult};
use revm_jit_context::{EvmContext, EvmWord};

/// Splits the stack pointer into `N` elements by casting it to an array.
Expand Down Expand Up @@ -37,12 +38,12 @@ pub(crate) unsafe fn copy_operation(
rev![memory_offset, data_offset, len]: &mut [EvmWord; 3],
data: &[u8],
) -> InstructionResult {
let len = tri!(usize::try_from(len));
gas_opt!(ecx, rgas::verylowcopy_cost(len as u64));
let len = try_into_usize!(len);
gas_opt!(ecx, gas::verylowcopy_cost(len as u64).map(|g| g - gas::VERYLOW));
if len == 0 {
return InstructionResult::Continue;
}
let memory_offset = try_into_usize!(memory_offset.as_u256());
let memory_offset = try_into_usize!(memory_offset);
resize_memory!(ecx, memory_offset, len);
let data_offset = data_offset.to_u256();
let data_offset = as_usize_saturated!(data_offset);
Expand Down
Loading
Loading