From 906f5c1d2d442b1d34621b97950c38c659b729a6 Mon Sep 17 00:00:00 2001 From: Kane York Date: Sun, 9 Aug 2020 22:42:00 -0700 Subject: fix(3p/nix): inherit Expr from gc, make parser state traceable The parser contained vectors, and the primary parser state, that were not participating in GC tracing. Change-Id: Ie198592cd7acffd390e3e2ae9595138b56416838 Reviewed-on: https://cl.tvl.fyi/c/depot/+/1706 Tested-by: BuildkiteCI Reviewed-by: tazjin Reviewed-by: glittershark --- third_party/nix/src/libexpr/nixexpr.hh | 34 +++++++++++++++-------- third_party/nix/src/libexpr/parser.cc | 7 ++--- third_party/nix/src/libexpr/parser.hh | 4 +-- third_party/nix/src/libexpr/parser.y | 51 +++++++++++++++++++--------------- 4 files changed, 56 insertions(+), 40 deletions(-) diff --git a/third_party/nix/src/libexpr/nixexpr.hh b/third_party/nix/src/libexpr/nixexpr.hh index 7b89fb0c92..6edfb2a187 100644 --- a/third_party/nix/src/libexpr/nixexpr.hh +++ b/third_party/nix/src/libexpr/nixexpr.hh @@ -74,13 +74,18 @@ struct StaticEnv; /* An attribute path is a sequence of attribute names. */ using AttrName = std::variant; -typedef std::vector AttrPath; +typedef std::vector> AttrPath; + +using AttrNameVector = + std::vector>; + +using VectorExprs = std::vector>; std::string showAttrPath(const AttrPath& attrPath); /* Abstract syntax of Nix expressions. */ -struct Expr { +struct Expr : public gc { virtual ~Expr(){}; virtual void show(std::ostream& str) const; virtual void bindVars(const StaticEnv& env); @@ -186,7 +191,7 @@ struct ExprOpHasAttr : Expr { struct ExprAttrs : Expr { bool recursive; - struct AttrDef { + struct AttrDef : public gc { bool inherited; Expr* e; Pos pos; @@ -196,17 +201,22 @@ struct ExprAttrs : Expr { AttrDef(){}; }; - typedef absl::flat_hash_map AttrDefs; + typedef absl::flat_hash_map< + Symbol, AttrDef, absl::container_internal::hash_default_hash, + absl::container_internal::hash_default_eq, + traceable_allocator>> + AttrDefs; AttrDefs attrs; - struct DynamicAttrDef { + struct DynamicAttrDef : public gc { Expr *nameExpr, *valueExpr; Pos pos; DynamicAttrDef(Expr* nameExpr, Expr* valueExpr, const Pos& pos) : nameExpr(nameExpr), valueExpr(valueExpr), pos(pos){}; }; - typedef std::vector DynamicAttrDefs; + typedef std::vector> + DynamicAttrDefs; DynamicAttrDefs dynamicAttrs; ExprAttrs() : recursive(false){}; @@ -214,20 +224,20 @@ struct ExprAttrs : Expr { }; struct ExprList : Expr { - std::vector elems; + VectorExprs elems; ExprList(){}; COMMON_METHODS }; -struct Formal { +struct Formal : public gc { Symbol name; Expr* def; // def = default, not definition Formal(const Symbol& name, Expr* def) : name(name), def(def){}; }; // Describes structured function arguments (e.g. `{ a }: ...`) -struct Formals { - typedef std::list Formals_; +struct Formals : public gc { + typedef std::list> Formals_; Formals_ formals; std::set argNames; // used during parsing bool ellipsis; @@ -325,8 +335,8 @@ MakeBinOp(ExprOpConcatLists, "++"); struct ExprConcatStrings : Expr { Pos pos; bool forceString; - std::vector* es; - ExprConcatStrings(const Pos& pos, bool forceString, std::vector* es) + nix::VectorExprs* es; + ExprConcatStrings(const Pos& pos, bool forceString, nix::VectorExprs* es) : pos(pos), forceString(forceString), es(es){}; COMMON_METHODS }; diff --git a/third_party/nix/src/libexpr/parser.cc b/third_party/nix/src/libexpr/parser.cc index a96d345cc1..29d31661c8 100644 --- a/third_party/nix/src/libexpr/parser.cc +++ b/third_party/nix/src/libexpr/parser.cc @@ -92,8 +92,7 @@ void addFormal(const Pos& pos, Formals* formals, const Formal& formal) { formals->argNames.insert(formal.name); } -Expr* stripIndentation(const Pos& pos, SymbolTable& symbols, - std::vector& es) { +Expr* stripIndentation(const Pos& pos, SymbolTable& symbols, VectorExprs& es) { if (es.empty()) { return new ExprString(symbols.Create("")); } @@ -138,11 +137,11 @@ Expr* stripIndentation(const Pos& pos, SymbolTable& symbols, } /* Strip spaces from each line. */ - std::vector* es2 = new std::vector; + VectorExprs* es2 = new VectorExprs; atStartOfLine = true; size_t curDropped = 0; size_t n = es.size(); - for (std::vector::iterator i = es.begin(); i != es.end(); ++i, --n) { + for (VectorExprs::iterator i = es.begin(); i != es.end(); ++i, --n) { ExprIndStr* e = dynamic_cast(*i); if (!e) { atStartOfLine = false; diff --git a/third_party/nix/src/libexpr/parser.hh b/third_party/nix/src/libexpr/parser.hh index 7b8f955731..ca7a88b3b9 100644 --- a/third_party/nix/src/libexpr/parser.hh +++ b/third_party/nix/src/libexpr/parser.hh @@ -5,6 +5,7 @@ #include #include +#include #include #include "libexpr/eval.hh" @@ -59,8 +60,7 @@ void addAttr(ExprAttrs* attrs, AttrPath& attrPath, Expr* e, const Pos& pos); void addFormal(const Pos& pos, Formals* formals, const Formal& formal); -Expr* stripIndentation(const Pos& pos, SymbolTable& symbols, - std::vector& es); +Expr* stripIndentation(const Pos& pos, SymbolTable& symbols, VectorExprs& es); Path resolveExprPath(Path path); diff --git a/third_party/nix/src/libexpr/parser.y b/third_party/nix/src/libexpr/parser.y index 9998721488..b47d96b1e1 100644 --- a/third_party/nix/src/libexpr/parser.y +++ b/third_party/nix/src/libexpr/parser.y @@ -14,6 +14,29 @@ %code requires { #define YY_NO_INPUT 1 // disable unused yyinput features #include "libexpr/parser.hh" + +// Allow GC tracing of YY-allocated structures +#define YYMALLOC GC_MALLOC_UNCOLLECTABLE +#define YYFREE GC_FREE +#define YYREALLOC GC_REALLOC + +struct YYSTYPE : public gc { + union { + nix::Expr * e; + nix::ExprList * list; + nix::ExprAttrs * attrs; + nix::Formals * formals; + nix::Formal * formal; + nix::NixInt n; + nix::NixFloat nf; + const char * id; // !!! -> Symbol + char * path; + char * uri; + nix::AttrNameVector * attrNames; + nix::VectorExprs * string_parts; + }; +}; + } %{ @@ -40,22 +63,6 @@ void yyerror(YYLTYPE* loc, yyscan_t scanner, ParseData* data, %} -%union { - // !!! We're probably leaking stuff here. - nix::Expr * e; - nix::ExprList * list; - nix::ExprAttrs * attrs; - nix::Formals * formals; - nix::Formal * formal; - nix::NixInt n; - nix::NixFloat nf; - const char * id; // !!! -> Symbol - char * path; - char * uri; - std::vector * attrNames; - std::vector * string_parts; -} - %type start expr expr_function expr_if expr_op %type expr_app expr_select expr_simple %type expr_list @@ -138,7 +145,7 @@ expr_op | expr_op UPDATE expr_op { $$ = new ExprOpUpdate(CUR_POS, $1, $3); } | expr_op '?' attrpath { $$ = new ExprOpHasAttr($1, *$3); } | expr_op '+' expr_op - { $$ = new ExprConcatStrings(CUR_POS, false, new std::vector({$1, $3})); } + { $$ = new ExprConcatStrings(CUR_POS, false, new nix::VectorExprs({$1, $3})); } | expr_op '-' expr_op { $$ = new ExprApp(CUR_POS, new ExprApp(new ExprVar(data->symbols.Create("__sub")), $1), $3); } | expr_op '*' expr_op { $$ = new ExprApp(CUR_POS, new ExprApp(new ExprVar(data->symbols.Create("__mul")), $1), $3); } | expr_op '/' expr_op { $$ = new ExprApp(CUR_POS, new ExprApp(new ExprVar(data->symbols.Create("__div")), $1), $3); } @@ -208,9 +215,9 @@ string_parts string_parts_interpolated : string_parts_interpolated STR { $$ = $1; $1->push_back($2); } | string_parts_interpolated DOLLAR_CURLY expr '}' { $$ = $1; $1->push_back($3); } - | DOLLAR_CURLY expr '}' { $$ = new std::vector; $$->push_back($2); } + | DOLLAR_CURLY expr '}' { $$ = new nix::VectorExprs; $$->push_back($2); } | STR DOLLAR_CURLY expr '}' { - $$ = new std::vector; + $$ = new nix::VectorExprs; $$->push_back($1); $$->push_back($3); } @@ -219,7 +226,7 @@ string_parts_interpolated ind_string_parts : ind_string_parts IND_STR { $$ = $1; $1->push_back($2); } | ind_string_parts DOLLAR_CURLY expr '}' { $$ = $1; $1->push_back($3); } - | { $$ = new std::vector; } + | { $$ = new nix::VectorExprs; } ; binds @@ -276,9 +283,9 @@ attrpath $$->push_back(AttrName($3)); } } - | attr { $$ = new std::vector; $$->push_back(AttrName(data->symbols.Create($1))); } + | attr { $$ = new nix::AttrNameVector; $$->push_back(AttrName(data->symbols.Create($1))); } | string_attr - { $$ = new std::vector; + { $$ = new nix::AttrNameVector; ExprString *str = dynamic_cast($1); if (str) { $$->push_back(AttrName(str->s)); -- cgit 1.4.1