diff --git a/libraries/chain/controller.cpp b/libraries/chain/controller.cpp index bafe7933e9d..1b1f914db2d 100644 --- a/libraries/chain/controller.cpp +++ b/libraries/chain/controller.cpp @@ -313,6 +313,10 @@ struct controller_impl { set_activation_handler(); set_activation_handler(); + self.irreversible_block.connect([this](const block_state_ptr& bsp) { + wasmif.current_lib(bsp->block_num); + }); + #define SET_APP_HANDLER( receiver, contract, action) \ set_apply_handler( #receiver, #contract, #action, &BOOST_PP_CAT(apply_, BOOST_PP_CAT(contract, BOOST_PP_CAT(_,action) ) ) ) diff --git a/libraries/chain/eosio_contract.cpp b/libraries/chain/eosio_contract.cpp index 1fe849abb48..4a18406ee02 100644 --- a/libraries/chain/eosio_contract.cpp +++ b/libraries/chain/eosio_contract.cpp @@ -160,6 +160,7 @@ void apply_eosio_setcode(apply_context& context) { old_size = (int64_t)old_code_entry.code.size() * config::setcode_ram_bytes_multiplier; if( old_code_entry.code_ref_count == 1 ) { db.remove(old_code_entry); + context.control.get_wasm_interface().code_block_num_last_used(account.code_hash, account.vm_type, account.vm_version, context.control.head_block_num() + 1); } else { db.modify(old_code_entry, [](code_object& o) { --o.code_ref_count; diff --git a/libraries/chain/include/eosio/chain/wasm_interface.hpp b/libraries/chain/include/eosio/chain/wasm_interface.hpp index 5ddea081d48..b5749179a9b 100644 --- a/libraries/chain/include/eosio/chain/wasm_interface.hpp +++ b/libraries/chain/include/eosio/chain/wasm_interface.hpp @@ -82,6 +82,12 @@ namespace eosio { namespace chain { //validates code -- does a WASM validation pass and checks the wasm against EOSIO specific constraints static void validate(const controller& control, const bytes& code); + //indicate that a particular code probably won't be used after given block_num + void code_block_num_last_used(const digest_type& code_hash, const uint8_t& vm_type, const uint8_t& vm_version, const uint32_t& block_num); + + //indicate the current LIB. evicts old cache entries + void current_lib(const uint32_t lib); + //Calls apply or error on a given code void apply(const digest_type& code_hash, const uint8_t& vm_type, const uint8_t& vm_version, apply_context& context); diff --git a/libraries/chain/include/eosio/chain/wasm_interface_private.hpp b/libraries/chain/include/eosio/chain/wasm_interface_private.hpp index 362a29e19f0..2f59bccf69f 100644 --- a/libraries/chain/include/eosio/chain/wasm_interface_private.hpp +++ b/libraries/chain/include/eosio/chain/wasm_interface_private.hpp @@ -64,6 +64,19 @@ namespace eosio { namespace chain { return mem_image; } + void code_block_num_last_used(const digest_type& code_hash, const uint8_t& vm_type, const uint8_t& vm_version, const uint32_t& block_num) { + wasm_cache_index::iterator it = wasm_instantiation_cache.find(boost::make_tuple(code_hash, vm_type, vm_version)); + if(it != wasm_instantiation_cache.end()) + wasm_instantiation_cache.modify(it, [block_num](wasm_cache_entry& e) { + e.last_block_num_used = block_num; + }); + } + + void current_lib(uint32_t lib) { + //anything last used before or on the LIB can be evicted + wasm_instantiation_cache.get().erase(wasm_instantiation_cache.get().begin(), wasm_instantiation_cache.get().upper_bound(lib)); + } + const std::unique_ptr& get_instantiated_module( const digest_type& code_hash, const uint8_t& vm_type, const uint8_t& vm_version, transaction_context& trx_context ) { diff --git a/libraries/chain/wasm_interface.cpp b/libraries/chain/wasm_interface.cpp index 9fd144a3cb1..75682ff4b80 100644 --- a/libraries/chain/wasm_interface.cpp +++ b/libraries/chain/wasm_interface.cpp @@ -57,6 +57,14 @@ namespace eosio { namespace chain { //Hard: Kick off instantiation in a separate thread at this location } + void wasm_interface::code_block_num_last_used(const digest_type& code_hash, const uint8_t& vm_type, const uint8_t& vm_version, const uint32_t& block_num) { + my->code_block_num_last_used(code_hash, vm_type, vm_version, block_num); + } + + void wasm_interface::current_lib(const uint32_t lib) { + my->current_lib(lib); + } + void wasm_interface::apply( const digest_type& code_hash, const uint8_t& vm_type, const uint8_t& vm_version, apply_context& context ) { my->get_instantiated_module(code_hash, vm_type, vm_version, context.trx_context)->apply(context); }