diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index fc6c8296b4a97e1239164d5c3fe0542b5a75c252..a3f2b92cedf7d2fd72c2f89e4e76109745186053 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -121,16 +121,16 @@ static void prim_scopedImport(EvalState & state, const Pos & pos, Value * * args
         }
         w.attrs->sort();
 
-        static Value * fun = nullptr;
+        static RootValue fun;
         if (!fun) {
-            fun = state.allocValue();
+            fun = allocRootValue(state.allocValue());
             state.eval(state.parseExprFromString(
                 #include "imported-drv-to-derivation.nix.gen.hh"
-                , "/"), *fun);
+                , "/"), **fun);
         }
 
-        state.forceFunction(*fun, pos);
-        mkApp(v, *fun, w);
+        state.forceFunction(**fun, pos);
+        mkApp(v, **fun, w);
         state.forceAttrs(v, pos);
     } else {
         state.forceAttrs(*args[0]);
diff --git a/src/nix/command.hh b/src/nix/command.hh
index 2c2303208ee4f1a0f4d8bc234d7c0da7c6a2027d..bf43d950f6a11bde59bd03dff5ec8a34a306a62c 100644
--- a/src/nix/command.hh
+++ b/src/nix/command.hh
@@ -41,7 +41,7 @@ private:
 
     std::shared_ptr<EvalState> evalState;
 
-    std::shared_ptr<Value> vSourceExpr;
+    RootValue vSourceExpr;
 };
 
 enum RealiseMode { Build, NoBuild, DryRun };
diff --git a/src/nix/installables.cc b/src/nix/installables.cc
index 902383bff07ef37c209100cab5cad2b371d76aa2..1d70ad3d554ea5ac210d4cef56e785203a54faea 100644
--- a/src/nix/installables.cc
+++ b/src/nix/installables.cc
@@ -8,8 +8,6 @@
 #include "store-api.hh"
 #include "shared.hh"
 
-#include <gc/gc.h>
-
 #include <regex>
 
 namespace nix {
@@ -27,17 +25,14 @@ SourceExprCommand::SourceExprCommand()
 
 Value * SourceExprCommand::getSourceExpr(EvalState & state)
 {
-    if (vSourceExpr) return vSourceExpr.get();
+    if (vSourceExpr) return *vSourceExpr;
 
     auto sToplevel = state.symbols.create("_toplevel");
 
-    // Allocate the vSourceExpr Value as uncollectable. Boehm GC doesn't
-    // consider the member variable "alive" during execution causing it to be
-    // GC'ed in the middle of evaluation.
-    vSourceExpr = std::allocate_shared<Value>(traceable_allocator<Value>());
+    vSourceExpr = allocRootValue(state.allocValue());
 
     if (file != "")
-        state.evalFile(lookupFileArg(state, file), *vSourceExpr);
+        state.evalFile(lookupFileArg(state, file), **vSourceExpr);
 
     else {
 
@@ -45,9 +40,9 @@ Value * SourceExprCommand::getSourceExpr(EvalState & state)
 
         auto searchPath = state.getSearchPath();
 
-        state.mkAttrs(*vSourceExpr, 1024);
+        state.mkAttrs(**vSourceExpr, 1024);
 
-        mkBool(*state.allocAttr(*vSourceExpr, sToplevel), true);
+        mkBool(*state.allocAttr(**vSourceExpr, sToplevel), true);
 
         std::unordered_set<std::string> seen;
 
@@ -58,7 +53,7 @@ Value * SourceExprCommand::getSourceExpr(EvalState & state)
             mkPrimOpApp(*v1, state.getBuiltin("findFile"), state.getBuiltin("nixPath"));
             Value * v2 = state.allocValue();
             mkApp(*v2, *v1, mkString(*state.allocValue(), name));
-            mkApp(*state.allocAttr(*vSourceExpr, state.symbols.create(name)),
+            mkApp(*state.allocAttr(**vSourceExpr, state.symbols.create(name)),
                 state.getBuiltin("import"), *v2);
         };
 
@@ -72,10 +67,10 @@ Value * SourceExprCommand::getSourceExpr(EvalState & state)
             } else
                 addEntry(i.first);
 
-        vSourceExpr->attrs->sort();
+        (*vSourceExpr)->attrs->sort();
     }
 
-    return vSourceExpr.get();
+    return *vSourceExpr;
 }
 
 ref<EvalState> SourceExprCommand::getEvalState()