state-holding fix: track unique identifiers for Func's in CompHash's, not Func's themselves

This commit is contained in:
Vern Paxson 2022-04-16 16:17:57 -07:00
parent 0235541a95
commit 323b919eef
4 changed files with 45 additions and 31 deletions

View file

@ -260,13 +260,16 @@ bool CompositeHash::RecoverOneVal(const HashKey& hk, Type* t, ValPtr* pval, bool
{ {
uint32_t id; uint32_t id;
hk.Read("func", id); hk.Read("func", id);
const auto& f = Func::GetFuncPtrByID(id);
if ( ! f ) ASSERT(func_id_to_func != nullptr);
if ( id >= func_id_to_func->size() )
reporter->InternalError("failed to look up unique function id %" PRIu32 reporter->InternalError("failed to look up unique function id %" PRIu32
" in CompositeHash::RecoverOneVal()", " in CompositeHash::RecoverOneVal()",
id); id);
const auto& f = func_id_to_func->at(id);
*pval = make_intrusive<FuncVal>(f); *pval = make_intrusive<FuncVal>(f);
const auto& pvt = (*pval)->GetType(); const auto& pvt = (*pval)->GetType();
@ -547,7 +550,31 @@ bool CompositeHash::SingleValHash(HashKey& hk, const Val* v, Type* bt, bool type
switch ( v->GetType()->Tag() ) switch ( v->GetType()->Tag() )
{ {
case TYPE_FUNC: case TYPE_FUNC:
hk.Write("func", v->AsFunc()->GetUniqueFuncID()); {
auto f = v->AsFunc();
if ( ! func_to_func_id )
const_cast<CompositeHash*>(this)->BuildFuncMappings();
auto id_mapping = func_to_func_id->find(f);
uint32_t id;
if ( id_mapping == func_to_func_id->end() )
{
// We need the pointer to stick around
// for our lifetime, so we have to get
// a non-const version we can ref.
FuncPtr fptr = {NewRef{}, const_cast<Func*>(f)};
id = func_id_to_func->size();
func_id_to_func->push_back(std::move(fptr));
func_to_func_id->insert_or_assign(f, id);
}
else
id = id_mapping->second;
hk.Write("func", id);
}
break; break;
case TYPE_PATTERN: case TYPE_PATTERN:

View file

@ -4,7 +4,7 @@
#include <memory> #include <memory>
#include "zeek/IntrusivePtr.h" #include "zeek/Func.h"
#include "zeek/Type.h" #include "zeek/Type.h"
namespace zeek namespace zeek
@ -61,6 +61,18 @@ protected:
bool EnsureTypeReserve(HashKey& hk, const Val* v, Type* bt, bool type_check) const; bool EnsureTypeReserve(HashKey& hk, const Val* v, Type* bt, bool type_check) const;
// The following are for allowing hashing of function values.
// These can occur, for example, in sets of predicates that get
// iterated over. We use pointers in order to keep storage
// lower for the common case of these not being needed.
std::unique_ptr<std::unordered_map<const Func*, uint32_t>> func_to_func_id;
std::unique_ptr<std::vector<FuncPtr>> func_id_to_func;
void BuildFuncMappings()
{
func_to_func_id = std::make_unique<std::unordered_map<const Func*, uint32_t>>();
func_id_to_func = std::make_unique<std::vector<FuncPtr>>();
}
TypeListPtr type; TypeListPtr type;
bool is_singleton = false; // if just one type in index bool is_singleton = false; // if just one type in index
}; };

View file

@ -133,20 +133,6 @@ std::string render_call_stack()
return rval; return rval;
} }
Func::Func()
{
unique_id = unique_ids.size();
unique_ids.push_back({NewRef{}, this});
}
Func::Func(Kind arg_kind) : kind(arg_kind)
{
unique_id = unique_ids.size();
unique_ids.push_back({NewRef{}, this});
}
Func::~Func() = default;
void Func::AddBody(detail::StmtPtr /* new_body */, void Func::AddBody(detail::StmtPtr /* new_body */,
const std::vector<detail::IDPtr>& /* new_inits */, size_t /* new_frame_size */, const std::vector<detail::IDPtr>& /* new_inits */, size_t /* new_frame_size */,
int /* priority */) int /* priority */)
@ -238,7 +224,6 @@ void Func::CopyStateInto(Func* other) const
other->type = type; other->type = type;
other->name = name; other->name = name;
other->unique_id = unique_id;
} }
void Func::CheckPluginResult(bool handled, const ValPtr& hook_result, FunctionFlavor flavor) const void Func::CheckPluginResult(bool handled, const ValPtr& hook_result, FunctionFlavor flavor) const

View file

@ -61,9 +61,7 @@ public:
BUILTIN_FUNC BUILTIN_FUNC
}; };
explicit Func(Kind arg_kind); explicit Func(Kind arg_kind) : kind(arg_kind) { }
~Func() override;
virtual bool IsPure() const = 0; virtual bool IsPure() const = 0;
FunctionFlavor Flavor() const { return GetType()->Flavor(); } FunctionFlavor Flavor() const { return GetType()->Flavor(); }
@ -122,14 +120,8 @@ public:
virtual detail::TraversalCode Traverse(detail::TraversalCallback* cb) const; virtual detail::TraversalCode Traverse(detail::TraversalCallback* cb) const;
uint32_t GetUniqueFuncID() const { return unique_id; }
static const FuncPtr& GetFuncPtrByID(uint32_t id)
{
return id >= unique_ids.size() ? Func::nil : unique_ids[id];
}
protected: protected:
Func(); Func() = default;
// Copies this function's state into other. // Copies this function's state into other.
void CopyStateInto(Func* other) const; void CopyStateInto(Func* other) const;
@ -140,10 +132,8 @@ protected:
std::vector<Body> bodies; std::vector<Body> bodies;
detail::ScopePtr scope; detail::ScopePtr scope;
Kind kind = SCRIPT_FUNC; Kind kind = SCRIPT_FUNC;
uint32_t unique_id = 0;
FuncTypePtr type; FuncTypePtr type;
std::string name; std::string name;
static inline std::vector<FuncPtr> unique_ids;
}; };
namespace detail namespace detail