diff --git a/clients/drcachesim/tests/decode_cache_test.cpp b/clients/drcachesim/tests/decode_cache_test.cpp index 43235bce432..a5274752431 100644 --- a/clients/drcachesim/tests/decode_cache_test.cpp +++ b/clients/drcachesim/tests/decode_cache_test.cpp @@ -161,6 +161,14 @@ check_decode_caching(void *drcontext, bool persist_instrs, bool use_module_mappe if (decode_info_nop_2 != decode_info_nop) { return "Did not see same decode info instance for second instance of nop"; } + decode_cache.clear_cache(); + decode_info_nop = + decode_cache.get_decode_info(reinterpret_cast(memrefs[0].instr.addr)); + decode_info_ret = + decode_cache.get_decode_info(reinterpret_cast(memrefs[1].instr.addr)); + if (decode_info_nop != nullptr || decode_info_ret != nullptr) { + return "Cached decode info not cleared after clear_cache()"; + } } instrlist_clear_and_destroy(drcontext, ilist); std::cerr << "check_decode_caching with persist_instrs: " << persist_instrs diff --git a/clients/drcachesim/tools/common/decode_cache.h b/clients/drcachesim/tools/common/decode_cache.h index 7b89e83c023..60214c1c752 100644 --- a/clients/drcachesim/tools/common/decode_cache.h +++ b/clients/drcachesim/tools/common/decode_cache.h @@ -350,6 +350,24 @@ template class decode_cache_t : public decode_cache_base_t { return init_module_mapper(module_file_path, alt_module_dir); } + /** + * Clears all cached decode info entries. + * + * Typically analysis tools like to keep their per-shard data around till all shards + * are done processing (so they can combine the shards and use the results), but + * this API allows tools to keep memory consumption in check by clearing the decode + * cache entries in parallel_shard_exit(), since it's very likely that the decode + * cache is not needed for result computation. + * + * This does not affect the state of any initialized module mapper, which is still + * cleaned up during destruction. + */ + void + clear_cache() + { + decode_cache_.clear(); + } + private: std::unordered_map decode_cache_; void *dcontext_ = nullptr; diff --git a/clients/drcachesim/tools/invariant_checker.cpp b/clients/drcachesim/tools/invariant_checker.cpp index 00c26b276d8..b93abd2b132 100644 --- a/clients/drcachesim/tools/invariant_checker.cpp +++ b/clients/drcachesim/tools/invariant_checker.cpp @@ -174,6 +174,8 @@ bool invariant_checker_t::parallel_shard_exit(void *shard_data) { per_shard_t *shard = reinterpret_cast(shard_data); + if (shard->decode_cache_ != nullptr) + shard->decode_cache_->clear_cache(); report_if_false(shard, shard->saw_thread_exit_ // XXX i#6733: For online we sometimes see threads diff --git a/clients/drcachesim/tools/opcode_mix.cpp b/clients/drcachesim/tools/opcode_mix.cpp index 9b9735631b2..fe0e50ef7d8 100644 --- a/clients/drcachesim/tools/opcode_mix.cpp +++ b/clients/drcachesim/tools/opcode_mix.cpp @@ -143,7 +143,10 @@ opcode_mix_t::parallel_shard_init_stream( bool opcode_mix_t::parallel_shard_exit(void *shard_data) { - // Nothing (we read the shard data in print_results). + shard_data_t *shard = reinterpret_cast(shard_data); + if (shard->decode_cache != nullptr) + shard->decode_cache->clear_cache(); + // We still need the remaining shard data in print_results. return true; } @@ -434,8 +437,8 @@ opcode_mix_t::opcode_data_t::set_decode_info_derived( void *dcontext, const dynamorio::drmemtrace::_memref_instr_t &memref_instr, instr_t *instr) { - opcode = instr_get_opcode(instr); - category = instr_get_category(instr); + opcode_ = instr_get_opcode(instr); + category_ = instr_get_category(instr); } } // namespace drmemtrace