about summary refs log tree commit diff
diff options
context:
space:
mode:
authorKane York <kanepyork@gmail.com>2020-08-10T05·42-0700
committerkanepyork <rikingcoding@gmail.com>2020-08-10T22·16+0000
commit906f5c1d2d442b1d34621b97950c38c659b729a6 (patch)
tree48b663ee52e56f8471539afece70de67a0144622
parent42bdaacca62ad5760e5d46315f1e6dc2bcc3fd96 (diff)
fix(3p/nix): inherit Expr from gc, make parser state traceable r/1633
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 <mail@tazj.in>
Reviewed-by: glittershark <grfn@gws.fyi>
-rw-r--r--third_party/nix/src/libexpr/nixexpr.hh34
-rw-r--r--third_party/nix/src/libexpr/parser.cc7
-rw-r--r--third_party/nix/src/libexpr/parser.hh4
-rw-r--r--third_party/nix/src/libexpr/parser.y51
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<Symbol, Expr*>;
 
-typedef std::vector<AttrName> AttrPath;
+typedef std::vector<AttrName, traceable_allocator<AttrName>> AttrPath;
+
+using AttrNameVector =
+    std::vector<nix::AttrName, traceable_allocator<nix::AttrName>>;
+
+using VectorExprs = std::vector<nix::Expr*, traceable_allocator<nix::Expr*>>;
 
 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<Symbol, AttrDef> AttrDefs;
+  typedef absl::flat_hash_map<
+      Symbol, AttrDef, absl::container_internal::hash_default_hash<Symbol>,
+      absl::container_internal::hash_default_eq<Symbol>,
+      traceable_allocator<std::pair<const Symbol, AttrDef>>>
+      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<DynamicAttrDef> DynamicAttrDefs;
+  typedef std::vector<DynamicAttrDef, traceable_allocator<DynamicAttrDef>>
+      DynamicAttrDefs;
   DynamicAttrDefs dynamicAttrs;
 
   ExprAttrs() : recursive(false){};
@@ -214,20 +224,20 @@ struct ExprAttrs : Expr {
 };
 
 struct ExprList : Expr {
-  std::vector<Expr*> 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<Formal> Formals_;
+struct Formals : public gc {
+  typedef std::list<Formal, traceable_allocator<Formal>> Formals_;
   Formals_ formals;
   std::set<Symbol> argNames;  // used during parsing
   bool ellipsis;
@@ -325,8 +335,8 @@ MakeBinOp(ExprOpConcatLists, "++");
 struct ExprConcatStrings : Expr {
   Pos pos;
   bool forceString;
-  std::vector<Expr*>* es;
-  ExprConcatStrings(const Pos& pos, bool forceString, std::vector<Expr*>* 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<Expr*>& 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<Expr*>* es2 = new std::vector<Expr*>;
+  VectorExprs* es2 = new VectorExprs;
   atStartOfLine = true;
   size_t curDropped = 0;
   size_t n = es.size();
-  for (std::vector<Expr*>::iterator i = es.begin(); i != es.end(); ++i, --n) {
+  for (VectorExprs::iterator i = es.begin(); i != es.end(); ++i, --n) {
     ExprIndStr* e = dynamic_cast<ExprIndStr*>(*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 <optional>
 #include <variant>
 
+#include <gc/gc.h>
 #include <glog/logging.h>
 
 #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<Expr*>& 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<nix::AttrName> * attrNames;
-  std::vector<nix::Expr *> * string_parts;
-}
-
 %type <e> start expr expr_function expr_if expr_op
 %type <e> expr_app expr_select expr_simple
 %type <list> 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<Expr *>({$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<Expr *>; $$->push_back($2); }
+  | DOLLAR_CURLY expr '}' { $$ = new nix::VectorExprs; $$->push_back($2); }
   | STR DOLLAR_CURLY expr '}' {
-      $$ = new std::vector<Expr *>;
+      $$ = 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<Expr *>; }
+  | { $$ = new nix::VectorExprs; }
   ;
 
 binds
@@ -276,9 +283,9 @@ attrpath
           $$->push_back(AttrName($3));
       }
     }
-  | attr { $$ = new std::vector<AttrName>; $$->push_back(AttrName(data->symbols.Create($1))); }
+  | attr { $$ = new nix::AttrNameVector; $$->push_back(AttrName(data->symbols.Create($1))); }
   | string_attr
-    { $$ = new std::vector<AttrName>;
+    { $$ = new nix::AttrNameVector;
       ExprString *str = dynamic_cast<ExprString *>($1);
       if (str) {
           $$->push_back(AttrName(str->s));