From adf3648554f600c9c5df5faf64752e2af7b4ffd2 Mon Sep 17 00:00:00 2001 From: Vern Paxson Date: Wed, 11 Sep 2024 16:47:54 +0200 Subject: [PATCH] fixes (to avoid collisions) for AST profiling's function hash computations --- src/script_opt/ProfileFunc.cc | 24 +++++++++++++++++------- src/script_opt/ProfileFunc.h | 11 ++++++++--- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/src/script_opt/ProfileFunc.cc b/src/script_opt/ProfileFunc.cc index e844bfb566..25d6a5e01d 100644 --- a/src/script_opt/ProfileFunc.cc +++ b/src/script_opt/ProfileFunc.cc @@ -584,8 +584,9 @@ ProfileFuncs::ProfileFuncs(std::vector& funcs, is_compilable_pred pred // side effects. // Propagate previous hash if requested. - if ( ! compute_func_hashes && f.Profile() ) - pf->SetHashVal(f.Profile()->HashVal()); + auto prev_pf = f.Profile(); + if ( ! compute_func_hashes && prev_pf && prev_pf->HasHashVal() ) + pf->SetHashVal(prev_pf->HashVal()); f.SetProfile(std::move(pf)); func_profs[f.Func()] = f.ProfilePtr(); @@ -834,17 +835,20 @@ void ProfileFuncs::ComputeTypeHashes(const std::vector& types) { } void ProfileFuncs::ComputeBodyHashes(std::vector& funcs) { - if ( compute_func_hashes ) - for ( auto& f : funcs ) - if ( ! f.ShouldSkip() ) - ComputeProfileHash(f.ProfilePtr()); + for ( auto& f : funcs ) { + if ( f.ShouldSkip() ) + continue; + auto pf = f.ProfilePtr(); + if ( compute_func_hashes || ! pf->HasHashVal() ) + ComputeProfileHash(f.ProfilePtr()); + } for ( auto& l : lambdas ) { auto pf = ExprProf(l); func_profs[l->PrimaryFunc().get()] = pf; lambda_primaries[l->Name()] = l->PrimaryFunc().get(); - if ( compute_func_hashes ) + if ( compute_func_hashes || ! pf->HasHashVal() ) ComputeProfileHash(pf); } } @@ -856,6 +860,12 @@ void ProfileFuncs::ComputeProfileHash(std::shared_ptr pf) { // prevent collisions due to elements with simple hashes // (such as Stmt's or Expr's that are only represented by // the hash of their tag). + h = merge_p_hashes(h, p_hash("params")); + auto& ov = pf->ProfiledScope()->OrderedVars(); + int n = pf->NumParams(); + for ( int i = 0; i < n; ++i ) + h = merge_p_hashes(h, p_hash(ov[i]->Name())); + h = merge_p_hashes(h, p_hash("stmts")); for ( auto i : pf->Stmts() ) h = merge_p_hashes(h, p_hash(i->Tag())); diff --git a/src/script_opt/ProfileFunc.h b/src/script_opt/ProfileFunc.h index 8acd15729f..9a2c53bc02 100644 --- a/src/script_opt/ProfileFunc.h +++ b/src/script_opt/ProfileFunc.h @@ -131,7 +131,11 @@ public: // Set this function's hash to the given value; retrieve that value. void SetHashVal(p_hash_type hash) { hash_val = hash; } - p_hash_type HashVal() const { return hash_val; } + p_hash_type HashVal() const { + ASSERT(hash_val); + return *hash_val; + } + bool HasHashVal() const { return bool(hash_val); } protected: // Construct the profile for the given function signature and body. @@ -286,7 +290,7 @@ protected: std::vector addl_hashes; // Associated hash value. - p_hash_type hash_val = 0; + std::optional hash_val; // How many when statements appear in the function body. We could // track these individually, but to date all that's mattered is @@ -610,7 +614,8 @@ protected: // These can arise for example due to lambdas or record attributes. std::vector pending_exprs; - // Whether to compute new hashes for the FuncInfo entries. + // Whether to compute new hashes for the FuncInfo entries. If the FuncInfo + // doesn't have a hash, it will always be computed. bool compute_func_hashes; // Whether the hashes for extended records should cover their final,