From 30b29ef7bac930bcdaba07b72e1d29d8daa899b5 Mon Sep 17 00:00:00 2001 From: Vern Paxson Date: Thu, 19 Nov 2020 16:05:42 -0800 Subject: [PATCH 01/17] inlining of Zeek script functions --- auxil/btest | 2 +- doc | 2 +- src/CMakeLists.txt | 6 + src/Expr.cc | 83 +- src/Expr.h | 217 +- src/Frame.cc | 14 +- src/Frame.h | 15 + src/Func.cc | 8 +- src/Func.h | 48 +- src/Options.cc | 46 +- src/Options.h | 6 +- src/Scope.cc | 1 + src/Scope.h | 17 +- src/ScriptCoverageManager.cc | 2 +- src/Stmt.cc | 100 +- src/Stmt.h | 186 +- src/StmtBase.h | 105 + src/TraverseTypes.h | 8 +- src/Var.cc | 20 +- src/main.cc | 3 + src/reporter.bif | 10 +- src/script_opt/Expr.cc | 547 + src/script_opt/ExprOpt-Enums.h | 5 + src/script_opt/ExprOpt-Names.h | 6 + src/script_opt/ExprOpt-Private.h | 13 + src/script_opt/ExprOpt-Public.h | 44 + src/script_opt/ExprOpt-Subclasses.h | 29 + src/script_opt/Inline.cc | 238 + src/script_opt/Inline.h | 62 + src/script_opt/ProfileFunc.cc | 218 + src/script_opt/ProfileFunc.h | 123 + src/script_opt/ScriptOpt.cc | 65 + src/script_opt/ScriptOpt.h | 79 + src/script_opt/Stmt.cc | 212 + src/script_opt/StmtOpt-Private.h | 13 + src/script_opt/StmtOpt-Public.h | 37 + src/zeek-setup.cc | 114 +- src/zeek-setup.h | 1 + src/zeek.bif | 2 +- .../broker.store.invalid-handle/out | 4 + .../coverage.zeek-profiler-file/step1.out | 2 + .../coverage.zeek-profiler-file/step2.out | 2 + .../coverage.zeek-profiler-file/step3.out | 3 + .../language.deprecated/no-warnings.out | 41 + .../language.deprecated/warnings.out | 41 + .../btest/Baseline.dup/plugins.hooks/output | 3553 ++++++ .../scripts.base.frameworks.input.reread/out | 1509 +++ .../btest/Baseline.inline/bifs.backtrace/out | 7 + .../broker.store.invalid-handle/out | 4 + .../language.index-assignment-invalid/out | 5 + .../Baseline.inline/plugins.func-hook/output | 1 + .../Baseline.inline/plugins.hooks/output | 2497 +++++ .../plugins.legacy-func-hook/output | 1 + .../.stdout | 9 + .../out | 160 + .../out | 15 + .../out | 320 + .../all-events-no-args.log | 236 + .../all-events.log | 1075 ++ .../really-all-events.log | 9512 +++++++++++++++++ .../smtp-events.log | 320 + .../btest/Baseline/opt.pure-inlining/output | 10 + testing/btest/btest.cfg | 34 + testing/btest/opt/pure-inlining.zeek | 67 + .../bifs/file_exists_lookup_file.zeek | 3 + 65 files changed, 21885 insertions(+), 253 deletions(-) create mode 100644 src/StmtBase.h create mode 100644 src/script_opt/Expr.cc create mode 100644 src/script_opt/ExprOpt-Enums.h create mode 100644 src/script_opt/ExprOpt-Names.h create mode 100644 src/script_opt/ExprOpt-Private.h create mode 100644 src/script_opt/ExprOpt-Public.h create mode 100644 src/script_opt/ExprOpt-Subclasses.h create mode 100644 src/script_opt/Inline.cc create mode 100644 src/script_opt/Inline.h create mode 100644 src/script_opt/ProfileFunc.cc create mode 100644 src/script_opt/ProfileFunc.h create mode 100644 src/script_opt/ScriptOpt.cc create mode 100644 src/script_opt/ScriptOpt.h create mode 100644 src/script_opt/Stmt.cc create mode 100644 src/script_opt/StmtOpt-Private.h create mode 100644 src/script_opt/StmtOpt-Public.h create mode 100644 testing/btest/Baseline.dup/broker.store.invalid-handle/out create mode 100644 testing/btest/Baseline.dup/coverage.zeek-profiler-file/step1.out create mode 100644 testing/btest/Baseline.dup/coverage.zeek-profiler-file/step2.out create mode 100644 testing/btest/Baseline.dup/coverage.zeek-profiler-file/step3.out create mode 100644 testing/btest/Baseline.dup/language.deprecated/no-warnings.out create mode 100644 testing/btest/Baseline.dup/language.deprecated/warnings.out create mode 100644 testing/btest/Baseline.dup/plugins.hooks/output create mode 100644 testing/btest/Baseline.dup/scripts.base.frameworks.input.reread/out create mode 100644 testing/btest/Baseline.inline/bifs.backtrace/out create mode 100644 testing/btest/Baseline.inline/broker.store.invalid-handle/out create mode 100644 testing/btest/Baseline.inline/language.index-assignment-invalid/out create mode 100644 testing/btest/Baseline.inline/plugins.func-hook/output create mode 100644 testing/btest/Baseline.inline/plugins.hooks/output create mode 100644 testing/btest/Baseline.inline/plugins.legacy-func-hook/output create mode 100644 testing/btest/Baseline.inline/scripts.base.frameworks.file-analysis.bifs.file_exists_lookup_file/.stdout create mode 100644 testing/btest/Baseline.inline/scripts.base.frameworks.input.raw.basic/out create mode 100644 testing/btest/Baseline.inline/scripts.base.frameworks.input.raw.execute/out create mode 100644 testing/btest/Baseline.inline/scripts.base.frameworks.input.raw.rereadraw/out create mode 100644 testing/btest/Baseline.inline/scripts.policy.misc.dump-events/all-events-no-args.log create mode 100644 testing/btest/Baseline.inline/scripts.policy.misc.dump-events/all-events.log create mode 100644 testing/btest/Baseline.inline/scripts.policy.misc.dump-events/really-all-events.log create mode 100644 testing/btest/Baseline.inline/scripts.policy.misc.dump-events/smtp-events.log create mode 100644 testing/btest/Baseline/opt.pure-inlining/output create mode 100644 testing/btest/opt/pure-inlining.zeek diff --git a/auxil/btest b/auxil/btest index a0f317ec29..8ce78fe388 160000 --- a/auxil/btest +++ b/auxil/btest @@ -1 +1 @@ -Subproject commit a0f317ec29461f7035d27b9f4f0cab389cc345a4 +Subproject commit 8ce78fe388fbb583b47e1a9ea956c94cb9b5be6d diff --git a/doc b/doc index 2e5ef4b5a6..7658414ac4 160000 --- a/doc +++ b/doc @@ -1 +1 @@ -Subproject commit 2e5ef4b5a6752d53a4145b5b5b9da6f0bd4735a8 +Subproject commit 7658414ac454522ecd5710c13ca6e0bc4a842e12 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3d185041f2..e3b4b9c2f3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -322,6 +322,12 @@ set(MAIN_SRCS plugin/Manager.cc plugin/Plugin.cc + script_opt/Expr.cc + script_opt/Inline.cc + script_opt/ProfileFunc.cc + script_opt/ScriptOpt.cc + script_opt/Stmt.cc + nb_dns.c digest.h ) diff --git a/src/Expr.cc b/src/Expr.cc index ba8370065b..2beaedfad2 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -39,7 +39,12 @@ const char* expr_name(BroExprTag t) "$=", "in", "<<>>", "()", "function()", "event", "schedule", "coerce", "record_coerce", "table_coerce", "vector_coerce", - "sizeof", "cast", "is", "[:]=" + "sizeof", "cast", "is", "[:]=", + +#include "zeek/script_opt/ExprOpt-Names.h" + + "nop", + }; if ( int(t) >= NUM_EXPRS ) @@ -74,6 +79,12 @@ ListExpr* Expr::AsListExpr() return (ListExpr*) this; } +ListExprPtr Expr::AsListExprPtr() + { + CHECK_TAG(tag, EXPR_LIST, "ExprVal::AsListExpr", expr_name) + return {NewRef{}, (ListExpr*) this}; + } + const NameExpr* Expr::AsNameExpr() const { CHECK_TAG(tag, EXPR_NAME, "ExprVal::AsNameExpr", expr_name) @@ -86,6 +97,18 @@ NameExpr* Expr::AsNameExpr() return (NameExpr*) this; } +const ConstExpr* Expr::AsConstExpr() const + { + CHECK_TAG(tag, EXPR_CONST, "ExprVal::AsConstExpr", expr_name) + return (const ConstExpr*) this; + } + +const CallExpr* Expr::AsCallExpr() const + { + CHECK_TAG(tag, EXPR_CALL, "ExprVal::AsCallExpr", expr_name) + return (const CallExpr*) this; + } + const AssignExpr* Expr::AsAssignExpr() const { CHECK_TAG(tag, EXPR_ASSIGN, "ExprVal::AsAssignExpr", expr_name) @@ -110,6 +133,18 @@ IndexExpr* Expr::AsIndexExpr() return (IndexExpr*) this; } +const EventExpr* Expr::AsEventExpr() const + { + CHECK_TAG(tag, EXPR_EVENT, "ExprVal::AsEventExpr", expr_name) + return (const EventExpr*) this; + } + +EventExprPtr Expr::AsEventExprPtr() + { + CHECK_TAG(tag, EXPR_EVENT, "ExprVal::AsEventExpr", expr_name) + return {NewRef{}, (EventExpr*) this}; + } + bool Expr::CanAdd() const { return false; @@ -244,7 +279,7 @@ void Expr::ExprError(const char msg[]) void Expr::RuntimeError(const std::string& msg) const { - reporter->ExprRuntimeError(this, "%s", msg.data()); + reporter->ExprRuntimeError(Original(), "%s", msg.data()); } void Expr::RuntimeErrorWithCallStack(const std::string& msg) const @@ -252,14 +287,15 @@ void Expr::RuntimeErrorWithCallStack(const std::string& msg) const auto rcs = render_call_stack(); if ( rcs.empty() ) - reporter->ExprRuntimeError(this, "%s", msg.data()); + reporter->ExprRuntimeError(Original(), "%s", msg.data()); else { ODesc d; d.SetShort(); Describe(&d); - reporter->RuntimeError(GetLocationInfo(), "%s, expression: %s, call stack: %s", - msg.data(), d.Description(), rcs.data()); + reporter->RuntimeError(Original()->GetLocationInfo(), + "%s, expression: %s, call stack: %s", + msg.data(), d.Description(), rcs.data()); } } @@ -928,12 +964,23 @@ void BinaryExpr::PromoteType(TypeTag t, bool is_vector) { PromoteOps(t); - if ( is_vector) + if ( is_vector ) SetType(make_intrusive(base_type(t))); else SetType(base_type(t)); } +void BinaryExpr::PromoteForInterval(ExprPtr& op) + { + if ( is_vector(op1) || is_vector(op2) ) + SetType(make_intrusive(base_type(TYPE_INTERVAL))); + else + SetType(base_type(TYPE_INTERVAL)); + + if ( op->GetType()->Tag() != TYPE_DOUBLE ) + op = make_intrusive(op, TYPE_DOUBLE); + } + CloneExpr::CloneExpr(ExprPtr arg_op) : UnaryExpr(EXPR_CLONE, std::move(arg_op)) { @@ -1414,12 +1461,7 @@ TimesExpr::TimesExpr(ExprPtr arg_op1, ExprPtr arg_op2) if ( bt1 == TYPE_INTERVAL || bt2 == TYPE_INTERVAL ) { if ( IsArithmetic(bt1) || IsArithmetic(bt2) ) - { - if ( is_vector(op1) && is_vector(op2) ) - SetType(make_intrusive(base_type(TYPE_INTERVAL))); - else - PromoteType(TYPE_INTERVAL, is_vector(op1) || is_vector(op2) ); - } + PromoteForInterval(IsArithmetic(bt1) ? op1 : op2); else ExprError("multiplication with interval requires arithmetic operand"); } @@ -1455,12 +1497,7 @@ DivideExpr::DivideExpr(ExprPtr arg_op1, ExprPtr arg_op2) if ( bt1 == TYPE_INTERVAL || bt2 == TYPE_INTERVAL ) { if ( IsArithmetic(bt1) || IsArithmetic(bt2) ) - { - if ( is_vector(op1) && is_vector(op2) ) - SetType(make_intrusive(base_type(TYPE_INTERVAL))); - else - PromoteType(TYPE_INTERVAL, is_vector(op1) || is_vector(op2)); - } + PromoteForInterval(IsArithmetic(bt1) ? op1 : op2); else if ( bt1 == TYPE_INTERVAL && bt2 == TYPE_INTERVAL ) { if ( is_vector(op1) || is_vector(op2) ) @@ -3151,7 +3188,8 @@ TraversalCode RecordConstructorExpr::Traverse(TraversalCallback* cb) const TableConstructorExpr::TableConstructorExpr(ListExprPtr constructor_list, std::unique_ptr> arg_attrs, - TypePtr arg_type) + TypePtr arg_type, + AttributesPtr arg_attrs2) : UnaryExpr(EXPR_TABLE_CONSTRUCTOR, std::move(constructor_list)) { if ( IsError() ) @@ -3187,6 +3225,8 @@ TableConstructorExpr::TableConstructorExpr(ListExprPtr constructor_list, if ( arg_attrs ) attrs = make_intrusive(std::move(*arg_attrs), type, false, false); + else + attrs = arg_attrs2; const auto& indices = type->AsTableType()->GetIndices()->GetTypes(); const ExprPList& cle = op->AsListExpr()->Exprs(); @@ -3286,7 +3326,8 @@ void TableConstructorExpr::ExprDescribe(ODesc* d) const SetConstructorExpr::SetConstructorExpr(ListExprPtr constructor_list, std::unique_ptr> arg_attrs, - TypePtr arg_type) + TypePtr arg_type, + AttributesPtr arg_attrs2) : UnaryExpr(EXPR_SET_CONSTRUCTOR, std::move(constructor_list)) { if ( IsError() ) @@ -3319,6 +3360,8 @@ SetConstructorExpr::SetConstructorExpr(ListExprPtr constructor_list, if ( arg_attrs ) attrs = make_intrusive(std::move(*arg_attrs), type, false, false); + else + attrs = arg_attrs2; const auto& indices = type->AsTableType()->GetIndices()->GetTypes(); ExprPList& cle = op->AsListExpr()->Exprs(); diff --git a/src/Expr.h b/src/Expr.h index 1c55055f82..5942c1f3fa 100644 --- a/src/Expr.h +++ b/src/Expr.h @@ -8,14 +8,15 @@ #include #include -#include "ZeekList.h" -#include "IntrusivePtr.h" -#include "Timer.h" -#include "Type.h" -#include "EventHandler.h" -#include "TraverseTypes.h" -#include "Val.h" -#include "ZeekArgs.h" +#include "zeek/ZeekList.h" +#include "zeek/IntrusivePtr.h" +#include "zeek/StmtBase.h" +#include "zeek/Timer.h" +#include "zeek/Type.h" +#include "zeek/EventHandler.h" +#include "zeek/TraverseTypes.h" +#include "zeek/Val.h" +#include "zeek/ZeekArgs.h" ZEEK_FORWARD_DECLARE_NAMESPACED(Frame, zeek::detail); ZEEK_FORWARD_DECLARE_NAMESPACED(Scope, zeek::detail); @@ -66,13 +67,19 @@ enum BroExprTag : int { EXPR_CAST, EXPR_IS, EXPR_INDEX_SLICE_ASSIGN, -#define NUM_EXPRS (int(EXPR_INDEX_SLICE_ASSIGN) + 1) + +#include "zeek/script_opt/ExprOpt-Enums.h" + + EXPR_NOP, + +#define NUM_EXPRS (int(EXPR_NOP) + 1) }; extern const char* expr_name(BroExprTag t); class ListExpr; class NameExpr; +class ConstExpr; class IndexExpr; class AssignExpr; class CallExpr; @@ -82,7 +89,7 @@ class Stmt; class Expr; using ExprPtr = IntrusivePtr; using EventExprPtr = IntrusivePtr; -using ListExprPtr = IntrusivePtr; +using StmtPtr = IntrusivePtr; class Expr : public Obj { public: @@ -99,6 +106,7 @@ public: BroExprTag Tag() const { return tag; } Expr* Ref() { zeek::Ref(this); return this; } + ExprPtr ThisPtr() { return {NewRef{}, this}; } // Evaluates the expression and returns a corresponding Val*, // or nil if the expression's value isn't fixed. @@ -171,22 +179,26 @@ public: void MarkParen() { paren = true; } bool IsParen() const { return paren; } - const ListExpr* AsListExpr() const; - ListExpr* AsListExpr(); +#undef ACCESSORS +#define ACCESSORS(ctype) \ + const ctype* As ## ctype () const; \ + ctype* As ## ctype (); \ + IntrusivePtr As ## ctype ## Ptr (); - const NameExpr* AsNameExpr() const; - NameExpr* AsNameExpr(); - - const AssignExpr* AsAssignExpr() const; - AssignExpr* AsAssignExpr(); - - const IndexExpr* AsIndexExpr() const; - IndexExpr* AsIndexExpr(); + ACCESSORS(ListExpr) + ACCESSORS(NameExpr) + ACCESSORS(ConstExpr) + ACCESSORS(CallExpr) + ACCESSORS(AssignExpr) + ACCESSORS(IndexExpr) + ACCESSORS(EventExpr) void Describe(ODesc* d) const override final; virtual TraversalCode Traverse(TraversalCallback* cb) const = 0; +#include "zeek/script_opt/ExprOpt-Public.h" + protected: Expr() = default; explicit Expr(BroExprTag arg_tag); @@ -211,6 +223,8 @@ protected: BroExprTag tag; TypePtr type; bool paren; + +#include "zeek/script_opt/ExprOpt-Private.h" }; class NameExpr final : public Expr { @@ -226,6 +240,9 @@ public: TraversalCode Traverse(TraversalCallback* cb) const override; + // Optimization-related: + ExprPtr Duplicate() override; + protected: void ExprDescribe(ODesc* d) const override; @@ -238,11 +255,15 @@ public: explicit ConstExpr(ValPtr val); Val* Value() const { return val.get(); } + ValPtr ValuePtr() const { return val; } ValPtr Eval(Frame* f) const override; TraversalCode Traverse(TraversalCallback* cb) const override; + // Optimization-related: + ExprPtr Duplicate() override; + protected: void ExprDescribe(ODesc* d) const override; ValPtr val; @@ -261,6 +282,9 @@ public: TraversalCode Traverse(TraversalCallback* cb) const override; + // Optimization-related: + ExprPtr Inline(Inliner* inl) override; + protected: UnaryExpr(BroExprTag arg_tag, ExprPtr arg_op); @@ -286,6 +310,9 @@ public: TraversalCode Traverse(TraversalCallback* cb) const override; + // Optimization-related: + ExprPtr Inline(Inliner* inl) override; + protected: BinaryExpr(BroExprTag arg_tag, ExprPtr arg_op1, ExprPtr arg_op2) @@ -325,6 +352,11 @@ protected: // operands and also set expression's type). void PromoteType(TypeTag t, bool is_vector); + // Promote one of the operands to be "double" (if not already), + // to make it suitable for combining with the other "interval" + // operand, yielding an "interval" type. + void PromoteForInterval(ExprPtr& op); + void ExprDescribe(ODesc* d) const override; ExprPtr op1; @@ -336,6 +368,9 @@ public: explicit CloneExpr(ExprPtr op); ValPtr Eval(Frame* f) const override; + // Optimization-related: + ExprPtr Duplicate() override; + protected: ValPtr Fold(Val* v) const override; }; @@ -347,12 +382,18 @@ public: ValPtr Eval(Frame* f) const override; ValPtr DoSingleEval(Frame* f, Val* v) const; bool IsPure() const override; + + // Optimization-related: + ExprPtr Duplicate() override; }; class ComplementExpr final : public UnaryExpr { public: explicit ComplementExpr(ExprPtr op); + // Optimization-related: + ExprPtr Duplicate() override; + protected: ValPtr Fold(Val* v) const override; }; @@ -361,6 +402,9 @@ class NotExpr final : public UnaryExpr { public: explicit NotExpr(ExprPtr op); + // Optimization-related: + ExprPtr Duplicate() override; + protected: ValPtr Fold(Val* v) const override; }; @@ -369,6 +413,9 @@ class PosExpr final : public UnaryExpr { public: explicit PosExpr(ExprPtr op); + // Optimization-related: + ExprPtr Duplicate() override; + protected: ValPtr Fold(Val* v) const override; }; @@ -377,6 +424,9 @@ class NegExpr final : public UnaryExpr { public: explicit NegExpr(ExprPtr op); + // Optimization-related: + ExprPtr Duplicate() override; + protected: ValPtr Fold(Val* v) const override; }; @@ -386,6 +436,9 @@ public: explicit SizeExpr(ExprPtr op); ValPtr Eval(Frame* f) const override; + // Optimization-related: + ExprPtr Duplicate() override; + protected: ValPtr Fold(Val* v) const override; }; @@ -394,35 +447,53 @@ class AddExpr final : public BinaryExpr { public: AddExpr(ExprPtr op1, ExprPtr op2); void Canonicize() override; + + // Optimization-related: + ExprPtr Duplicate() override; }; class AddToExpr final : public BinaryExpr { public: AddToExpr(ExprPtr op1, ExprPtr op2); ValPtr Eval(Frame* f) const override; + + // Optimization-related: + ExprPtr Duplicate() override; }; class RemoveFromExpr final : public BinaryExpr { public: RemoveFromExpr(ExprPtr op1, ExprPtr op2); ValPtr Eval(Frame* f) const override; + + // Optimization-related: + ExprPtr Duplicate() override; }; class SubExpr final : public BinaryExpr { public: SubExpr(ExprPtr op1, ExprPtr op2); + + // Optimization-related: + ExprPtr Duplicate() override; }; class TimesExpr final : public BinaryExpr { public: TimesExpr(ExprPtr op1, ExprPtr op2); void Canonicize() override; + + // Optimization-related: + ExprPtr Duplicate() override; }; class DivideExpr final : public BinaryExpr { public: DivideExpr(ExprPtr op1, ExprPtr op2); + // Optimization-related: + ExprPtr Duplicate() override; + protected: ValPtr AddrFold(Val* v1, Val* v2) const override; }; @@ -430,6 +501,9 @@ protected: class ModExpr final : public BinaryExpr { public: ModExpr(ExprPtr op1, ExprPtr op2); + + // Optimization-related: + ExprPtr Duplicate() override; }; class BoolExpr final : public BinaryExpr { @@ -438,11 +512,17 @@ public: ValPtr Eval(Frame* f) const override; ValPtr DoSingleEval(Frame* f, ValPtr v1, Expr* op2) const; + + // Optimization-related: + ExprPtr Duplicate() override; }; class BitExpr final : public BinaryExpr { public: BitExpr(BroExprTag tag, ExprPtr op1, ExprPtr op2); + + // Optimization-related: + ExprPtr Duplicate() override; }; class EqExpr final : public BinaryExpr { @@ -450,6 +530,9 @@ public: EqExpr(BroExprTag tag, ExprPtr op1, ExprPtr op2); void Canonicize() override; + // Optimization-related: + ExprPtr Duplicate() override; + protected: ValPtr Fold(Val* v1, Val* v2) const override; }; @@ -458,6 +541,9 @@ class RelExpr final : public BinaryExpr { public: RelExpr(BroExprTag tag, ExprPtr op1, ExprPtr op2); void Canonicize() override; + + // Optimization-related: + ExprPtr Duplicate() override; }; class CondExpr final : public Expr { @@ -473,6 +559,10 @@ public: TraversalCode Traverse(TraversalCallback* cb) const override; + // Optimization-related: + ExprPtr Duplicate() override; + ExprPtr Inline(Inliner* inl) override; + protected: void ExprDescribe(ODesc* d) const override; @@ -487,6 +577,9 @@ public: void Assign(Frame* f, ValPtr v) override; ExprPtr MakeLvalue() override; + + // Optimization-related: + ExprPtr Duplicate() override; }; class AssignExpr : public BinaryExpr { @@ -509,6 +602,9 @@ public: op2 = std::move(e); } + // Optimization-related: + ExprPtr Duplicate() override; + protected: bool TypeCheck(const AttributesPtr& attrs = nullptr); bool TypeCheckArithmetics(TypeTag bt1, TypeTag bt2); @@ -522,6 +618,9 @@ public: IndexSliceAssignExpr(ExprPtr op1, ExprPtr op2, bool is_init); ValPtr Eval(Frame* f) const override; + + // Optimization-related: + ExprPtr Duplicate() override; }; class IndexExpr : public BinaryExpr { @@ -546,6 +645,9 @@ public: bool IsSlice() const { return is_slice; } + // Optimization-related: + ExprPtr Duplicate() override; + protected: ValPtr Fold(Val* v1, Val* v2) const override; @@ -585,6 +687,9 @@ public: return v; } + + // Optimization-related: + ExprPtr Duplicate() override; }; class FieldExpr final : public UnaryExpr { @@ -602,6 +707,9 @@ public: ExprPtr MakeLvalue() override; + // Optimization-related: + ExprPtr Duplicate() override; + protected: ValPtr Fold(Val* v) const override; @@ -621,6 +729,9 @@ public: const char* FieldName() const { return field_name; } + // Optimization-related: + ExprPtr Duplicate() override; + protected: ValPtr Fold(Val* v) const override; @@ -643,6 +754,9 @@ public: TraversalCode Traverse(TraversalCallback* cb) const override; + // Optimization-related: + ExprPtr Duplicate() override; + protected: ValPtr InitVal(const zeek::Type* t, ValPtr aggr) const override; @@ -655,7 +769,8 @@ class TableConstructorExpr final : public UnaryExpr { public: TableConstructorExpr(ListExprPtr constructor_list, std::unique_ptr> attrs, - TypePtr arg_type = nullptr); + TypePtr arg_type = nullptr, + AttributesPtr arg_attrs = nullptr); [[deprecated("Remove in v4.1. Use GetAttrs().")]] Attributes* Attrs() { return attrs.get(); } @@ -665,6 +780,9 @@ public: ValPtr Eval(Frame* f) const override; + // Optimization-related: + ExprPtr Duplicate() override; + protected: ValPtr InitVal(const zeek::Type* t, ValPtr aggr) const override; @@ -677,7 +795,8 @@ class SetConstructorExpr final : public UnaryExpr { public: SetConstructorExpr(ListExprPtr constructor_list, std::unique_ptr> attrs, - TypePtr arg_type = nullptr); + TypePtr arg_type = nullptr, + AttributesPtr arg_attrs = nullptr); [[deprecated("Remove in v4.1. Use GetAttrs().")]] Attributes* Attrs() { return attrs.get(); } @@ -687,6 +806,9 @@ public: ValPtr Eval(Frame* f) const override; + // Optimization-related: + ExprPtr Duplicate() override; + protected: ValPtr InitVal(const zeek::Type* t, ValPtr aggr) const override; @@ -702,6 +824,9 @@ public: ValPtr Eval(Frame* f) const override; + // Optimization-related: + ExprPtr Duplicate() override; + protected: ValPtr InitVal(const zeek::Type* t, ValPtr aggr) const override; @@ -717,6 +842,9 @@ public: void EvalIntoAggregate(const zeek::Type* t, Val* aggr, Frame* f) const override; bool IsRecordElement(TypeDecl* td) const override; + // Optimization-related: + ExprPtr Duplicate() override; + protected: void ExprDescribe(ODesc* d) const override; @@ -727,6 +855,9 @@ class ArithCoerceExpr final : public UnaryExpr { public: ArithCoerceExpr(ExprPtr op, TypeTag t); + // Optimization-related: + ExprPtr Duplicate() override; + protected: ValPtr FoldSingleVal(Val* v, InternalTypeTag t) const; ValPtr Fold(Val* v) const override; @@ -737,6 +868,9 @@ public: RecordCoerceExpr(ExprPtr op, RecordTypePtr r); ~RecordCoerceExpr() override; + // Optimization-related: + ExprPtr Duplicate() override; + protected: ValPtr InitVal(const zeek::Type* t, ValPtr aggr) const override; ValPtr Fold(Val* v) const override; @@ -752,6 +886,9 @@ public: TableCoerceExpr(ExprPtr op, TableTypePtr r); ~TableCoerceExpr() override; + // Optimization-related: + ExprPtr Duplicate() override; + protected: ValPtr Fold(Val* v) const override; }; @@ -761,6 +898,9 @@ public: VectorCoerceExpr(ExprPtr op, VectorTypePtr v); ~VectorCoerceExpr() override; + // Optimization-related: + ExprPtr Duplicate() override; + protected: ValPtr Fold(Val* v) const override; }; @@ -790,6 +930,10 @@ public: TraversalCode Traverse(TraversalCallback* cb) const override; + // Optimization-related: + ExprPtr Duplicate() override; + ExprPtr Inline(Inliner* inl) override; + protected: void ExprDescribe(ODesc* d) const override; @@ -801,6 +945,9 @@ class InExpr final : public BinaryExpr { public: InExpr(ExprPtr op1, ExprPtr op2); + // Optimization-related: + ExprPtr Duplicate() override; + protected: ValPtr Fold(Val* v1, Val* v2) const override; @@ -820,6 +967,10 @@ public: TraversalCode Traverse(TraversalCallback* cb) const override; + // Optimization-related: + ExprPtr Duplicate() override; + ExprPtr Inline(Inliner* inl) override; + protected: void ExprDescribe(ODesc* d) const override; @@ -843,6 +994,10 @@ public: Scope* GetScope() const; + // Optimization-related: + ExprPtr Duplicate() override; + ExprPtr Inline(Inliner* inl) override; + protected: void ExprDescribe(ODesc* d) const override; @@ -865,6 +1020,10 @@ public: TraversalCode Traverse(TraversalCallback* cb) const override; + // Optimization-related: + ExprPtr Duplicate() override; + ExprPtr Inline(Inliner* inl) override; + protected: void ExprDescribe(ODesc* d) const override; @@ -896,6 +1055,10 @@ public: TraversalCode Traverse(TraversalCallback* cb) const override; + // Optimization-related: + ExprPtr Duplicate() override; + ExprPtr Inline(Inliner* inl) override; + protected: ValPtr AddSetInit(const zeek::Type* t, ValPtr aggr) const; @@ -914,6 +1077,9 @@ class CastExpr final : public UnaryExpr { public: CastExpr(ExprPtr op, TypePtr t); + // Optimization-related: + ExprPtr Duplicate() override; + protected: ValPtr Eval(Frame* f) const override; void ExprDescribe(ODesc* d) const override; @@ -923,6 +1089,9 @@ class IsExpr final : public UnaryExpr { public: IsExpr(ExprPtr op, TypePtr t); + // Optimization-related: + ExprPtr Duplicate() override; + protected: ValPtr Fold(Val* v) const override; void ExprDescribe(ODesc* d) const override; @@ -931,6 +1100,10 @@ private: TypePtr t; }; + +#include "zeek/script_opt/ExprOpt-Subclasses.h" + + inline Val* Expr::ExprVal() const { if ( ! IsConst() ) diff --git a/src/Frame.cc b/src/Frame.cc index 67a42c0163..b9541527ef 100644 --- a/src/Frame.cc +++ b/src/Frame.cc @@ -30,6 +30,8 @@ Frame::Frame(int arg_size, const ScriptFunc* func, const zeek::Args* fn_args) delayed = false; closure = nullptr; + + current_offset = 0; } Frame::~Frame() @@ -68,12 +70,16 @@ void Frame::SetElement(int n, Val* v) void Frame::SetElement(int n, ValPtr v) { + n += current_offset; + ClearElement(n); frame[n] = {std::move(v), false}; } void Frame::SetElementWeak(int n, Val* v) { + n += current_offset; + ClearElement(n); frame[n] = {{AdoptRef{}, v}, true}; } @@ -120,10 +126,10 @@ const ValPtr& Frame::GetElementByID(const ID* id) const { auto where = offset_map->find(std::string(id->Name())); if ( where != offset_map->end() ) - return frame[where->second].val; + return frame[where->second + current_offset].val; } - return frame[id->Offset()].val; + return frame[id->Offset() + current_offset].val; } void Frame::Reset(int startIdx) @@ -142,7 +148,7 @@ void Frame::Reset(int startIdx) functions_with_closure_frame_reference.reset(); } - for ( int i = startIdx; i < size; ++i ) + for ( int i = startIdx + current_offset; i < size; ++i ) ClearElement(i); } @@ -244,7 +250,7 @@ Frame* Frame::SelectiveClone(const IDPList& selection, ScriptFunc* func) const } } - if ( ! frame[id->Offset()].val ) + if ( ! frame[id->Offset() + current_offset].val ) reporter->InternalError("Attempted to clone an id ('%s') with no associated value.", id->Name()); CloneNonFuncElement(id->Offset(), func, other); diff --git a/src/Frame.h b/src/Frame.h index 6dbe069d2e..8e2e26dcaf 100644 --- a/src/Frame.h +++ b/src/Frame.h @@ -98,6 +98,15 @@ public: Val* GetElement(const ID* id) const { return GetElementByID(id).get(); } + /** + * Increases the current offset being used for frame accesses. + * This is in support of inlined functions. + * + * @param incr Amount by which to increase the frame offset. + * Use a negative value to shrink the offset. + */ + void IncreaseOffset(int incr) { current_offset += incr; } + /** * Resets all of the indexes from [*startIdx, frame_size) in * the Frame. @@ -316,6 +325,12 @@ private: /** Associates ID's offsets with values. */ std::unique_ptr frame; + /** The offset we're currently using for references into the frame. + * This is how we support inlined functions without having to + * alter the offsets associated with their local variables. + */ + int current_offset; + /** The enclosing frame of this frame. */ Frame* closure; diff --git a/src/Func.cc b/src/Func.cc index f947f176d2..bd0a0c6b06 100644 --- a/src/Func.cc +++ b/src/Func.cc @@ -115,7 +115,7 @@ std::string render_call_stack() if ( ci.call ) { - auto loc = ci.call->GetLocationInfo(); + auto loc = ci.call->Original()->GetLocationInfo(); rval += util::fmt(" at %s:%d", loc->filename, loc->first_line); } @@ -310,6 +310,7 @@ ScriptFunc::ScriptFunc(const IDPtr& arg_id, StmtPtr arg_body, { Body b; b.stmts = AddInits(std::move(arg_body), aggr_inits); + current_body = b.stmts; b.priority = priority; bodies.push_back(b); } @@ -385,7 +386,7 @@ ValPtr ScriptFunc::Invoke(zeek::Args* args, Frame* parent) const { if ( sample_logger ) sample_logger->LocationSeen( - body.stmts->GetLocationInfo()); + body.stmts->Original()->GetLocationInfo()); // Fill in the rest of the frame with the function's arguments. for ( auto j = 0u; j < args->size(); ++j ) @@ -497,6 +498,8 @@ void ScriptFunc::AddBody(StmtPtr new_body, b.stmts = new_body; b.priority = priority; + current_body = new_body; + bodies.push_back(b); sort(bodies.begin(), bodies.end()); } @@ -627,6 +630,7 @@ BuiltinFunc::BuiltinFunc(built_in_func arg_func, const char* arg_name, type = id->GetType(); id->SetVal(make_intrusive(IntrusivePtr{NewRef{}, this})); + id->SetConst(); } BuiltinFunc::~BuiltinFunc() diff --git a/src/Func.h b/src/Func.h index 110ce6300d..e58b8b5ccf 100644 --- a/src/Func.h +++ b/src/Func.h @@ -9,13 +9,14 @@ #include #include -#include "ZeekList.h" -#include "Obj.h" -#include "IntrusivePtr.h" -#include "Type.h" /* for function_flavor */ -#include "TraverseTypes.h" -#include "ZeekArgs.h" -#include "BifReturnVal.h" +#include "zeek/ZeekList.h" +#include "zeek/Stmt.h" +#include "zeek/Obj.h" +#include "zeek/IntrusivePtr.h" +#include "zeek/Type.h" /* for function_flavor */ +#include "zeek/TraverseTypes.h" +#include "zeek/ZeekArgs.h" +#include "zeek/BifReturnVal.h" ZEEK_FORWARD_DECLARE_NAMESPACED(Scope, zeek::detail); ZEEK_FORWARD_DECLARE_NAMESPACED(Val, zeek); @@ -43,6 +44,8 @@ using ScopePtr = IntrusivePtr; using IDPtr = IntrusivePtr; using StmtPtr = IntrusivePtr; +class ScriptFunc; + } // namespace detail class Func; @@ -60,6 +63,18 @@ public: ~Func() override; + zeek::detail::ScriptFunc* AsScriptFunc() + { + return GetKind() == SCRIPT_FUNC ? + (zeek::detail::ScriptFunc*) this : nullptr; + } + + const zeek::detail::ScriptFunc* AsScriptFunc() const + { + return GetKind() == SCRIPT_FUNC ? + (zeek::detail::ScriptFunc*) this : nullptr; + } + virtual bool IsPure() const = 0; FunctionFlavor Flavor() const { return GetType()->Flavor(); } @@ -193,6 +208,22 @@ public: const std::vector& new_inits, size_t new_frame_size, int priority) override; + StmtPtr CurrentBody() const { return current_body; } + + /** + * Returns the function's frame size. + * @return The number of ValPtr slots in the function's frame. + */ + int FrameSize() const { return frame_size; } + + /** + * Changes the function's frame size to a new size - used for + * script optimization/compilation. + * + * @param new_size The frame size the function should use. + */ + void SetFrameSize(int new_size) { frame_size = new_size; } + /** Sets this function's outer_id list. */ void SetOuterIDs(IDPList ids) { outer_ids = std::move(ids); } @@ -226,6 +257,9 @@ private: // The frame the ScriptFunc was initialized in. Frame* closure = nullptr; bool weak_closure_ref = false; + + // The most recently added/updated body. + StmtPtr current_body; }; using built_in_func = BifReturnVal (*)(Frame* frame, const Args* args); diff --git a/src/Options.cc b/src/Options.cc index 951c55831b..b3ce952ac5 100644 --- a/src/Options.cc +++ b/src/Options.cc @@ -2,10 +2,8 @@ #include "zeek-config.h" -#include "Options.h" - -#include -#include +#include "zeek/Options.h" +#include "zeek/script_opt/ScriptOpt.h" #include @@ -13,8 +11,11 @@ #include #endif -#include "bsd-getopt-long.h" -#include "logging/writers/ascii/Ascii.h" +#include +#include + +#include "zeek/bsd-getopt-long.h" +#include "zeek/logging/writers/ascii/Ascii.h" namespace zeek { @@ -104,6 +105,7 @@ void usage(const char* prog, int code) fprintf(stderr, " -H|--save-seeds | save seeds to given file\n"); fprintf(stderr, " -I|--print-id | print out given ID\n"); fprintf(stderr, " -N|--print-plugins | print available plugins and exit (-NN for verbose)\n"); + fprintf(stderr, " -O|--optimize[=