Change RecordVals to get resized at time of RecordType redef

Opposed to unconditionally checking all RecordVals whether they need to
be resized after parsing ends.
This commit is contained in:
Jon Siwek 2020-03-12 15:51:37 -07:00
parent da5fca7163
commit a61ad9ea5c
4 changed files with 21 additions and 13 deletions

View file

@ -874,6 +874,7 @@ const char* RecordType::AddFields(type_decl_list* others, attr_list* attr)
delete others; delete others;
num_fields = types->length(); num_fields = types->length();
RecordVal::ResizeParseTimeRecords(this);
return 0; return 0;
} }

View file

@ -2548,7 +2548,7 @@ HashKey* TableVal::ComputeHash(const Val* index) const
return table_hash->ComputeHash(index, 1); return table_hash->ComputeHash(index, 1);
} }
vector<RecordVal*> RecordVal::parse_time_records; RecordVal::RecordTypeValMap RecordVal::parse_time_records;
RecordVal::RecordVal(RecordType* t, bool init_fields) : Val(t) RecordVal::RecordVal(RecordType* t, bool init_fields) : Val(t)
{ {
@ -2557,10 +2557,7 @@ RecordVal::RecordVal(RecordType* t, bool init_fields) : Val(t)
val_list* vl = val.val_list_val = new val_list(n); val_list* vl = val.val_list_val = new val_list(n);
if ( is_parsing ) if ( is_parsing )
{ parse_time_records[t].emplace_back(NewRef{}, this);
parse_time_records.emplace_back(this);
Ref();
}
if ( ! init_fields ) if ( ! init_fields )
return; return;
@ -2630,12 +2627,18 @@ Val* RecordVal::LookupWithDefault(int field) const
return Type()->AsRecordType()->FieldDefault(field); return Type()->AsRecordType()->FieldDefault(field);
} }
void RecordVal::ResizeParseTimeRecords() void RecordVal::ResizeParseTimeRecords(RecordType* rt)
{ {
for ( auto& rv : parse_time_records ) auto it = parse_time_records.find(rt);
if ( it == parse_time_records.end() )
return;
auto& rvs = it->second;
for ( auto& rv : rvs )
{ {
auto vs = rv->val.val_list_val; auto vs = rv->val.val_list_val;
auto rt = rv->Type()->AsRecordType();
auto current_length = vs->length(); auto current_length = vs->length();
auto required_length = rt->NumFields(); auto required_length = rt->NumFields();
@ -2646,10 +2649,11 @@ void RecordVal::ResizeParseTimeRecords()
for ( auto i = current_length; i < required_length; ++i ) for ( auto i = current_length; i < required_length; ++i )
vs->replace(i, nullptr); vs->replace(i, nullptr);
} }
Unref(rv);
} }
}
void RecordVal::DoneParsing()
{
parse_time_records.clear(); parse_time_records.clear();
} }

View file

@ -924,14 +924,17 @@ public:
// Extend the underlying arrays of record instances created during // Extend the underlying arrays of record instances created during
// parsing to match the number of fields in the record type (they may // parsing to match the number of fields in the record type (they may
// mismatch as a result of parse-time record type redefinitions. // mismatch as a result of parse-time record type redefinitions.
static void ResizeParseTimeRecords(); static void ResizeParseTimeRecords(RecordType* rt);
static void DoneParsing();
protected: protected:
Val* DoClone(CloneState* state) override; Val* DoClone(CloneState* state) override;
BroObj* origin; BroObj* origin;
static vector<RecordVal*> parse_time_records; using RecordTypeValMap = std::unordered_map<RecordType*, std::vector<IntrusivePtr<RecordVal>>>;
static RecordTypeValMap parse_time_records;
}; };
class EnumVal : public Val { class EnumVal : public Val {

View file

@ -649,7 +649,7 @@ int main(int argc, char** argv)
yyparse(); yyparse();
is_parsing = false; is_parsing = false;
RecordVal::ResizeParseTimeRecords(); RecordVal::DoneParsing();
init_general_global_var(); init_general_global_var();
init_net_var(); init_net_var();