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

chore(interpreter): use let else #629

Merged
merged 2 commits into from Aug 23, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
63 changes: 23 additions & 40 deletions crates/interpreter/src/instructions/host.rs
Expand Up @@ -13,12 +13,10 @@ use revm_primitives::BLOCK_HASH_HISTORY;

pub fn balance<SPEC: Spec>(interpreter: &mut Interpreter, host: &mut dyn Host) {
pop_address!(interpreter, address);
let ret = host.balance(address);
if ret.is_none() {
let Some((balance, is_cold)) = host.balance(address) else {
interpreter.instruction_result = InstructionResult::FatalExternalError;
return;
}
let (balance, is_cold) = ret.unwrap();
};
gas!(
interpreter,
if SPEC::enabled(ISTANBUL) {
Expand All @@ -37,23 +35,19 @@ pub fn selfbalance<SPEC: Spec>(interpreter: &mut Interpreter, host: &mut dyn Hos
// EIP-1884: Repricing for trie-size-dependent opcodes
check!(interpreter, SPEC::enabled(ISTANBUL));
gas!(interpreter, gas::LOW);
let ret = host.balance(interpreter.contract.address);
if ret.is_none() {
let Some((balance, _)) = host.balance(interpreter.contract.address) else {
interpreter.instruction_result = InstructionResult::FatalExternalError;
return;
}
let (balance, _) = ret.unwrap();
};
push!(interpreter, balance);
}

pub fn extcodesize<SPEC: Spec>(interpreter: &mut Interpreter, host: &mut dyn Host) {
pop_address!(interpreter, address);
let ret = host.code(address);
if ret.is_none() {
let Some((code, is_cold)) = host.code(address) else {
interpreter.instruction_result = InstructionResult::FatalExternalError;
return;
}
let (code, is_cold) = ret.unwrap();
};
if SPEC::enabled(BERLIN) {
gas!(
interpreter,
Expand All @@ -75,12 +69,10 @@ pub fn extcodesize<SPEC: Spec>(interpreter: &mut Interpreter, host: &mut dyn Hos
pub fn extcodehash<SPEC: Spec>(interpreter: &mut Interpreter, host: &mut dyn Host) {
check!(interpreter, SPEC::enabled(CONSTANTINOPLE)); // EIP-1052: EXTCODEHASH opcode
pop_address!(interpreter, address);
let ret = host.code_hash(address);
if ret.is_none() {
let Some((code_hash, is_cold)) = host.code_hash(address) else {
interpreter.instruction_result = InstructionResult::FatalExternalError;
return;
}
let (code_hash, is_cold) = ret.unwrap();
};
if SPEC::enabled(BERLIN) {
gas!(
interpreter,
Expand All @@ -102,12 +94,10 @@ pub fn extcodecopy<SPEC: Spec>(interpreter: &mut Interpreter, host: &mut dyn Hos
pop_address!(interpreter, address);
pop!(interpreter, memory_offset, code_offset, len_u256);

let ret = host.code(address);
if ret.is_none() {
let Some((code, is_cold)) = host.code(address) else {
interpreter.instruction_result = InstructionResult::FatalExternalError;
return;
}
let (code, is_cold) = ret.unwrap();
};

let len = as_usize_or_fail!(interpreter, len_u256, InstructionResult::InvalidOperandOOG);
gas_or_fail!(
Expand Down Expand Up @@ -139,12 +129,11 @@ pub fn blockhash(interpreter: &mut Interpreter, host: &mut dyn Host) {
let diff = as_usize_saturated!(diff);
// blockhash should push zero if number is same as current block number.
if diff <= BLOCK_HASH_HISTORY && diff != 0 {
let ret = host.block_hash(*number);
if ret.is_none() {
let Some(hash) = host.block_hash(*number) else {
interpreter.instruction_result = InstructionResult::FatalExternalError;
return;
}
*number = U256::from_be_bytes(*ret.unwrap());
};
*number = U256::from_be_bytes(hash.0);
return;
}
}
Expand All @@ -154,12 +143,10 @@ pub fn blockhash(interpreter: &mut Interpreter, host: &mut dyn Host) {
pub fn sload<SPEC: Spec>(interpreter: &mut Interpreter, host: &mut dyn Host) {
pop!(interpreter, index);

let ret = host.sload(interpreter.contract.address, index);
if ret.is_none() {
let Some((value, is_cold)) = host.sload(interpreter.contract.address, index) else {
interpreter.instruction_result = InstructionResult::FatalExternalError;
return;
}
let (value, is_cold) = ret.unwrap();
};
gas!(interpreter, gas::sload_cost::<SPEC>(is_cold));
push!(interpreter, value);
}
Expand All @@ -168,12 +155,12 @@ pub fn sstore<SPEC: Spec>(interpreter: &mut Interpreter, host: &mut dyn Host) {
check_staticcall!(interpreter);

pop!(interpreter, index, value);
let ret = host.sstore(interpreter.contract.address, index, value);
if ret.is_none() {
let Some((original, old, new, is_cold)) =
host.sstore(interpreter.contract.address, index, value)
else {
interpreter.instruction_result = InstructionResult::FatalExternalError;
return;
}
let (original, old, new, is_cold) = ret.unwrap();
};
gas_or_fail!(interpreter, {
let remaining_gas = interpreter.gas.remaining();
gas::sstore_cost::<SPEC>(original, old, new, remaining_gas, is_cold)
Expand Down Expand Up @@ -238,12 +225,10 @@ pub fn selfdestruct<SPEC: Spec>(interpreter: &mut Interpreter, host: &mut dyn Ho
check_staticcall!(interpreter);
pop_address!(interpreter, target);

let res = host.selfdestruct(interpreter.contract.address, target);
if res.is_none() {
let Some(res) = host.selfdestruct(interpreter.contract.address, target) else {
interpreter.instruction_result = InstructionResult::FatalExternalError;
return;
}
let res = res.unwrap();
};

// EIP-3529: Reduction in refunds
if !SPEC::enabled(LONDON) && !res.previously_destroyed {
Expand Down Expand Up @@ -482,12 +467,10 @@ fn prepare_call_inputs<SPEC: Spec>(
};

// load account and calculate gas cost.
let res = host.load_account(to);
if res.is_none() {
let Some((is_cold, exist)) = host.load_account(to) else {
interpreter.instruction_result = InstructionResult::FatalExternalError;
return;
}
let (is_cold, exist) = res.unwrap();
};
let is_new = !exist;

gas!(
Expand Down
100 changes: 47 additions & 53 deletions crates/interpreter/src/instructions/macros.rs
@@ -1,5 +1,3 @@
pub use crate::InstructionResult;

macro_rules! check_staticcall {
($interp:expr) => {
if $interp.is_static {
Expand All @@ -21,7 +19,7 @@ macro_rules! check {
macro_rules! gas {
($interp:expr, $gas:expr) => {
if crate::USE_GAS {
if !$interp.gas.record_cost(($gas)) {
if !$interp.gas.record_cost($gas) {
$interp.instruction_result = InstructionResult::OutOfGas;
return;
}
Expand All @@ -30,19 +28,19 @@ macro_rules! gas {
}

macro_rules! refund {
($interp:expr, $gas:expr) => {{
($interp:expr, $gas:expr) => {
if crate::USE_GAS {
$interp.gas.gas_refund($gas);
$interp.gas.record_refund($gas);
}
}};
};
}

macro_rules! gas_or_fail {
($interp:expr, $gas:expr) => {
if crate::USE_GAS {
match $gas {
Some(gas_used) => gas!($interp, gas_used),
None => {
Some(gas_used) if $interp.gas.record_cost(gas_used) => {}
_ => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit any reason to not use the macro

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would duplicate the assign/return on both branches, doesn't really matter since compiler probably optimizes that anyway

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you revert this one, I slightly vary on the fn call side-effect inside if, and second reason is that gas! is used everywhere so it converges to one place

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Understandable

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$interp.instruction_result = InstructionResult::OutOfGas;
return;
}
Expand All @@ -52,11 +50,9 @@ macro_rules! gas_or_fail {
}

macro_rules! memory_resize {
($interp:expr, $offset:expr, $len:expr) => {{
let len: usize = $len;
let offset: usize = $offset;
($interp:expr, $offset:expr, $len:expr) => {
if let Some(new_size) =
crate::interpreter::memory::next_multiple_of_32(offset.saturating_add(len))
crate::interpreter::memory::next_multiple_of_32($offset.saturating_add($len))
{
#[cfg(feature = "memory_limit")]
if new_size > ($interp.memory_limit as usize) {
Expand All @@ -78,7 +74,7 @@ macro_rules! memory_resize {
$interp.instruction_result = InstructionResult::MemoryOOG;
return;
}
}};
};
}

macro_rules! pop_address {
Expand Down Expand Up @@ -115,23 +111,23 @@ macro_rules! pop_address {
}

macro_rules! pop {
( $interp:expr, $x1:ident) => {
($interp:expr, $x1:ident) => {
if $interp.stack.len() < 1 {
$interp.instruction_result = InstructionResult::StackUnderflow;
return;
}
// Safety: Length is checked above.
let $x1 = unsafe { $interp.stack.pop_unsafe() };
};
( $interp:expr, $x1:ident, $x2:ident) => {
($interp:expr, $x1:ident, $x2:ident) => {
if $interp.stack.len() < 2 {
$interp.instruction_result = InstructionResult::StackUnderflow;
return;
}
// Safety: Length is checked above.
let ($x1, $x2) = unsafe { $interp.stack.pop2_unsafe() };
};
( $interp:expr, $x1:ident, $x2:ident, $x3:ident) => {
($interp:expr, $x1:ident, $x2:ident, $x3:ident) => {
if $interp.stack.len() < 3 {
$interp.instruction_result = InstructionResult::StackUnderflow;
return;
Expand All @@ -140,7 +136,7 @@ macro_rules! pop {
let ($x1, $x2, $x3) = unsafe { $interp.stack.pop3_unsafe() };
};

( $interp:expr, $x1:ident, $x2:ident, $x3:ident, $x4:ident) => {
($interp:expr, $x1:ident, $x2:ident, $x3:ident, $x4:ident) => {
if $interp.stack.len() < 4 {
$interp.instruction_result = InstructionResult::StackUnderflow;
return;
Expand All @@ -151,23 +147,23 @@ macro_rules! pop {
}

macro_rules! pop_top {
( $interp:expr, $x1:ident) => {
($interp:expr, $x1:ident) => {
if $interp.stack.len() < 1 {
$interp.instruction_result = InstructionResult::StackUnderflow;
return;
}
// Safety: Length is checked above.
let $x1 = unsafe { $interp.stack.top_unsafe() };
};
( $interp:expr, $x1:ident, $x2:ident) => {
($interp:expr, $x1:ident, $x2:ident) => {
if $interp.stack.len() < 2 {
$interp.instruction_result = InstructionResult::StackUnderflow;
return;
}
// Safety: Length is checked above.
let ($x1, $x2) = unsafe { $interp.stack.pop_top_unsafe() };
};
( $interp:expr, $x1:ident, $x2:ident, $x3:ident) => {
($interp:expr, $x1:ident, $x2:ident, $x3:ident) => {
if $interp.stack.len() < 3 {
$interp.instruction_result = InstructionResult::StackUnderflow;
return;
Expand All @@ -178,59 +174,57 @@ macro_rules! pop_top {
}

macro_rules! push_b256 {
( $interp:expr, $( $x:expr ),* ) => (
$(
match $interp.stack.push_b256($x) {
Ok(()) => (),
Err(e) => {
$interp.instruction_result = e;
return
},
}
)*
)
($interp:expr, $($x:expr),* $(,)?) => ($(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this now lets you push multiple values? or what is the new $(,)? for?

Copy link
Collaborator Author

@DaniPopes DaniPopes Aug 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just allows trailing comma. Sometimes rustfmt will add it and then parsing fails because it is not expected in the macro.

match $interp.stack.push_b256($x) {
Ok(()) => {},
Err(e) => {
$interp.instruction_result = e;
return;
},
}
)*)
}

macro_rules! push {
( $interp:expr, $( $x:expr ),* ) => (
$(
match $interp.stack.push($x) {
Ok(()) => (),
Err(e) => { $interp.instruction_result = e;
return
} ,
}
)*
)
($interp:expr, $($x:expr),* $(,)?) => ($(
match $interp.stack.push($x) {
Ok(()) => {},
Err(e) => {
$interp.instruction_result = e;
return;
}
}
)*)
}

macro_rules! as_u64_saturated {
( $v:expr ) => {{
if $v.as_limbs()[1] != 0 || $v.as_limbs()[2] != 0 || $v.as_limbs()[3] != 0 {
u64::MAX
($v:expr) => {{
let x: &[u64; 4] = $v.as_limbs();
if x[1] == 0 && x[2] == 0 && x[3] == 0 {
x[0]
} else {
$v.as_limbs()[0]
u64::MAX
}
}};
}

macro_rules! as_usize_saturated {
( $v:expr ) => {{
($v:expr) => {
as_u64_saturated!($v) as usize
}};
};
}

macro_rules! as_usize_or_fail {
( $interp:expr, $v:expr ) => {{
($interp:expr, $v:expr) => {
as_usize_or_fail!($interp, $v, InstructionResult::InvalidOperandOOG)
}};
};

( $interp:expr, $v:expr, $reason:expr ) => {{
if $v.as_limbs()[1] != 0 || $v.as_limbs()[2] != 0 || $v.as_limbs()[3] != 0 {
($interp:expr, $v:expr, $reason:expr) => {{
let x = $v.as_limbs();
if x[1] != 0 || x[2] != 0 || x[3] != 0 {
$interp.instruction_result = $reason;
return;
}

$v.as_limbs()[0] as usize
x[0] as usize
}};
}