mirror of
https://github.com/zeek/zeek.git
synced 2025-10-09 10:08:20 +00:00
Merge remote-tracking branch 'origin/topic/vern/record-optimizations.Apr23B'
* origin/topic/vern/record-optimizations.Apr23B: different fix for MSVC compiler issues more general approach for addressing MSVC compiler issues with IntrusivePtr restored RecordType::Create, now marked as deprecated tidying of namespaces and private class members simplification of flagging record field initializations that should be skipped address peculiar MSVC compilation complaint for IntrusivePtr's clarifications and tidying for record field initializations optimize record construction by deferring initializations of aggregates compile-scripts-to-C++ speedups by switching to raw record access logging speedup by switching to raw record access remove redundant record coercions Removed the `#if 0` hunk during merging: Probably could have gone with a doctest instead.
This commit is contained in:
commit
89c828ac14
14 changed files with 399 additions and 205 deletions
249
src/Type.cc
249
src/Type.cc
|
@ -992,41 +992,118 @@ void TypeDecl::DescribeReST(ODesc* d, bool roles_only) const
|
|||
}
|
||||
}
|
||||
|
||||
// The following tracks how to initialize a given field, for fast execution
|
||||
// of Create().
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class FieldInit
|
||||
// A record field initialization that directly assigns a fixed value ...
|
||||
class DirectFieldInit final : public FieldInit
|
||||
{
|
||||
public:
|
||||
// The type of initialization for the field.
|
||||
enum
|
||||
{
|
||||
R_INIT_NONE, // skip this entry
|
||||
DirectFieldInit(ZVal _init_val) : init_val(_init_val) { }
|
||||
|
||||
R_INIT_DIRECT, // look in direct_init for raw value
|
||||
R_INIT_DIRECT_MANAGED, // same, but managed type
|
||||
ZVal Generate() const override { return init_val; }
|
||||
|
||||
R_INIT_DEF, // look in def_expr for expression
|
||||
|
||||
R_INIT_RECORD, // field requires a new record
|
||||
R_INIT_TABLE, // field requires a new table/set
|
||||
R_INIT_VECTOR, // field requires a new vector
|
||||
} init_type = R_INIT_NONE;
|
||||
|
||||
bool def_coerce = false; // whether coercion's required
|
||||
|
||||
// For R_INIT_DIRECT/R_INIT_DIRECT_MANAGED:
|
||||
ZVal direct_init;
|
||||
|
||||
detail::ExprPtr def_expr;
|
||||
TypePtr def_type;
|
||||
|
||||
RecordTypePtr r_type; // for R_INIT_RECORD
|
||||
TableTypePtr t_type; // for R_INIT_TABLE
|
||||
detail::AttributesPtr attrs; // attributes for R_INIT_TABLE
|
||||
VectorTypePtr v_type; // for R_INIT_VECTOR
|
||||
private:
|
||||
ZVal init_val;
|
||||
};
|
||||
|
||||
// ... the same, but for a value that needs memory management.
|
||||
class DirectManagedFieldInit final : public FieldInit
|
||||
{
|
||||
public:
|
||||
DirectManagedFieldInit(ZVal _init_val) : init_val(_init_val) { }
|
||||
~DirectManagedFieldInit() { ZVal::DeleteManagedType(init_val); }
|
||||
|
||||
ZVal Generate() const override
|
||||
{
|
||||
zeek::Ref(init_val.ManagedVal());
|
||||
return init_val;
|
||||
}
|
||||
|
||||
private:
|
||||
ZVal init_val;
|
||||
};
|
||||
|
||||
// A record field initialization that's done by evaluating an expression.
|
||||
class ExprFieldInit final : public FieldInit
|
||||
{
|
||||
public:
|
||||
// Initialization requires evaluating the given expression,
|
||||
// yielding the a value of the given type (which might require
|
||||
// coercion for some records).
|
||||
ExprFieldInit(detail::ExprPtr _init_expr, TypePtr _init_type)
|
||||
: init_expr(std::move(_init_expr)), init_type(std::move(_init_type))
|
||||
{
|
||||
if ( init_type->Tag() == TYPE_RECORD && ! same_type(init_expr->GetType(), init_type) )
|
||||
coerce_type = cast_intrusive<RecordType>(init_type);
|
||||
}
|
||||
|
||||
ZVal Generate() const override
|
||||
{
|
||||
auto v = init_expr->Eval(nullptr);
|
||||
if ( ! v )
|
||||
{
|
||||
reporter->Error("failed &default in record creation");
|
||||
return ZVal();
|
||||
}
|
||||
|
||||
if ( coerce_type )
|
||||
v = v->AsRecordVal()->CoerceTo(coerce_type);
|
||||
|
||||
return ZVal(v, init_type);
|
||||
}
|
||||
|
||||
private:
|
||||
detail::ExprPtr init_expr;
|
||||
TypePtr init_type;
|
||||
RecordTypePtr coerce_type; // non-nil iff coercion is required
|
||||
};
|
||||
|
||||
// A record field initialization where the field is initialized to an
|
||||
// empty/default record of the given type.
|
||||
class RecordFieldInit final : public FieldInit
|
||||
{
|
||||
public:
|
||||
RecordFieldInit(RecordTypePtr _init_type) : init_type(std::move(_init_type)) { }
|
||||
|
||||
ZVal Generate() const override { return ZVal(new RecordVal(init_type)); }
|
||||
|
||||
private:
|
||||
RecordTypePtr init_type;
|
||||
};
|
||||
|
||||
// A record field initialization where the field is initialized to an
|
||||
// empty table of the given type.
|
||||
class TableFieldInit final : public FieldInit
|
||||
{
|
||||
public:
|
||||
TableFieldInit(TableTypePtr _init_type, detail::AttributesPtr _attrs)
|
||||
: init_type(std::move(_init_type)), attrs(std::move(_attrs))
|
||||
{
|
||||
}
|
||||
|
||||
ZVal Generate() const override { return ZVal(new TableVal(init_type, attrs)); }
|
||||
|
||||
private:
|
||||
TableTypePtr init_type;
|
||||
detail::AttributesPtr attrs;
|
||||
};
|
||||
|
||||
// A record field initialization where the field is initialized to an
|
||||
// empty vector of the given type.
|
||||
class VectorFieldInit final : public FieldInit
|
||||
{
|
||||
public:
|
||||
VectorFieldInit(VectorTypePtr _init_type) : init_type(std::move(_init_type)) { }
|
||||
|
||||
ZVal Generate() const override { return ZVal(new VectorVal(init_type)); }
|
||||
|
||||
private:
|
||||
VectorTypePtr init_type;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
RecordType::RecordType(type_decl_list* arg_types) : Type(TYPE_RECORD)
|
||||
{
|
||||
types = arg_types;
|
||||
|
@ -1062,65 +1139,52 @@ RecordType::~RecordType()
|
|||
|
||||
delete types;
|
||||
}
|
||||
|
||||
for ( auto fi : field_inits )
|
||||
delete fi;
|
||||
}
|
||||
|
||||
void RecordType::AddField(unsigned int field, const TypeDecl* td)
|
||||
{
|
||||
ASSERT(field == field_inits.size());
|
||||
ASSERT(field == deferred_inits.size());
|
||||
ASSERT(field == managed_fields.size());
|
||||
|
||||
managed_fields.push_back(ZVal::IsManagedType(td->type));
|
||||
|
||||
auto init = new FieldInit();
|
||||
init->init_type = FieldInit::R_INIT_NONE;
|
||||
|
||||
init->attrs = td->attrs;
|
||||
|
||||
// We defer error-checking until here so that we can keep field_inits
|
||||
// We defer error-checking until here so that we can keep deferred_inits
|
||||
// and managed_fields correctly tracking the associated fields.
|
||||
|
||||
if ( field_ids.count(td->id) != 0 )
|
||||
{
|
||||
reporter->Error("duplicate field '%s' found in record definition", td->id);
|
||||
field_inits.push_back(init);
|
||||
deferred_inits.push_back(nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
field_ids.insert(std::string(td->id));
|
||||
|
||||
auto a = init->attrs;
|
||||
|
||||
auto a = td->attrs;
|
||||
auto type = td->type;
|
||||
|
||||
auto def_attr = a ? a->Find(detail::ATTR_DEFAULT) : nullptr;
|
||||
auto def_expr = def_attr ? def_attr->GetExpr() : nullptr;
|
||||
|
||||
std::unique_ptr<detail::FieldInit> init;
|
||||
|
||||
if ( def_expr && ! IsErrorType(type->Tag()) )
|
||||
{
|
||||
if ( type->Tag() == TYPE_RECORD && def_expr->GetType()->Tag() == TYPE_RECORD &&
|
||||
! same_type(def_expr->GetType(), type) )
|
||||
init->def_coerce = true;
|
||||
|
||||
if ( def_expr->Tag() == detail::EXPR_CONST )
|
||||
{
|
||||
auto v = def_expr->Eval(nullptr);
|
||||
auto zv = ZVal(v, type);
|
||||
|
||||
if ( ZVal::IsManagedType(type) )
|
||||
init->init_type = FieldInit::R_INIT_DIRECT_MANAGED;
|
||||
init = std::make_unique<detail::DirectManagedFieldInit>(zv);
|
||||
else
|
||||
init->init_type = FieldInit::R_INIT_DIRECT;
|
||||
|
||||
init->direct_init = ZVal(v, type);
|
||||
init = std::make_unique<detail::DirectFieldInit>(zv);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
init->init_type = FieldInit::R_INIT_DEF;
|
||||
init->def_expr = def_expr;
|
||||
init->def_type = def_expr->GetType();
|
||||
auto efi = std::make_unique<detail::ExprFieldInit>(def_expr, type);
|
||||
creation_inits.emplace_back(std::make_pair(field, std::move(efi)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1129,25 +1193,16 @@ void RecordType::AddField(unsigned int field, const TypeDecl* td)
|
|||
TypeTag tag = type->Tag();
|
||||
|
||||
if ( tag == TYPE_RECORD )
|
||||
{
|
||||
init->init_type = FieldInit::R_INIT_RECORD;
|
||||
init->r_type = cast_intrusive<RecordType>(type);
|
||||
}
|
||||
init = std::make_unique<detail::RecordFieldInit>(cast_intrusive<RecordType>(type));
|
||||
|
||||
else if ( tag == TYPE_TABLE )
|
||||
{
|
||||
init->init_type = FieldInit::R_INIT_TABLE;
|
||||
init->t_type = cast_intrusive<TableType>(type);
|
||||
}
|
||||
init = std::make_unique<detail::TableFieldInit>(cast_intrusive<TableType>(type), a);
|
||||
|
||||
else if ( tag == TYPE_VECTOR )
|
||||
{
|
||||
init->init_type = FieldInit::R_INIT_VECTOR;
|
||||
init->v_type = cast_intrusive<VectorType>(type);
|
||||
}
|
||||
init = std::make_unique<detail::VectorFieldInit>(cast_intrusive<VectorType>(type));
|
||||
}
|
||||
|
||||
field_inits.push_back(init);
|
||||
deferred_inits.push_back(std::move(init));
|
||||
}
|
||||
|
||||
bool RecordType::HasField(const char* field) const
|
||||
|
@ -1344,64 +1399,14 @@ void RecordType::AddFieldsDirectly(const type_decl_list& others, bool add_log_at
|
|||
|
||||
void RecordType::Create(std::vector<std::optional<ZVal>>& r) const
|
||||
{
|
||||
int n = NumFields();
|
||||
for ( auto& di : deferred_inits )
|
||||
if ( di )
|
||||
r.push_back(di->Generate());
|
||||
else
|
||||
r.push_back(std::nullopt);
|
||||
|
||||
for ( int i = 0; i < n; ++i )
|
||||
{
|
||||
auto* init = field_inits[i];
|
||||
|
||||
ZVal r_i;
|
||||
|
||||
switch ( init->init_type )
|
||||
{
|
||||
case FieldInit::R_INIT_NONE:
|
||||
r.push_back(std::nullopt);
|
||||
continue;
|
||||
|
||||
case FieldInit::R_INIT_DIRECT:
|
||||
r_i = init->direct_init;
|
||||
break;
|
||||
|
||||
case FieldInit::R_INIT_DIRECT_MANAGED:
|
||||
r_i = init->direct_init;
|
||||
zeek::Ref(r_i.ManagedVal());
|
||||
break;
|
||||
|
||||
case FieldInit::R_INIT_DEF:
|
||||
{
|
||||
auto v = init->def_expr->Eval(nullptr);
|
||||
if ( v )
|
||||
{
|
||||
const auto& t = init->def_type;
|
||||
|
||||
if ( init->def_coerce )
|
||||
{
|
||||
auto rt = cast_intrusive<RecordType>(t);
|
||||
v = v->AsRecordVal()->CoerceTo(rt);
|
||||
}
|
||||
|
||||
r_i = ZVal(v, t);
|
||||
}
|
||||
else
|
||||
reporter->Error("failed &default in record creation");
|
||||
}
|
||||
break;
|
||||
|
||||
case FieldInit::R_INIT_RECORD:
|
||||
r_i = ZVal(new RecordVal(init->r_type));
|
||||
break;
|
||||
|
||||
case FieldInit::R_INIT_TABLE:
|
||||
r_i = ZVal(new TableVal(init->t_type, init->attrs));
|
||||
break;
|
||||
|
||||
case FieldInit::R_INIT_VECTOR:
|
||||
r_i = ZVal(new VectorVal(init->v_type));
|
||||
break;
|
||||
}
|
||||
|
||||
r.push_back(r_i);
|
||||
}
|
||||
for ( auto& ci : creation_inits )
|
||||
r[ci.first] = ci.second->Generate();
|
||||
}
|
||||
|
||||
void RecordType::DescribeFields(ODesc* d) const
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue