Skip to content

Commit

Permalink
perf: pay base gas of dynamic opcodes in sections (#19)
Browse files Browse the repository at this point in the history
  • Loading branch information
DaniPopes authored May 2, 2024
1 parent d839518 commit 3d91bbf
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 141 deletions.
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

0 comments on commit 3d91bbf

Please sign in to comment.