Optimize record constructor expression.

We remove the inheritance from UnaryExpression because we know the
type of the operand precisely and can skip a temporary when evaluating
the expression.

#425
This commit is contained in:
Robin Sommer 2020-10-02 14:17:43 +00:00
parent d782c60f19
commit e9aa531b83
2 changed files with 37 additions and 8 deletions

View file

@ -3055,7 +3055,7 @@ void HasFieldExpr::ExprDescribe(ODesc* d) const
} }
RecordConstructorExpr::RecordConstructorExpr(ListExprPtr constructor_list) RecordConstructorExpr::RecordConstructorExpr(ListExprPtr constructor_list)
: UnaryExpr(EXPR_RECORD_CONSTRUCTOR, std::move(constructor_list)) : Expr(EXPR_RECORD_CONSTRUCTOR), op(std::move(constructor_list))
{ {
if ( IsError() ) if ( IsError() )
return; return;
@ -3108,22 +3108,30 @@ ValPtr RecordConstructorExpr::InitVal(const zeek::Type* t, ValPtr aggr) const
return nullptr; return nullptr;
} }
ValPtr RecordConstructorExpr::Fold(Val* v) const ValPtr RecordConstructorExpr::Eval(Frame* f) const
{ {
ListVal* lv = v->AsListVal(); if ( IsError() )
return nullptr;
const auto& exprs = op->Exprs();
auto rt = cast_intrusive<RecordType>(type); auto rt = cast_intrusive<RecordType>(type);
if ( lv->Length() != rt->NumFields() ) if ( exprs.length() != rt->NumFields() )
RuntimeErrorWithCallStack("inconsistency evaluating record constructor"); RuntimeErrorWithCallStack("inconsistency evaluating record constructor");
auto rv = make_intrusive<RecordVal>(std::move(rt)); auto rv = make_intrusive<RecordVal>(std::move(rt));
for ( int i = 0; i < lv->Length(); ++i ) for ( int i = 0; i < exprs.length(); ++i )
rv->Assign(i, lv->Idx(i)); rv->Assign(i, exprs[i]->Eval(f));
return rv; return rv;
} }
bool RecordConstructorExpr::IsPure() const
{
return op->IsPure();
}
void RecordConstructorExpr::ExprDescribe(ODesc* d) const void RecordConstructorExpr::ExprDescribe(ODesc* d) const
{ {
d->Add("["); d->Add("[");
@ -3131,6 +3139,18 @@ void RecordConstructorExpr::ExprDescribe(ODesc* d) const
d->Add("]"); d->Add("]");
} }
TraversalCode RecordConstructorExpr::Traverse(TraversalCallback* cb) const
{
TraversalCode tc = cb->PreExpr(this);
HANDLE_TC_EXPR_PRE(tc);
tc = op->Traverse(cb);
HANDLE_TC_EXPR_PRE(tc);
tc = cb->PostExpr(this);
HANDLE_TC_EXPR_POST(tc);
}
TableConstructorExpr::TableConstructorExpr(ListExprPtr constructor_list, TableConstructorExpr::TableConstructorExpr(ListExprPtr constructor_list,
std::unique_ptr<std::vector<AttrPtr>> arg_attrs, std::unique_ptr<std::vector<AttrPtr>> arg_attrs,
TypePtr arg_type) TypePtr arg_type)

View file

@ -630,16 +630,25 @@ protected:
int field; int field;
}; };
class RecordConstructorExpr final : public UnaryExpr { class RecordConstructorExpr final : public Expr {
public: public:
explicit RecordConstructorExpr(ListExprPtr constructor_list); explicit RecordConstructorExpr(ListExprPtr constructor_list);
~RecordConstructorExpr() override; ~RecordConstructorExpr() override;
ListExpr* Op() const { return op.get(); }
ValPtr Eval(Frame* f) const override;
bool IsPure() const override;
TraversalCode Traverse(TraversalCallback* cb) const override;
protected: protected:
ValPtr InitVal(const zeek::Type* t, ValPtr aggr) const override; ValPtr InitVal(const zeek::Type* t, ValPtr aggr) const override;
ValPtr Fold(Val* v) const override;
void ExprDescribe(ODesc* d) const override; void ExprDescribe(ODesc* d) const override;
ListExprPtr op;
}; };
class TableConstructorExpr final : public UnaryExpr { class TableConstructorExpr final : public UnaryExpr {