From 2cb26eda5118718f378c713da0efb8750836f97b Mon Sep 17 00:00:00 2001 From: Arne Welzel Date: Thu, 24 Jul 2025 17:06:09 +0200 Subject: [PATCH] RecordType: Allow field init deferral of deferrable record constructors The ctx: conn_id_ctx &default=conn_id_ctx() field was not optimized as deferrable even though by default its an empty record and so deferring initialization seems safe. Open-code the special record constructor expression case in ExprFieldInit so that the ctx field is not default initialized at record construction anymore. I am wondering a bit if the same applies to &default=set() and &default=table(). --- src/Type.cc | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/Type.cc b/src/Type.cc index 5628470e74..10104dbc74 100644 --- a/src/Type.cc +++ b/src/Type.cc @@ -915,7 +915,22 @@ public: return {v, init_type}; } - bool IsDeferrable() const override { return false; } + bool IsDeferrable() const override { + if ( init_expr->Tag() == EXPR_RECORD_CONSTRUCTOR ) { + // Special-case deferrable record construction. + auto rce = zeek::cast_intrusive(init_expr); + auto rt = rce->GetType(); + + // The empty constructor_list check here is a short-cut: If the + // constructor expression contained only further const expressions + // or only further deferrable record constructors, this could be + // more aggressively deferring initializations. + auto constructor_list = rce->Op(); + return rt->IsDeferrable() && constructor_list->Exprs().empty(); + } + + return false; + } ExprPtr InitExpr() const override { return init_expr; } @@ -995,6 +1010,8 @@ private: if ( ! ci.second->IsDeferrable() ) rt->creation_inits[i++] = std::move(ci); else { + // std::fprintf(stderr, "deferred %s$%s: %s\n", obj_desc_short(rt).c_str(), rt->FieldName(ci.first), + // ci.second->InitExpr() ? obj_desc_short(ci.second->InitExpr()).c_str() : ""); assert(! rt->deferred_inits[ci.first]); rt->deferred_inits[ci.first].swap(ci.second); }