mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
restored support for incremental compilation of scripts to C++
This commit is contained in:
parent
3b3cea799b
commit
2f7137999f
11 changed files with 37 additions and 56 deletions
|
@ -585,10 +585,6 @@ private:
|
||||||
// function name, and maps to the C++ name.
|
// function name, and maps to the C++ name.
|
||||||
std::unordered_map<std::string, std::string> compiled_simple_funcs;
|
std::unordered_map<std::string, std::string> compiled_simple_funcs;
|
||||||
|
|
||||||
// Maps those to their associated files - used to make add-C++ body
|
|
||||||
// hashes distinct.
|
|
||||||
std::unordered_map<std::string, std::string> cf_locs;
|
|
||||||
|
|
||||||
// Maps function bodies to the names we use for them.
|
// Maps function bodies to the names we use for them.
|
||||||
std::unordered_map<const Stmt*, std::string> body_names;
|
std::unordered_map<const Stmt*, std::string> body_names;
|
||||||
|
|
||||||
|
|
|
@ -99,9 +99,6 @@ void CPPCompile::CreateFunction(const FuncTypePtr& ft, const ProfileFunc* pf, co
|
||||||
// for lambdas that don't take any arguments, but that
|
// for lambdas that don't take any arguments, but that
|
||||||
// seems potentially more confusing than beneficial.
|
// seems potentially more confusing than beneficial.
|
||||||
compiled_funcs.emplace(fname);
|
compiled_funcs.emplace(fname);
|
||||||
|
|
||||||
auto loc_f = script_specific_filename(body);
|
|
||||||
cf_locs[fname] = loc_f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto h = pf->HashVal();
|
auto h = pf->HashVal();
|
||||||
|
|
|
@ -197,10 +197,10 @@ void CPPCompile::Compile(bool report_uncompilable)
|
||||||
|
|
||||||
void CPPCompile::GenProlog()
|
void CPPCompile::GenProlog()
|
||||||
{
|
{
|
||||||
if ( addl_tag == 0 )
|
if ( addl_tag <= 1 )
|
||||||
{
|
// This is either a compilation via gen-C++, or
|
||||||
|
// one using add-C++ and an empty CPP-gen.cc file.
|
||||||
Emit("#include \"zeek/script_opt/CPP/Runtime.h\"\n");
|
Emit("#include \"zeek/script_opt/CPP/Runtime.h\"\n");
|
||||||
}
|
|
||||||
|
|
||||||
Emit("namespace zeek::detail { //\n");
|
Emit("namespace zeek::detail { //\n");
|
||||||
Emit("namespace CPP_%s { // %s\n", Fmt(addl_tag), working_dir);
|
Emit("namespace CPP_%s { // %s\n", Fmt(addl_tag), working_dir);
|
||||||
|
@ -292,13 +292,6 @@ void CPPCompile::RegisterCompiledBody(const string& f)
|
||||||
|
|
||||||
events = string("{") + events + "}";
|
events = string("{") + events + "}";
|
||||||
|
|
||||||
if ( addl_tag > 0 )
|
|
||||||
// Hash in the location associated with this compilation
|
|
||||||
// pass, to get a final hash that avoids conflicts with
|
|
||||||
// identical-but-in-a-different-context function bodies
|
|
||||||
// when compiling potentially conflicting additional code.
|
|
||||||
h = merge_p_hashes(h, p_hash(cf_locs[f]));
|
|
||||||
|
|
||||||
auto fi = func_index.find(f);
|
auto fi = func_index.find(f);
|
||||||
ASSERT(fi != func_index.end());
|
ASSERT(fi != func_index.end());
|
||||||
auto type_signature = casting_index[fi->second];
|
auto type_signature = casting_index[fi->second];
|
||||||
|
|
|
@ -105,6 +105,7 @@ struct CompiledScript
|
||||||
CPPStmtPtr body;
|
CPPStmtPtr body;
|
||||||
int priority;
|
int priority;
|
||||||
std::vector<std::string> events;
|
std::vector<std::string> events;
|
||||||
|
void (*finish_init_func)();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Maps hashes to compiled information.
|
// Maps hashes to compiled information.
|
||||||
|
|
|
@ -239,14 +239,14 @@ void FuncConstInfo::InitializerVals(std::vector<std::string>& ivs) const
|
||||||
{
|
{
|
||||||
auto f = fv->AsFunc();
|
auto f = fv->AsFunc();
|
||||||
const auto& fn = f->Name();
|
const auto& fn = f->Name();
|
||||||
|
const auto& bodies = f->GetBodies();
|
||||||
|
|
||||||
ivs.emplace_back(Fmt(type));
|
ivs.emplace_back(Fmt(type));
|
||||||
ivs.emplace_back(Fmt(c->TrackString(fn)));
|
ivs.emplace_back(Fmt(c->TrackString(fn)));
|
||||||
|
ivs.emplace_back(to_string(bodies.size()));
|
||||||
|
|
||||||
if ( ! c->NotFullyCompilable(fn) )
|
if ( ! c->NotFullyCompilable(fn) )
|
||||||
{
|
{
|
||||||
const auto& bodies = f->GetBodies();
|
|
||||||
|
|
||||||
for ( const auto& b : bodies )
|
for ( const auto& b : bodies )
|
||||||
{
|
{
|
||||||
auto h = c->BodyHash(b.stmts.get());
|
auto h = c->BodyHash(b.stmts.get());
|
||||||
|
|
|
@ -62,9 +62,10 @@ void register_type__CPP(TypePtr t, const string& name)
|
||||||
id->MakeType();
|
id->MakeType();
|
||||||
}
|
}
|
||||||
|
|
||||||
void register_body__CPP(CPPStmtPtr body, int priority, p_hash_type hash, vector<string> events)
|
void register_body__CPP(CPPStmtPtr body, int priority, p_hash_type hash, vector<string> events,
|
||||||
|
void (*finish_init)())
|
||||||
{
|
{
|
||||||
compiled_scripts[hash] = {move(body), priority, move(events)};
|
compiled_scripts[hash] = {move(body), priority, move(events), finish_init};
|
||||||
}
|
}
|
||||||
|
|
||||||
void register_lambda__CPP(CPPStmtPtr body, p_hash_type hash, const char* name, TypePtr t,
|
void register_lambda__CPP(CPPStmtPtr body, p_hash_type hash, const char* name, TypePtr t,
|
||||||
|
@ -89,7 +90,7 @@ void register_lambda__CPP(CPPStmtPtr body, p_hash_type hash, const char* name, T
|
||||||
if ( ! has_captures )
|
if ( ! has_captures )
|
||||||
// Note, no support for lambdas that themselves refer
|
// Note, no support for lambdas that themselves refer
|
||||||
// to events.
|
// to events.
|
||||||
register_body__CPP(body, 0, hash, {});
|
register_body__CPP(body, 0, hash, {}, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void register_scripts__CPP(p_hash_type h, void (*callback)())
|
void register_scripts__CPP(p_hash_type h, void (*callback)())
|
||||||
|
@ -190,11 +191,12 @@ Func* lookup_bif__CPP(const char* bif)
|
||||||
return b ? b->GetVal()->AsFunc() : nullptr;
|
return b ? b->GetVal()->AsFunc() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
FuncValPtr lookup_func__CPP(string name, vector<p_hash_type> hashes, const TypePtr& t)
|
FuncValPtr lookup_func__CPP(string name, int num_bodies, vector<p_hash_type> hashes,
|
||||||
|
const TypePtr& t)
|
||||||
{
|
{
|
||||||
auto ft = cast_intrusive<FuncType>(t);
|
auto ft = cast_intrusive<FuncType>(t);
|
||||||
|
|
||||||
if ( hashes.empty() )
|
if ( static_cast<int>(hashes.size()) < num_bodies )
|
||||||
{
|
{
|
||||||
// This happens for functions that have at least one
|
// This happens for functions that have at least one
|
||||||
// uncompilable body.
|
// uncompilable body.
|
||||||
|
|
|
@ -37,7 +37,7 @@ extern void register_type__CPP(TypePtr t, const std::string& name);
|
||||||
// relevant for the function body, which should be registered if the
|
// relevant for the function body, which should be registered if the
|
||||||
// function body is going to be used.
|
// function body is going to be used.
|
||||||
extern void register_body__CPP(CPPStmtPtr body, int priority, p_hash_type hash,
|
extern void register_body__CPP(CPPStmtPtr body, int priority, p_hash_type hash,
|
||||||
std::vector<std::string> events);
|
std::vector<std::string> events, void (*finish_init)());
|
||||||
|
|
||||||
// Registers a lambda body as associated with the given hash. Includes
|
// Registers a lambda body as associated with the given hash. Includes
|
||||||
// the name of the lambda (so it can be made available as a quasi-global
|
// the name of the lambda (so it can be made available as a quasi-global
|
||||||
|
@ -67,7 +67,8 @@ extern Func* lookup_bif__CPP(const char* bif);
|
||||||
// returns an associated FuncVal. It's a fatal error for the hash
|
// returns an associated FuncVal. It's a fatal error for the hash
|
||||||
// not to exist, because this function should only be called by compiled
|
// not to exist, because this function should only be called by compiled
|
||||||
// code that has ensured its existence.
|
// code that has ensured its existence.
|
||||||
extern FuncValPtr lookup_func__CPP(std::string name, std::vector<p_hash_type> h, const TypePtr& t);
|
extern FuncValPtr lookup_func__CPP(std::string name, int num_bodies, std::vector<p_hash_type> h,
|
||||||
|
const TypePtr& t);
|
||||||
|
|
||||||
// Returns the record corresponding to the given name, as long as the
|
// Returns the record corresponding to the given name, as long as the
|
||||||
// name is indeed a record type. Otherwise (or if the name is nil)
|
// name is indeed a record type. Otherwise (or if the name is nil)
|
||||||
|
|
|
@ -147,13 +147,14 @@ void CPP_IndexedInits<T>::Generate(InitsManager* im, std::vector<FuncValPtr>& iv
|
||||||
auto iv_end = init_vals.end();
|
auto iv_end = init_vals.end();
|
||||||
auto t = *(iv_it++);
|
auto t = *(iv_it++);
|
||||||
auto fn = im->Strings(*(iv_it++));
|
auto fn = im->Strings(*(iv_it++));
|
||||||
|
auto num_bodies = *(iv_it++);
|
||||||
|
|
||||||
std::vector<p_hash_type> hashes;
|
std::vector<p_hash_type> hashes;
|
||||||
|
|
||||||
while ( iv_it != iv_end )
|
while ( iv_it != iv_end )
|
||||||
hashes.push_back(im->Hashes(*(iv_it++)));
|
hashes.push_back(im->Hashes(*(iv_it++)));
|
||||||
|
|
||||||
ivec[offset] = lookup_func__CPP(fn, hashes, im->Types(t));
|
ivec[offset] = lookup_func__CPP(fn, num_bodies, hashes, im->Types(t));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
|
|
|
@ -23,7 +23,13 @@ p_hash_type p_hash(const Obj* o)
|
||||||
return p_hash(d.Description());
|
return p_hash(d.Description());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string script_specific_filename(const StmtPtr& body)
|
// Returns a filename associated with the given function body. Used to
|
||||||
|
// provide distinctness to identical function bodies seen in separate,
|
||||||
|
// potentially conflicting incremental compilations. An example of this
|
||||||
|
// is a function named foo() that calls bar(), for which in two different
|
||||||
|
// compilation contexts bar() has differing semantics, even though foo()'s
|
||||||
|
// (shallow) semantics are the same.
|
||||||
|
static std::string script_specific_filename(const Stmt* body)
|
||||||
{
|
{
|
||||||
// The specific filename is taken from the location filename, making
|
// The specific filename is taken from the location filename, making
|
||||||
// it absolute if necessary.
|
// it absolute if necessary.
|
||||||
|
@ -52,12 +58,15 @@ std::string script_specific_filename(const StmtPtr& body)
|
||||||
return bl_f;
|
return bl_f;
|
||||||
}
|
}
|
||||||
|
|
||||||
p_hash_type script_specific_hash(const StmtPtr& body, p_hash_type generic_hash)
|
// Returns a incremental-compilation-specific hash for the given function
|
||||||
|
// body, given its non-specific hash is "generic_hash".
|
||||||
|
static p_hash_type script_specific_hash(const Stmt* body, p_hash_type generic_hash)
|
||||||
{
|
{
|
||||||
auto bl_f = script_specific_filename(body);
|
auto bl_f = script_specific_filename(body);
|
||||||
return merge_p_hashes(generic_hash, p_hash(bl_f));
|
return merge_p_hashes(generic_hash, p_hash(bl_f));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ProfileFunc::ProfileFunc(const Func* func, const StmtPtr& body, bool _abs_rec_fields)
|
ProfileFunc::ProfileFunc(const Func* func, const StmtPtr& body, bool _abs_rec_fields)
|
||||||
{
|
{
|
||||||
profiled_func = func;
|
profiled_func = func;
|
||||||
|
@ -698,6 +707,9 @@ void ProfileFuncs::ComputeProfileHash(std::shared_ptr<ProfileFunc> pf)
|
||||||
for ( auto i : pf->AdditionalHashes() )
|
for ( auto i : pf->AdditionalHashes() )
|
||||||
h = merge_p_hashes(h, i);
|
h = merge_p_hashes(h, i);
|
||||||
|
|
||||||
|
if ( ! pf->Stmts().empty() )
|
||||||
|
h = script_specific_hash(pf->Stmts()[0], h);
|
||||||
|
|
||||||
pf->SetHashVal(h);
|
pf->SetHashVal(h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -74,17 +74,6 @@ inline p_hash_type merge_p_hashes(p_hash_type h1, p_hash_type h2)
|
||||||
return h1 ^ (h2 + 0x9e3779b9 + (h1 << 6) + (h1 >> 2));
|
return h1 ^ (h2 + 0x9e3779b9 + (h1 << 6) + (h1 >> 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a filename associated with the given function body. Used to
|
|
||||||
// provide distinctness to identical function bodies seen in separate,
|
|
||||||
// potentially conflicting incremental compilations. This is only germane
|
|
||||||
// for allowing incremental compilation of subsets of the test suite, so
|
|
||||||
// if we decide to forgo that capability, we can remove this.
|
|
||||||
extern std::string script_specific_filename(const StmtPtr& body);
|
|
||||||
|
|
||||||
// Returns a incremental-compilation-specific hash for the given function
|
|
||||||
// body, given it's non-specific hash is "generic_hash".
|
|
||||||
extern p_hash_type script_specific_hash(const StmtPtr& body, p_hash_type generic_hash);
|
|
||||||
|
|
||||||
// Class for profiling the components of a single function (or expression).
|
// Class for profiling the components of a single function (or expression).
|
||||||
class ProfileFunc : public TraversalCallback
|
class ProfileFunc : public TraversalCallback
|
||||||
{
|
{
|
||||||
|
|
|
@ -350,17 +350,8 @@ static void report_CPP()
|
||||||
auto name = f.Func()->Name();
|
auto name = f.Func()->Name();
|
||||||
auto hash = f.Profile()->HashVal();
|
auto hash = f.Profile()->HashVal();
|
||||||
bool have = compiled_scripts.count(hash) > 0;
|
bool have = compiled_scripts.count(hash) > 0;
|
||||||
auto specific = "";
|
|
||||||
|
|
||||||
if ( ! have )
|
printf("script function %s (hash %llu): %s\n", name, hash, have ? "yes" : "no");
|
||||||
{
|
|
||||||
hash = script_specific_hash(f.Body(), hash);
|
|
||||||
have = compiled_scripts.count(hash) > 0;
|
|
||||||
if ( have )
|
|
||||||
specific = " - specific";
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("script function %s (hash %llu%s): %s\n", name, hash, specific, have ? "yes" : "no");
|
|
||||||
|
|
||||||
if ( have )
|
if ( have )
|
||||||
already_reported.insert(hash);
|
already_reported.insert(hash);
|
||||||
|
@ -387,12 +378,6 @@ static void use_CPP()
|
||||||
auto hash = f.Profile()->HashVal();
|
auto hash = f.Profile()->HashVal();
|
||||||
auto s = compiled_scripts.find(hash);
|
auto s = compiled_scripts.find(hash);
|
||||||
|
|
||||||
if ( s == compiled_scripts.end() )
|
|
||||||
{ // Look for script-specific body.
|
|
||||||
hash = script_specific_hash(f.Body(), hash);
|
|
||||||
s = compiled_scripts.find(hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( s != compiled_scripts.end() )
|
if ( s != compiled_scripts.end() )
|
||||||
{
|
{
|
||||||
auto b = s->second.body;
|
auto b = s->second.body;
|
||||||
|
@ -418,6 +403,10 @@ static void use_CPP()
|
||||||
auto h = event_registry->Register(e);
|
auto h = event_registry->Register(e);
|
||||||
h->SetUsed();
|
h->SetUsed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto finish = s->second.finish_init_func;
|
||||||
|
if ( finish )
|
||||||
|
(*finish)();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue