Skip to content
This repository has been archived by the owner on Feb 21, 2024. It is now read-only.

Commit

Permalink
Remove some more CPU cycles (0xPolygonZero#1472)
Browse files Browse the repository at this point in the history
* Speed-up some mload/mstore calls

* Misc

* Improve logs loop

* Speed-up bloom

* Speed-up access_lists loops

* Fix

* Speed up selfdestruct loop

* Speed-up touched_addresses loop

* Speed-up receipt loop

* Skip rep loop

* Fix

* Misc

* Review
  • Loading branch information
Nashtare authored Jan 17, 2024
1 parent 990eb34 commit 10fc966
Show file tree
Hide file tree
Showing 18 changed files with 239 additions and 143 deletions.
32 changes: 17 additions & 15 deletions evm/src/cpu/kernel/asm/bloom_filter.asm
Original file line number Diff line number Diff line change
Expand Up @@ -55,20 +55,21 @@ logs_bloom_loop:
// Add address to bloom filter.
%increment
// stack: addr_ptr, i, logs_len, retdest
PUSH @SEGMENT_LOGS_DATA %build_kernel_address
DUP1
%mload_kernel(@SEGMENT_LOGS_DATA)
// stack: addr, addr_ptr, i, logs_len, retdest
MLOAD_GENERAL
// stack: addr, full_addr_ptr, i, logs_len, retdest
PUSH 0
// stack: is_topic, addr, addr_ptr, i, logs_len, retdest
// stack: is_topic, addr, full_addr_ptr, i, logs_len, retdest
%add_to_bloom
// stack: addr_ptr, i, logs_len, retdest
// stack: full_addr_ptr, i, logs_len, retdest
%increment
// stack: num_topics_ptr, i, logs_len, retdest
// stack: full_num_topics_ptr, i, logs_len, retdest
DUP1
%mload_kernel(@SEGMENT_LOGS_DATA)
// stack: num_topics, num_topics_ptr, i, logs_len, retdest
MLOAD_GENERAL
// stack: num_topics, full_num_topics_ptr, i, logs_len, retdest
SWAP1 %increment
// stack: topics_ptr, num_topics, i, logs_len, retdest
// stack: full_topics_ptr, num_topics, i, logs_len, retdest
PUSH 0

logs_bloom_topic_loop:
Expand All @@ -78,7 +79,7 @@ logs_bloom_topic_loop:
%jumpi(logs_bloom_topic_end)
DUP2 DUP2 ADD
// stack: curr_topic_ptr, j, topics_ptr, num_topics, i, logs_len, retdest
%mload_kernel(@SEGMENT_LOGS_DATA)
MLOAD_GENERAL
// stack: topic, j, topics_ptr, num_topics, i, logs_len, retdest
PUSH 1
// stack: is_topic, topic, j, topics_ptr, num_topics, i, logs_len, retdest
Expand Down Expand Up @@ -142,19 +143,20 @@ logs_bloom_end:
// Also updates the block bloom filter.
%macro bloom_write_bit
// stack: byte_index, byte_bit_index
PUSH @SEGMENT_TXN_BLOOM
%build_kernel_address
PUSH 1
DUP3
// stack: byte_bit_index, 1, byte_index, byte_bit_index
// stack: byte_bit_index, 1, byte_addr, byte_bit_index
PUSH 7 SUB
SHL
// Updates the current txn bloom filter.
SWAP2 POP DUP1
%mload_kernel(@SEGMENT_TXN_BLOOM)
// stack: old_bloom_byte, byte_index, one_shifted_by_index
MLOAD_GENERAL
// stack: old_bloom_byte, byte_addr, one_shifted_by_index
DUP3 OR
// stack: new_bloom_byte, byte_index, one_shifted_by_index
SWAP1
%mstore_kernel(@SEGMENT_TXN_BLOOM)
// stack: new_bloom_byte, byte_addr, one_shifted_by_index
MSTORE_GENERAL
// stack: one_shifted_by_index
POP
// stack: empty
Expand Down
74 changes: 44 additions & 30 deletions evm/src/cpu/kernel/asm/core/access_lists.asm
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,15 @@ global insert_accessed_addresses:
// stack: addr, retdest
%mload_global_metadata(@GLOBAL_METADATA_ACCESSED_ADDRESSES_LEN)
// stack: len, addr, retdest
PUSH 0
PUSH @SEGMENT_ACCESSED_ADDRESSES ADD
PUSH @SEGMENT_ACCESSED_ADDRESSES
insert_accessed_addresses_loop:
// `i` and `len` are both scaled by SEGMENT_ACCESSED_ADDRESSES
%stack (i, len, addr, retdest) -> (i, len, i, len, addr, retdest)
EQ %jumpi(insert_address)
// stack: i, len, addr, retdest
DUP1 %mload_kernel(@SEGMENT_ACCESSED_ADDRESSES)
DUP1
MLOAD_GENERAL
// stack: loaded_addr, i, len, addr, retdest
DUP4
// stack: addr, loaded_addr, i, len, addr, retdest
Expand All @@ -42,9 +45,10 @@ insert_accessed_addresses_loop:
insert_address:
%stack (i, len, addr, retdest) -> (i, addr, len, retdest)
DUP2 %journal_add_account_loaded // Add a journal entry for the loaded account.
%mstore_kernel(@SEGMENT_ACCESSED_ADDRESSES) // Store new address at the end of the array.
%swap_mstore // Store new address at the end of the array.
// stack: len, retdest
%increment
%sub_const(@SEGMENT_ACCESSED_ADDRESSES) // unscale `len`
%mstore_global_metadata(@GLOBAL_METADATA_ACCESSED_ADDRESSES_LEN) // Store new length.
PUSH 1 // Return 1 to indicate that the address was inserted.
SWAP1 JUMP
Expand All @@ -59,12 +63,14 @@ global remove_accessed_addresses:
// stack: addr, retdest
%mload_global_metadata(@GLOBAL_METADATA_ACCESSED_ADDRESSES_LEN)
// stack: len, addr, retdest
PUSH 0
PUSH @SEGMENT_ACCESSED_ADDRESSES ADD
PUSH @SEGMENT_ACCESSED_ADDRESSES
remove_accessed_addresses_loop:
// `i` and `len` are both scaled by SEGMENT_ACCESSED_ADDRESSES
%stack (i, len, addr, retdest) -> (i, len, i, len, addr, retdest)
EQ %jumpi(panic)
// stack: i, len, addr, retdest
DUP1 %mload_kernel(@SEGMENT_ACCESSED_ADDRESSES)
DUP1 MLOAD_GENERAL
// stack: loaded_addr, i, len, addr, retdest
DUP4
// stack: addr, loaded_addr, i, len, addr, retdest
Expand All @@ -74,12 +80,15 @@ remove_accessed_addresses_loop:
%jump(remove_accessed_addresses_loop)
remove_accessed_addresses_found:
%stack (i, len, addr, retdest) -> (len, 1, i, retdest)
SUB DUP1 %mstore_global_metadata(@GLOBAL_METADATA_ACCESSED_ADDRESSES_LEN) // Decrement the access list length.
SUB // len -= 1
PUSH @SEGMENT_ACCESSED_ADDRESSES
DUP2 SUB // unscale `len`
%mstore_global_metadata(@GLOBAL_METADATA_ACCESSED_ADDRESSES_LEN) // Decrement the access list length.
// stack: len-1, i, retdest
%mload_kernel(@SEGMENT_ACCESSED_ADDRESSES) // Load the last address in the access list.
MLOAD_GENERAL // Load the last address in the access list.
// stack: last_addr, i, retdest
SWAP1
%mstore_kernel(@SEGMENT_ACCESSED_ADDRESSES) // Store the last address at the position of the removed address.
MSTORE_GENERAL
// Store the last address at the position of the removed address.
JUMP


Expand All @@ -97,14 +106,16 @@ global insert_accessed_storage_keys:
// stack: addr, key, value, retdest
%mload_global_metadata(@GLOBAL_METADATA_ACCESSED_STORAGE_KEYS_LEN)
// stack: len, addr, key, value, retdest
PUSH 0
PUSH @SEGMENT_ACCESSED_STORAGE_KEYS ADD
PUSH @SEGMENT_ACCESSED_STORAGE_KEYS
insert_accessed_storage_keys_loop:
// `i` and `len` are both scaled by SEGMENT_ACCESSED_STORAGE_KEYS
%stack (i, len, addr, key, value, retdest) -> (i, len, i, len, addr, key, value, retdest)
EQ %jumpi(insert_storage_key)
// stack: i, len, addr, key, value, retdest
DUP1 %increment %mload_kernel(@SEGMENT_ACCESSED_STORAGE_KEYS)
DUP1 %increment MLOAD_GENERAL
// stack: loaded_key, i, len, addr, key, value, retdest
DUP2 %mload_kernel(@SEGMENT_ACCESSED_STORAGE_KEYS)
DUP2 MLOAD_GENERAL
// stack: loaded_addr, loaded_key, i, len, addr, key, value, retdest
DUP5 EQ
// stack: loaded_addr==addr, loaded_key, i, len, addr, key, value, retdest
Expand All @@ -120,28 +131,26 @@ insert_storage_key:
// stack: i, len, addr, key, value, retdest
DUP4 DUP4 %journal_add_storage_loaded // Add a journal entry for the loaded storage key.
// stack: i, len, addr, key, value, retdest
DUP1
PUSH @SEGMENT_ACCESSED_STORAGE_KEYS
%build_kernel_address

%stack(dst, i, len, addr, key, value) -> (addr, dst, dst, key, dst, value, i, value)
%stack(dst, len, addr, key, value) -> (addr, dst, dst, key, dst, value, dst, @SEGMENT_ACCESSED_STORAGE_KEYS, value)
MSTORE_GENERAL // Store new address at the end of the array.
// stack: dst, key, dst, value, i, value, retdest
// stack: dst, key, dst, value, dst, segment, value, retdest
%increment SWAP1
MSTORE_GENERAL // Store new key after that
// stack: dst, value, i, value, retdest
// stack: dst, value, dst, segment, value, retdest
%add_const(2) SWAP1
MSTORE_GENERAL // Store new value after that
// stack: i, value, retdest
// stack: dst, segment, value, retdest
%add_const(3)
SUB // unscale dst
%mstore_global_metadata(@GLOBAL_METADATA_ACCESSED_STORAGE_KEYS_LEN) // Store new length.
%stack (value, retdest) -> (retdest, 1, value) // Return 1 to indicate that the storage key was inserted.
JUMP

insert_accessed_storage_keys_found:
// stack: i, len, addr, key, value, retdest
%add_const(2)
%mload_kernel(@SEGMENT_ACCESSED_STORAGE_KEYS)
MLOAD_GENERAL
%stack (original_value, len, addr, key, value, retdest) -> (retdest, 0, original_value) // Return 0 to indicate that the storage key was already present.
JUMP

Expand All @@ -151,14 +160,16 @@ global remove_accessed_storage_keys:
// stack: addr, key, retdest
%mload_global_metadata(@GLOBAL_METADATA_ACCESSED_STORAGE_KEYS_LEN)
// stack: len, addr, key, retdest
PUSH 0
PUSH @SEGMENT_ACCESSED_STORAGE_KEYS ADD
PUSH @SEGMENT_ACCESSED_STORAGE_KEYS
remove_accessed_storage_keys_loop:
// `i` and `len` are both scaled by SEGMENT_ACCESSED_STORAGE_KEYS
%stack (i, len, addr, key, retdest) -> (i, len, i, len, addr, key, retdest)
EQ %jumpi(panic)
// stack: i, len, addr, key, retdest
DUP1 %increment %mload_kernel(@SEGMENT_ACCESSED_STORAGE_KEYS)
DUP1 %increment MLOAD_GENERAL
// stack: loaded_key, i, len, addr, key, retdest
DUP2 %mload_kernel(@SEGMENT_ACCESSED_STORAGE_KEYS)
DUP2 MLOAD_GENERAL
// stack: loaded_addr, loaded_key, i, len, addr, key, retdest
DUP5 EQ
// stack: loaded_addr==addr, loaded_key, i, len, addr, key, retdest
Expand All @@ -172,18 +183,21 @@ remove_accessed_storage_keys_loop:

remove_accessed_storage_keys_found:
%stack (i, len, addr, key, retdest) -> (len, 3, i, retdest)
SUB DUP1 %mstore_global_metadata(@GLOBAL_METADATA_ACCESSED_STORAGE_KEYS_LEN) // Decrease the access list length.
SUB
PUSH @SEGMENT_ACCESSED_STORAGE_KEYS
DUP2 SUB // unscale
%mstore_global_metadata(@GLOBAL_METADATA_ACCESSED_STORAGE_KEYS_LEN) // Decrease the access list length.
// stack: len-3, i, retdest
DUP1 %add_const(2) %mload_kernel(@SEGMENT_ACCESSED_STORAGE_KEYS)
DUP1 %add_const(2) MLOAD_GENERAL
// stack: last_value, len-3, i, retdest
DUP2 %add_const(1) %mload_kernel(@SEGMENT_ACCESSED_STORAGE_KEYS)
DUP2 %add_const(1) MLOAD_GENERAL
// stack: last_key, last_value, len-3, i, retdest
DUP3 %mload_kernel(@SEGMENT_ACCESSED_STORAGE_KEYS)
DUP3 MLOAD_GENERAL
// stack: last_addr, last_key, last_value, len-3, i, retdest
DUP5 %mstore_kernel(@SEGMENT_ACCESSED_STORAGE_KEYS) // Move the last tuple to the position of the removed tuple.
DUP5 %swap_mstore // Move the last tuple to the position of the removed tuple.
// stack: last_key, last_value, len-3, i, retdest
DUP4 %add_const(1) %mstore_kernel(@SEGMENT_ACCESSED_STORAGE_KEYS)
DUP4 %add_const(1) %swap_mstore
// stack: last_value, len-3, i, retdest
DUP3 %add_const(2) %mstore_kernel(@SEGMENT_ACCESSED_STORAGE_KEYS)
DUP3 %add_const(2) %swap_mstore
// stack: len-3, i, retdest
%pop2 JUMP
18 changes: 9 additions & 9 deletions evm/src/cpu/kernel/asm/core/create_addresses.asm
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,17 @@ global get_create_address:
// Post stack: address
global get_create2_address:
// stack: sender, code_hash, salt, retdest
PUSH 0xff PUSH 0 %mstore_kernel_general
%stack (sender, code_hash, salt, retdest) -> (@SEGMENT_KERNEL_GENERAL, 1, sender, salt, code_hash, retdest)
ADD
PUSH @SEGMENT_KERNEL_GENERAL
DUP1
PUSH 0xff
MSTORE_GENERAL
// stack: addr, sender, code_hash, salt, retdest
%increment
%stack (addr, sender, code_hash, salt, retdest) -> (addr, sender, salt, code_hash, retdest)
MSTORE_32BYTES_20
POP
%stack (salt, code_hash, retdest) -> (@SEGMENT_KERNEL_GENERAL, 21, salt, code_hash, retdest)
ADD
// stack: addr, salt, code_hash, retdest
MSTORE_32BYTES_32
POP
%stack (code_hash, retdest) -> (@SEGMENT_KERNEL_GENERAL, 53, code_hash, retdest)
ADD
// stack: addr, code_hash, retdest
MSTORE_32BYTES_32
POP
%stack (retdest) -> (@SEGMENT_KERNEL_GENERAL, 85, retdest) // offset == context == 0
Expand Down
30 changes: 11 additions & 19 deletions evm/src/cpu/kernel/asm/core/create_receipt.asm
Original file line number Diff line number Diff line change
Expand Up @@ -116,22 +116,23 @@ process_receipt_logs_loop:
%mload_kernel(@SEGMENT_LOGS)
// stack: log_ptr, i, num_logs, receipt_ptr, txn_nb, new_cum_gas, txn_nb, num_nibbles, retdest
// Write payload_len.
PUSH @SEGMENT_LOGS_DATA %build_kernel_address
DUP1
%mload_kernel(@SEGMENT_LOGS_DATA)
MLOAD_GENERAL
%append_to_trie_data
// stack: log_ptr, i, num_logs, receipt_ptr, txn_nb, new_cum_gas, txn_nb, num_nibbles, retdest
// Write address.
%increment
// stack: addr_ptr, i, num_logs, receipt_ptr, txn_nb, new_cum_gas, txn_nb, num_nibbles, retdest
DUP1
%mload_kernel(@SEGMENT_LOGS_DATA)
MLOAD_GENERAL
%append_to_trie_data
// stack: addr_ptr, i, num_logs, receipt_ptr, txn_nb, new_cum_gas, txn_nb, num_nibbles, retdest
//Write num_topics.
%increment
// stack: num_topics_ptr, i, num_logs, receipt_ptr, txn_nb, new_cum_gas, txn_nb, num_nibbles, retdest
DUP1
%mload_kernel(@SEGMENT_LOGS_DATA)
MLOAD_GENERAL
// stack: num_topics, num_topics_ptr, i, num_logs, receipt_ptr, txn_nb, new_cum_gas, txn_nb, num_nibbles, retdest
DUP1
%append_to_trie_data
Expand All @@ -151,7 +152,7 @@ process_receipt_topics_loop:
DUP3 DUP2
ADD
// stack: cur_topic_ptr, j, num_topics, topics_ptr, i, num_logs, receipt_ptr, txn_nb, new_cum_gas, txn_nb, num_nibbles, retdest
%mload_kernel(@SEGMENT_LOGS_DATA)
MLOAD_GENERAL
%append_to_trie_data
// stack: j, num_topics, topics_ptr, i, num_logs, receipt_ptr, txn_nb, new_cum_gas, txn_nb, num_nibbles, retdest
%increment
Expand All @@ -164,7 +165,7 @@ process_receipt_topics_end:
// stack: data_len_ptr, i, num_logs, receipt_ptr, txn_nb, new_cum_gas, txn_nb, num_nibbles, retdest
// Write data_len
DUP1
%mload_kernel(@SEGMENT_LOGS_DATA)
MLOAD_GENERAL
// stack: data_len, data_len_ptr, i, num_logs, receipt_ptr, txn_nb, new_cum_gas, txn_nb, num_nibbles, retdest
DUP1
%append_to_trie_data
Expand All @@ -184,7 +185,7 @@ process_receipt_data_loop:
DUP3 DUP2
ADD
// stack: cur_data_ptr, j, data_len, data_ptr, i, num_logs, receipt_ptr, txn_nb, new_cum_gas, txn_nb, num_nibbles, retdest
%mload_kernel(@SEGMENT_LOGS_DATA)
MLOAD_GENERAL
%append_to_trie_data
// stack: j, data_len, data_ptr, i, num_logs, receipt_ptr, txn_nb, new_cum_gas, txn_nb, num_nibbles, retdest
%increment
Expand All @@ -205,19 +206,10 @@ process_receipt_after_write:
DUP5
%mpt_insert_receipt_trie
// stack: new_cum_gas, txn_nb, num_nibbles, retdest
// Now, we set the Bloom filter back to 0. We proceed by chunks of 32 bytes.
PUSH @SEGMENT_TXN_BLOOM // ctx == offset == 0
%rep 8
// stack: addr, new_cum_gas, txn_nb, num_nibbles, retdest
PUSH 0 // we will fill the memory segment with zeroes
DUP2
// stack: addr, 0, addr, new_cum_gas, txn_nb, num_nibbles, retdest
MSTORE_32BYTES_32
// stack: new_addr, addr, new_cum_gas, txn_nb, num_nibbles, retdest
SWAP1 POP
%endrep
POP
// stack: new_cum_gas, txn_nb, num_nibbles, retdest

// We don't need to reset the bloom filter segment as we only process a single transaction.
// TODO: Revert in case we add back support for multi-txn proofs.

%stack (new_cum_gas, txn_nb, num_nibbles, retdest) -> (retdest, new_cum_gas)
JUMP
Expand Down
Loading

0 comments on commit 10fc966

Please sign in to comment.