Nix 2.26.3
Nix, the purely functional package manager; unstable internal interfaces
 
Loading...
Searching...
No Matches
eval-inline.hh
Go to the documentation of this file.
1#pragma once
3
4#include "print.hh"
5#include "eval.hh"
6#include "eval-error.hh"
7#include "eval-settings.hh"
8
9namespace nix {
10
14[[gnu::always_inline]]
15inline void * allocBytes(size_t n)
16{
17 void * p;
18#if HAVE_BOEHMGC
19 p = GC_MALLOC(n);
20#else
21 p = calloc(n, 1);
22#endif
23 if (!p) throw std::bad_alloc();
24 return p;
25}
26
27
28[[gnu::always_inline]]
30{
31#if HAVE_BOEHMGC
32 /* We use the boehm batch allocator to speed up allocations of Values (of which there are many).
33 GC_malloc_many returns a linked list of objects of the given size, where the first word
34 of each object is also the pointer to the next object in the list. This also means that we
35 have to explicitly clear the first word of every object we take. */
36 if (!*valueAllocCache) {
37 *valueAllocCache = GC_malloc_many(sizeof(Value));
38 if (!*valueAllocCache) throw std::bad_alloc();
39 }
40
41 /* GC_NEXT is a convenience macro for accessing the first word of an object.
42 Take the first list item, advance the list to the next item, and clear the next pointer. */
43 void * p = *valueAllocCache;
44 *valueAllocCache = GC_NEXT(p);
45 GC_NEXT(p) = nullptr;
46#else
47 void * p = allocBytes(sizeof(Value));
48#endif
49
50 nrValues++;
51 return (Value *) p;
52}
53
54
55[[gnu::always_inline]]
56Env & EvalState::allocEnv(size_t size)
57{
58 nrEnvs++;
59 nrValuesInEnvs += size;
60
61 Env * env;
62
63#if HAVE_BOEHMGC
64 if (size == 1) {
65 /* see allocValue for explanations. */
66 if (!*env1AllocCache) {
67 *env1AllocCache = GC_malloc_many(sizeof(Env) + sizeof(Value *));
68 if (!*env1AllocCache) throw std::bad_alloc();
69 }
70
71 void * p = *env1AllocCache;
72 *env1AllocCache = GC_NEXT(p);
73 GC_NEXT(p) = nullptr;
74 env = (Env *) p;
75 } else
76#endif
77 env = (Env *) allocBytes(sizeof(Env) + size * sizeof(Value *));
78
79 /* We assume that env->values has been cleared by the allocator; maybeThunk() and lookupVar fromWith expect this. */
80
81 return *env;
82}
83
84
85[[gnu::always_inline]]
86void EvalState::forceValue(Value & v, const PosIdx pos)
87{
88 if (v.isThunk()) {
89 Env * env = v.payload.thunk.env;
90 assert(env || v.isBlackhole());
91 Expr * expr = v.payload.thunk.expr;
92 try {
93 v.mkBlackhole();
94 //checkInterrupt();
95 if (env) [[likely]]
96 expr->eval(*this, *env, v);
97 else
98 ExprBlackHole::throwInfiniteRecursionError(*this, v);
99 } catch (...) {
100 v.mkThunk(env, expr);
101 tryFixupBlackHolePos(v, pos);
102 throw;
103 }
104 }
105 else if (v.isApp())
106 callFunction(*v.payload.app.left, *v.payload.app.right, v, pos);
107}
108
109
110[[gnu::always_inline]]
111inline void EvalState::forceAttrs(Value & v, const PosIdx pos, std::string_view errorCtx)
112{
113 forceAttrs(v, [&]() { return pos; }, errorCtx);
114}
115
116
117template <typename Callable>
118[[gnu::always_inline]]
119inline void EvalState::forceAttrs(Value & v, Callable getPos, std::string_view errorCtx)
120{
121 PosIdx pos = getPos();
122 forceValue(v, pos);
123 if (v.type() != nAttrs) {
124 error<TypeError>(
125 "expected a set but found %1%: %2%",
126 showType(v),
127 ValuePrinter(*this, v, errorPrintOptions)
128 ).withTrace(pos, errorCtx).debugThrow();
129 }
130}
131
132
133[[gnu::always_inline]]
134inline void EvalState::forceList(Value & v, const PosIdx pos, std::string_view errorCtx)
135{
136 forceValue(v, pos);
137 if (!v.isList()) {
138 error<TypeError>(
139 "expected a list but found %1%: %2%",
140 showType(v),
141 ValuePrinter(*this, v, errorPrintOptions)
142 ).withTrace(pos, errorCtx).debugThrow();
143 }
144}
145
146[[gnu::always_inline]]
148 if (callDepth > settings.maxCallDepth)
149 error<EvalError>("stack overflow; max-call-depth exceeded").atPos(pos).debugThrow();
150
151 return CallDepth(callDepth);
152};
153
154}
Definition eval.hh:47
void forceValue(Value &v, const PosIdx pos)
Definition eval-inline.hh:86
Value * allocValue()
Definition eval-inline.hh:29
CallDepth addCallDepth(const PosIdx pos)
Definition eval-inline.hh:147
Definition pos-idx.hh:9
void * allocBytes(size_t n)
Definition eval-inline.hh:15
std::shared_ptr< T > p
Definition lexer.l:1269
Common printing functions for the Nix language.
Definition eval.hh:152
Definition nixexpr.hh:81
Definition value.hh:167