script optimization fixes for "concretizing" vector-of-any's

This commit is contained in:
Vern Paxson 2024-01-10 18:24:01 -08:00 committed by Arne Welzel
parent fc12ac2b06
commit bae87fb606
4 changed files with 78 additions and 29 deletions

View file

@ -902,6 +902,9 @@ public:
if ( coerce_type ) if ( coerce_type )
v = v->AsRecordVal()->CoerceTo(coerce_type); v = v->AsRecordVal()->CoerceTo(coerce_type);
else if ( init_type->Tag() == TYPE_VECTOR )
concretize_if_unspecified(cast_intrusive<VectorVal>(v), init_type->Yield());
return ZVal(v, init_type); return ZVal(v, init_type);
} }

View file

@ -1889,45 +1889,56 @@ ValPtr TableVal::Default(const ValPtr& index) {
return nullptr; return nullptr;
} }
ValPtr result;
if ( def_val->GetType()->Tag() != TYPE_FUNC || same_type(def_val->GetType(), GetType()->Yield()) ) { if ( def_val->GetType()->Tag() != TYPE_FUNC || same_type(def_val->GetType(), GetType()->Yield()) ) {
if ( def_attr->GetExpr()->IsConst() ) if ( def_attr->GetExpr()->IsConst() )
return def_val; return def_val;
try { try {
return def_val->Clone(); result = def_val->Clone();
} catch ( InterpreterException& e ) { /* Already reported. */ } catch ( InterpreterException& e ) { /* Already reported. */
} }
Error("&default value for table is not clone-able"); if ( ! result ) {
return nullptr; Error("&default value for table is not clone-able");
return nullptr;
}
}
else {
const Func* f = def_val->AsFunc();
Args vl;
if ( index->GetType()->Tag() == TYPE_LIST ) {
auto lv = index->AsListVal();
vl.reserve(lv->Length());
for ( const auto& v : lv->Vals() )
vl.emplace_back(v);
}
else
vl.emplace_back(index);
try {
result = f->Invoke(&vl);
}
catch ( InterpreterException& e ) { /* Already reported. */
}
if ( ! result ) {
Error("no value returned from &default function");
return nullptr;
}
} }
const Func* f = def_val->AsFunc(); auto rt = result->GetType();
Args vl; if ( rt->Tag() == TYPE_VECTOR )
// The double-Yield() here is because this is a "table of vector of X"
if ( index->GetType()->Tag() == TYPE_LIST ) { // and we want X. If this is instead a "table of any", that'll be
auto lv = index->AsListVal(); // okay because concretize_if_unspecified() correctly deals with
vl.reserve(lv->Length()); // nil target types.
detail::concretize_if_unspecified(cast_intrusive<VectorVal>(result), GetType()->Yield()->Yield());
for ( const auto& v : lv->Vals() )
vl.emplace_back(v);
}
else
vl.emplace_back(index);
ValPtr result;
try {
result = f->Invoke(&vl);
}
catch ( InterpreterException& e ) { /* Already reported. */
}
if ( ! result ) {
Error("no value returned from &default function");
return nullptr;
}
return result; return result;
} }
@ -3474,6 +3485,26 @@ bool VectorVal::Concretize(const TypePtr& t) {
return true; return true;
} }
void detail::concretize_if_unspecified(VectorValPtr v, TypePtr t) {
if ( v->Size() != 0 )
// Concretization only applies to empty vectors.
return;
if ( v->GetType()->Yield()->Tag() != TYPE_ANY )
// It's not an unspecified vector.
return;
if ( ! t )
// "t" can be nil if the vector is being assigned to an "any" value.
return;
if ( t->Tag() == TYPE_ANY )
// No need to concretize.
return;
v->Concretize(t);
}
unsigned int VectorVal::ComputeFootprint(std::unordered_set<const Val*>* analyzed_vals) const { unsigned int VectorVal::ComputeFootprint(std::unordered_set<const Val*>* analyzed_vals) const {
auto n = vector_val.size(); auto n = vector_val.size();
unsigned int fp = n; unsigned int fp = n;

View file

@ -1744,6 +1744,13 @@ namespace detail {
// for normalization. If Func::nil is passed, no normalization happens. // for normalization. If Func::nil is passed, no normalization happens.
extern std::variant<ValPtr, std::string> ValFromJSON(std::string_view json_str, const TypePtr& t, extern std::variant<ValPtr, std::string> ValFromJSON(std::string_view json_str, const TypePtr& t,
const FuncPtr& key_func); const FuncPtr& key_func);
// If the given vector is an empty vector-of-any ("unspecified"),
// concretizes it to the given type. *v* gives the vector and *t* the
// type to concretize it to if appropriate. *t* can be nil, in which
// case nothing is done.
extern void concretize_if_unspecified(VectorValPtr v, TypePtr t);
} // namespace detail } // namespace detail
} // namespace zeek } // namespace zeek

View file

@ -124,6 +124,14 @@ StmtPtr Reducer::GenParam(const IDPtr& id, ExprPtr rhs, bool is_modified) {
// the inline block's execution. // the inline block's execution.
is_modified = true; is_modified = true;
auto& id_t = id->GetType();
if ( id_t->Tag() == TYPE_VECTOR && rhs->GetType()->Yield() != id_t->Yield() )
// Presumably either the identifier or the RHS is a vector-of-any.
// This means there will essentially be a modification of the RHS
// due to the need to use (or omit) operations coercing from such
// vectors.
is_modified = true;
if ( ! is_modified ) { if ( ! is_modified ) {
// Can use a temporary variable, which then supports // Can use a temporary variable, which then supports
// optimization via alias propagation. // optimization via alias propagation.