RecordVal: Avoid usage of RecordType::IsManaged()

This is going through some std::vector<bool> bitset that shows up in
profiles, so avoid it...
This commit is contained in:
Arne Welzel 2025-07-26 16:09:37 +02:00
parent e61f060f8d
commit 0fb4f3ae48
2 changed files with 17 additions and 48 deletions

View file

@ -2985,7 +2985,7 @@ RecordVal::RecordVal(RecordTypePtr t, bool init_fields) : Val(t) {
// Initialize the managed flag of each slot so that we don't need // Initialize the managed flag of each slot so that we don't need
// to go back to record type for figuring out if it's managed. // to go back to record type for figuring out if it's managed.
for ( size_t i = 0; i < record_val.size(); i++ ) for ( size_t i = 0; i < record_val.size(); i++ )
record_val[i].SetManaged(IsManaged(i)); record_val[i].SetManaged(ZVal::IsManagedType(rt.GetFieldType(i)));
} }
else else
@ -2995,13 +2995,15 @@ RecordVal::RecordVal(RecordTypePtr t, bool init_fields) : Val(t) {
} }
RecordVal::RecordVal(RecordTypePtr t, std::vector<std::optional<ZVal>> init_vals) : Val(t) { RecordVal::RecordVal(RecordTypePtr t, std::vector<std::optional<ZVal>> init_vals) : Val(t) {
record_val.resize(GetRecordType().NumFields()); const auto& rt = GetRecordType();
record_val.resize(rt.NumFields());
assert(record_val.size() == init_vals.size());
for ( size_t i = 0; i < record_val.size(); ++i ) { for ( size_t i = 0; i < record_val.size(); ++i ) {
if ( init_vals[i] ) if ( init_vals[i] )
record_val[i].Set(*init_vals[i]); record_val[i].Set(*init_vals[i]);
record_val[i].SetManaged(IsManaged(i)); record_val[i].SetManaged(ZVal::IsManagedType(rt.GetFieldType(i)));
} }
} }

View file

