From e879a0371ba7ef99da2d82547823c3f96b445fdb Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 20 Oct 2010 11:38:30 +0000 Subject: [PATCH] * Use the Boehm garbage collector to reclaim unused memory in the Nix expression evaluator. --- src/libexpr/Makefile.am | 3 ++- src/libexpr/eval.cc | 23 ++++++++++++++--------- src/libexpr/eval.hh | 5 ++++- src/nix-env/Makefile.am | 6 ++++-- src/nix-instantiate/Makefile.am | 7 +++++-- 5 files changed, 29 insertions(+), 15 deletions(-) diff --git a/src/libexpr/Makefile.am b/src/libexpr/Makefile.am index e7228e183..24aa2968b 100644 --- a/src/libexpr/Makefile.am +++ b/src/libexpr/Makefile.am @@ -20,7 +20,8 @@ EXTRA_DIST = lexer.l parser.y AM_CXXFLAGS = \ -I$(srcdir)/.. \ - -I$(srcdir)/../libutil -I$(srcdir)/../libstore + -I$(srcdir)/../libutil -I$(srcdir)/../libstore \ + -I/home/eelco/Dev/nix/boehmgc/include # Parser generation. diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index e55f28822..ba331749f 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -8,6 +8,9 @@ #include +#include +#include + #define LocalNoInline(f) static f __attribute__((noinline)); f #define LocalNoInlineNoReturn(f) static f __attribute__((noinline, noreturn)); f @@ -147,7 +150,7 @@ void EvalState::addPrimOp(const string & name, v.type = tPrimOp; v.primOp.arity = arity; v.primOp.fun = primOp; - v.primOp.name = strdup(name2.c_str()); + v.primOp.name = GC_strdup(name2.c_str()); staticBaseEnv.vars[symbols.create(name)] = baseEnvDispl; baseEnv.values[baseEnvDispl++] = v; (*baseEnv.values[0].attrs)[symbols.create(name2)].value = v; @@ -218,7 +221,7 @@ LocalNoInline(void addErrorPrefix(Error & e, const char * s, const string & s2, void mkString(Value & v, const char * s) { v.type = tString; - v.string.s = strdup(s); + v.string.s = GC_strdup(s); v.string.context = 0; } @@ -228,9 +231,10 @@ void mkString(Value & v, const string & s, const PathSet & context) mkString(v, s.c_str()); if (!context.empty()) { unsigned int n = 0; - v.string.context = new const char *[context.size() + 1]; + v.string.context = (const char * *) + GC_malloc((context.size() + 1) * sizeof(char *)); foreach (PathSet::const_iterator, i, context) - v.string.context[n++] = strdup(i->c_str()); + v.string.context[n++] = GC_strdup(i->c_str()); v.string.context[n] = 0; } } @@ -239,7 +243,7 @@ void mkString(Value & v, const string & s, const PathSet & context) void mkPath(Value & v, const char * s) { v.type = tPath; - v.path = strdup(s); + v.path = GC_strdup(s); } @@ -264,7 +268,7 @@ Value * EvalState::lookupVar(Env * env, const VarRef & var) Value * EvalState::allocValues(unsigned int count) { nrValues += count; - return new Value[count]; // !!! check destructor + return (Value *) GC_MALLOC(count * sizeof(Value)); } @@ -272,7 +276,7 @@ Env & EvalState::allocEnv(unsigned int size) { nrEnvs++; nrValuesInEnvs += size; - Env * env = (Env *) malloc(sizeof(Env) + size * sizeof(Value)); + Env * env = (Env *) GC_MALLOC(sizeof(Env) + size * sizeof(Value)); return *env; } @@ -281,7 +285,7 @@ void EvalState::mkList(Value & v, unsigned int length) { v.type = tList; v.list.length = length; - v.list.elems = new Value *[length]; + v.list.elems = (Value * *) GC_MALLOC(length * sizeof(Value *)); nrListElems += length; } @@ -289,7 +293,7 @@ void EvalState::mkList(Value & v, unsigned int length) void EvalState::mkAttrs(Value & v) { v.type = tAttrs; - v.attrs = new Bindings; + v.attrs = new (UseGC) Bindings; } @@ -1089,6 +1093,7 @@ void EvalState::printStats() bool showStats = getEnv("NIX_SHOW_STATS", "0") != "0"; Verbosity v = showStats ? lvlInfo : lvlDebug; printMsg(v, "evaluation statistics:"); + printMsg(v, format(" size of a value: %1%") % sizeof(Value)); printMsg(v, format(" expressions evaluated: %1%") % nrEvaluated); printMsg(v, format(" stack space used: %1% bytes") % (&x - deepestStack)); printMsg(v, format(" max eval() nesting depth: %1%") % maxRecursionDepth); diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 501ac93d0..d74a03506 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -7,6 +7,8 @@ #include +#include + namespace nix { @@ -16,7 +18,7 @@ struct Env; struct Value; struct Attr; -typedef std::map Bindings; +typedef std::map, gc_allocator > > Bindings; typedef enum { @@ -313,6 +315,7 @@ private: char * deepestStack; /* for measuring stack usage */ friend class RecursionCounter; + friend class ExprOpUpdate; }; diff --git a/src/nix-env/Makefile.am b/src/nix-env/Makefile.am index 7dfa7425a..169c85fcb 100644 --- a/src/nix-env/Makefile.am +++ b/src/nix-env/Makefile.am @@ -4,7 +4,8 @@ nix_env_SOURCES = nix-env.cc profiles.cc profiles.hh user-env.cc user-env.hh hel nix_env_LDADD = ../libmain/libmain.la ../libexpr/libexpr.la \ ../libstore/libstore.la ../libutil/libutil.la \ - ../boost/format/libformat.la @ADDITIONAL_NETWORK_LIBS@ + ../boost/format/libformat.la @ADDITIONAL_NETWORK_LIBS@ \ + -L/home/eelco/Dev/nix/boehmgc/lib -lgc nix-env.o: help.txt.hh @@ -14,4 +15,5 @@ nix-env.o: help.txt.hh AM_CXXFLAGS = \ -I$(srcdir)/.. \ -I$(srcdir)/../libutil -I$(srcdir)/../libstore \ - -I$(srcdir)/../libexpr -I$(srcdir)/../libmain -I../libexpr + -I$(srcdir)/../libexpr -I$(srcdir)/../libmain -I../libexpr \ + -I/home/eelco/Dev/nix/boehmgc/include diff --git a/src/nix-instantiate/Makefile.am b/src/nix-instantiate/Makefile.am index a65907a8d..c6455b116 100644 --- a/src/nix-instantiate/Makefile.am +++ b/src/nix-instantiate/Makefile.am @@ -3,7 +3,8 @@ bin_PROGRAMS = nix-instantiate nix_instantiate_SOURCES = nix-instantiate.cc help.txt nix_instantiate_LDADD = ../libmain/libmain.la ../libexpr/libexpr.la \ ../libstore/libstore.la ../libutil/libutil.la \ - ../boost/format/libformat.la @ADDITIONAL_NETWORK_LIBS@ + ../boost/format/libformat.la @ADDITIONAL_NETWORK_LIBS@ \ + -L/home/eelco/Dev/nix/boehmgc/lib -lgc nix-instantiate.o: help.txt.hh @@ -12,4 +13,6 @@ nix-instantiate.o: help.txt.hh AM_CXXFLAGS = \ -I$(srcdir)/.. -I$(srcdir)/../libutil -I$(srcdir)/../libstore \ - -I$(srcdir)/../libexpr -I$(srcdir)/../libmain -I../libexpr + -I$(srcdir)/../libexpr -I$(srcdir)/../libmain -I../libexpr \ + -I/home/eelco/Dev/nix/boehmgc/include +