diff --git a/src/Val.h b/src/Val.h index 3d833932f4..e8c8351438 100644 --- a/src/Val.h +++ b/src/Val.h @@ -1545,10 +1545,15 @@ protected: record_val.push_back({ZVal(), ZVal::IsManagedType(t), /*is_set=*/false}); } - // For internal use by low-level ZAM instructions and event tracing. - // Caller assumes responsibility for memory management. The first - // version allows manipulation of whether the field is present at all. - // The second version ensures that the optional value is present. + // Three record field accesses for internal use by low-level ZAM + // instructions and event tracing. + + // This version provides direct read-only access to the field's value. + ZVal RawField(int field) { return record_val[field].zval; } + + // This version allows manipulation of the entire record slot, and + // ensures that any default value is present if the field is presently + // not set. If assigning a new value, use Set(). detail::RecordValSlot& RawOptField(int field) { auto& slot = record_val[field]; if ( ! slot.IsSet() ) { @@ -1560,7 +1565,16 @@ protected: return slot; } - ZVal& RawField(int field) { return record_val[field].zval; } + // This version allows low-level assignment directly to the field's value. + // The caller is responsible for memory management of the current value + // (if appropriate) and *must* assign a value into the ZVal (or modify the + // existing value), as after this call the record slot is marked as being + // set even if currently it is not set. + ZVal& RawFieldRef(int field) { + auto& slot = RawOptField(field); + slot.is_set = true; + return slot.zval; + } ValPtr DoClone(CloneState* state) override; diff --git a/src/script_opt/CPP/RuntimeOps.h b/src/script_opt/CPP/RuntimeOps.h index 5f10d86d15..db664760b0 100644 --- a/src/script_opt/CPP/RuntimeOps.h +++ b/src/script_opt/CPP/RuntimeOps.h @@ -18,8 +18,6 @@ namespace detail { class CPPRuntime { public: - static auto& RawField(const RecordValPtr& rv, int field) { return rv->RawField(field); } - static auto& RawField(RecordVal* rv, int field) { return rv->RawField(field); } static auto& RawOptField(const RecordValPtr& rv, int field) { return rv->RawOptField(field); } static auto& RawOptField(RecordVal* rv, int field) { return rv->RawOptField(field); } @@ -133,7 +131,7 @@ inline ValPtr field_access__CPP(const RecordValPtr& rec, int field) { #define NATIVE_FIELD_ACCESS(type, zaccessor, vaccessor) \ inline type field_access_##type##__CPP(const RecordValPtr& r, int field) { \ - auto rv = CPPRuntime::RawOptField(r, field); \ + auto& rv = CPPRuntime::RawOptField(r, field); \ if ( rv.IsSet() ) \ return rv.GetZVal().zaccessor(); \ return field_access__CPP(r, field)->vaccessor(); \ @@ -147,7 +145,7 @@ NATIVE_FIELD_ACCESS(double, AsDouble, AsDouble) #define VP_FIELD_ACCESS(type, zaccessor) \ inline type##Ptr field_access_##type##__CPP(const RecordValPtr& r, int field) { \ - auto rv = CPPRuntime::RawOptField(r, field); \ + auto& rv = CPPRuntime::RawOptField(r, field); \ if ( rv.IsSet() ) \ return {NewRef{}, rv.GetZVal().zaccessor()}; \ return cast_intrusive(field_access__CPP(r, field)); \ diff --git a/src/script_opt/ZAM/OPs/constructors.op b/src/script_opt/ZAM/OPs/constructors.op index daf179a1e3..531158e201 100644 --- a/src/script_opt/ZAM/OPs/constructors.op +++ b/src/script_opt/ZAM/OPs/constructors.op @@ -161,17 +161,13 @@ eval SetUpRecFieldOps(map) macro DoManagedRecAssign(lhs, rhs) auto is_managed = Z_AUX->is_managed; for ( size_t i = 0U; i < n; ++i ) + { + auto& lhs_i = lhs->RawOptField(lhs_map[i]); + auto rhs_i = rhs->RawField(rhs_map[i]); if ( is_managed[i] ) - { - auto& lhs_i = lhs->RawOptField(lhs_map[i]); - auto rhs_i = rhs->RawField(rhs_map[i]); zeek::Ref(rhs_i.ManagedVal()); - if ( lhs_i.IsSet() ) - ZVal::DeleteManagedType(lhs_i.GetZVal()); - lhs_i.Set(rhs_i); - } - else - lhs->RawOptField(lhs_map[i]).Set(rhs->RawField(rhs_map[i])); + lhs_i.Set(rhs_i); + } op Rec-Assign-Fields-Managed op1-read @@ -190,8 +186,6 @@ eval SetUpRecFieldOps(map) auto& lhs_i = $1->RawOptField(lhs_map[i]); auto rhs_i = $2->RawField(rhs_map[i]); zeek::Ref(rhs_i.ManagedVal()); - if ( lhs_i.IsSet() ) - ZVal::DeleteManagedType(lhs_i.GetZVal()); lhs_i.Set(rhs_i); } @@ -201,7 +195,7 @@ class VV op-types R R eval SetUpRecFieldOps(map) for ( size_t i = 0U; i < n; ++i ) - $1->RawField(lhs_map[i]).AsIntRef() += $2->RawField(rhs_map[i]).AsInt(); + $1->RawFieldRef(lhs_map[i]).AsIntRef() += $2->RawField(rhs_map[i]).AsInt(); op Rec-Add-Double-Fields op1-read @@ -209,7 +203,7 @@ class VV op-types R R eval SetUpRecFieldOps(map) for ( size_t i = 0U; i < n; ++i ) - $1->RawField(lhs_map[i]).AsDoubleRef() += $2->RawField(rhs_map[i]).AsDouble(); + $1->RawFieldRef(lhs_map[i]).AsDoubleRef() += $2->RawField(rhs_map[i]).AsDouble(); op Rec-Add-Fields op1-read @@ -219,7 +213,7 @@ eval SetUpRecFieldOps(map) auto& types = Z_AUX->types; for ( size_t i = 0U; i < n; ++i ) { - auto& lhs_i = $1->RawField(lhs_map[i]); + auto& lhs_i = $1->RawFieldRef(lhs_map[i]); auto rhs_i = $2->RawField(rhs_map[i]); auto tag = types[i]->Tag(); if ( tag == TYPE_INT ) diff --git a/src/script_opt/ZAM/OPs/macros.op b/src/script_opt/ZAM/OPs/macros.op index 92d2eedba5..2b3f234d07 100644 --- a/src/script_opt/ZAM/OPs/macros.op +++ b/src/script_opt/ZAM/OPs/macros.op @@ -69,6 +69,7 @@ macro StepIter(slot) step_iters[slot] macro TableIter(slot) (*tiv_ptr)[slot] macro DirectField(r, f) r->RawField(f) +macro DirectFieldRef(r, f) r->RawFieldRef(f) macro DirectOptField(r, f) r->RawOptField(f) macro LogEnum(v) v.ToVal(ZAM::log_ID_enum_type)