@ -1118,24 +1118,6 @@ inline constexpr bool is_zeek_val_v = is_zeek_val<T>::value;
namespace detail { namespace detail {
enum class RecordValSlotFlags : uint8_t {
None = 0,
Managed = 1, // replicates
Set = 2,
Deleted = 4,
};
constexpr RecordValSlotFlags operator|(RecordValSlotFlags l, RecordValSlotFlags r) {
return static_cast<RecordValSlotFlags>(static_cast<uint8_t>(l) | static_cast<uint8_t>(r));
}
constexpr RecordValSlotFlags operator&(RecordValSlotFlags l, RecordValSlotFlags r) {
return static_cast<RecordValSlotFlags>(static_cast<uint8_t>(l) & static_cast<uint8_t>(r));
}
constexpr RecordValSlotFlags operator~(RecordValSlotFlags x) {
return static_cast<RecordValSlotFlags>(~static_cast<uint8_t>(x));
}
/** /**
* Representation of a single slot for a field in a RecordVal. * Representation of a single slot for a field in a RecordVal.
* *
@ -1146,22 +1128,15 @@ constexpr RecordValSlotFlags operator~(RecordValSlotFlags x) {
class RecordValSlot { class RecordValSlot {
public: public:
RecordValSlot() {} RecordValSlot() {}
RecordValSlot(ZVal zval, RecordValSlotFlags flags) : zval(zval), flags(flags) {} RecordValSlot(ZVal zval, bool is_managed) : zval(zval), is_managed(is_managed), is_set(true) {}
bool IsManaged() const noexcept { return (flags & RecordValSlotFlags::Managed) == RecordValSlotFlags::Managed; } bool IsManaged() const noexcept { return is_managed; }
bool IsDeleted() const noexcept { return (flags & RecordValSlotFlags::Deleted) == RecordValSlotFlags::Deleted; } bool IsSet() const noexcept { return is_set; }
bool IsSet() const noexcept { return (flags & RecordValSlotFlags::Set) == RecordValSlotFlags::Set; }
void SetManaged(bool is_managed) noexcept { void SetManaged(bool new_is_managed) noexcept { is_managed = new_is_managed; }
if ( is_managed )
flags = flags | detail::RecordValSlotFlags::Managed;
else
flags = flags & (~detail::RecordValSlotFlags::Managed);
}
void Set(ZVal new_zval) noexcept { void Set(ZVal new_zval) noexcept {
flags = flags | RecordValSlotFlags::Set; is_set = true;
flags = flags & (~RecordValSlotFlags::Deleted);
zval = new_zval; zval = new_zval;
} }
@ -1169,8 +1144,7 @@ public:
if ( IsSet() && IsManaged() ) if ( IsSet() && IsManaged() )
ZVal::DeleteManagedType(zval); ZVal::DeleteManagedType(zval);
flags = flags | RecordValSlotFlags::Deleted; is_set = false;
flags = flags & (~RecordValSlotFlags::Set);
} }
ValPtr ToVal(const TypePtr& t) const { ValPtr ToVal(const TypePtr& t) const {
@ -1185,7 +1159,8 @@ private:
friend class zeek::detail::CPPRuntime; friend class zeek::detail::CPPRuntime;
friend class zeek::RecordVal; friend class zeek::RecordVal;
ZVal zval; ZVal zval;
RecordValSlotFlags flags = RecordValSlotFlags::None; bool is_managed = false;
bool is_set = false;
}; };
/** /**
@ -1436,10 +1411,7 @@ public:
// Returns true if the slot for the given field is initialized. // Returns true if the slot for the given field is initialized.
// This helper can be used to guard GetFieldAs() accesses. // This helper can be used to guard GetFieldAs() accesses.
bool HasRawField(int field) const { bool HasRawField(int field) const noexcept { return record_val[field].IsSet(); }
assert((record_val[field].IsSet() && ! record_val[field].IsDeleted()) || ! record_val[field].IsSet());
return record_val[field].IsSet();
}
// The following return the given field converted to a particular // The following return the given field converted to a particular
// underlying value. We provide these to enable efficient // underlying value. We provide these to enable efficient
@ -1567,13 +1539,10 @@ protected:
* @param t The type associated with the field. * @param t The type associated with the field.
*/ */
void AppendField(ValPtr v, const TypePtr& t) { void AppendField(ValPtr v, const TypePtr& t) {
detail::RecordValSlotFlags managed_flag =
IsManaged(record_val.size()) ? detail::RecordValSlotFlags::Managed : detail::RecordValSlotFlags::None;
if ( v ) if ( v )
record_val.push_back({ZVal(v, t), managed_flag | detail::RecordValSlotFlags::Set}); record_val.push_back({ZVal(v, t), /*is_managed=*/ZVal::IsManagedType(t)});
else else
record_val.push_back({ZVal(), managed_flag}); record_val.push_back({ZVal(), /*is_managed=*/ZVal::IsManagedType(t)});
} }
// For internal use by low-level ZAM instructions and event tracing. // For internal use by low-level ZAM instructions and event tracing.
@ -1582,7 +1551,7 @@ protected:
// The second version ensures that the optional value is present. // The second version ensures that the optional value is present.
detail::RecordValSlot& RawOptField(int field) { detail::RecordValSlot& RawOptField(int field) {
auto& slot = record_val[field]; auto& slot = record_val[field];
if ( ! slot.IsSet() && ! slot.IsDeleted() ) { if ( ! slot.IsSet() ) {
const auto& fi = GetRecordType().DeferredInits()[field]; const auto& fi = GetRecordType().DeferredInits()[field];
if ( fi ) if ( fi )
slot.Set(fi->Generate()); slot.Set(fi->Generate());
@ -1609,8 +1578,6 @@ private:
return *static_cast<RecordType*>(GetType().get()); // AsRecordType() isn't inlined return *static_cast<RecordType*>(GetType().get()); // AsRecordType() isn't inlined
} }
bool IsManaged(unsigned int offset) const { return GetRecordType().ManagedFields()[offset]; }
// Just for template inferencing. // Just for template inferencing.
RecordVal* Get() { return this; } RecordVal* Get() { return this; }