Nix 2.93.3
Lix: A modern, delicious implementation of the Nix package manager; unstable internal interfaces
Loading...
Searching...
No Matches
eval-inline.hh
Go to the documentation of this file.
1#pragma once
3
5#include "lix/libexpr/eval.hh"
7#include "lix/libexpr/gc-alloc.hh"
8
9namespace nix {
10
11[[gnu::always_inline]]
12Value * EvalMemory::allocValue()
13{
14#if HAVE_BOEHMGC
15 /* We use the boehm batch allocator to speed up allocations of Values (of which there are many).
16 GC_malloc_many returns a linked list of objects of the given size, where the first word
17 of each object is also the pointer to the next object in the list. This also means that we
18 have to explicitly clear the first word of every object we take. */
19 if (!*valueAllocCache) {
20 *valueAllocCache = GC_malloc_many(sizeof(Value));
21 if (!*valueAllocCache) throw std::bad_alloc();
22 }
23
24 /* GC_NEXT is a convenience macro for accessing the first word of an object.
25 Take the first list item, advance the list to the next item, and clear the next pointer. */
26 void * p = *valueAllocCache;
27 *valueAllocCache = GC_NEXT(p);
28 GC_NEXT(p) = nullptr;
29#else
30 void * p = gcAllocBytes(sizeof(Value));
31#endif
32
33 stats.nrValues++;
34 return static_cast<Value *>(p);
35}
36
37
38[[gnu::always_inline]]
39Env & EvalMemory::allocEnv(size_t size)
40{
41 stats.nrEnvs++;
42 stats.nrValuesInEnvs += size;
43
44 Env * env;
45
46#if HAVE_BOEHMGC
47 if (size == 1) {
48 /* see allocValue for explanations. */
49 if (!*env1AllocCache) {
50 *env1AllocCache = GC_malloc_many(sizeof(Env) + sizeof(Value *));
51 if (!*env1AllocCache) throw std::bad_alloc();
52 }
53
54 void * p = *env1AllocCache;
55 *env1AllocCache = GC_NEXT(p);
56 GC_NEXT(p) = nullptr;
57 env = static_cast<Env *>(p);
58 } else
59#endif
60 env = static_cast<Env *>(gcAllocBytes(sizeof(Env) + size * sizeof(Value *)));
61
62 /* We assume that env->values has been cleared by the allocator; maybeThunk() and lookupVar fromWith expect this. */
63
64 return *env;
65}
66
67
68[[gnu::always_inline]]
70{
71 if (v.isThunk()) {
72 Env * env = v.thunk.env;
73 Expr & expr = *v.thunk.expr;
74 try {
75 v.mkBlackhole();
76 //checkInterrupt();
77 expr.eval(*this, *env, v);
78 } catch (...) {
79 v.mkThunk(env, expr);
80 tryFixupBlackHolePos(v, pos);
81 throw;
82 }
83 }
84 else if (v.isApp())
85 callFunction(*v.app.left, *v.app.right, v, pos);
86}
87
88
89[[gnu::always_inline]]
90inline void EvalState::forceAttrs(Value & v, const PosIdx pos, std::string_view errorCtx)
91{
92 forceValue(v, pos);
93 if (v.type() != nAttrs) {
94 ctx.errors.make<TypeError>(
95 "expected a set but found %1%: %2%",
96 showType(v),
97 ValuePrinter(*this, v, errorPrintOptions)
98 ).withTrace(pos, errorCtx).debugThrow();
99 }
100}
101
102
103[[gnu::always_inline]]
104inline void EvalState::forceList(Value & v, const PosIdx pos, std::string_view errorCtx)
105{
106 forceValue(v, pos);
107 if (!v.isList()) {
108 ctx.errors.make<TypeError>(
109 "expected a list but found %1%: %2%",
110 showType(v),
111 ValuePrinter(*this, v, errorPrintOptions)
112 ).withTrace(pos, errorCtx).debugThrow();
113 }
114}
115
116
117}
void forceValue(Value &v, const PosIdx pos)
Definition eval-inline.hh:69
Definition pos-idx.hh:9
Definition print.hh:61
Common printing functions for the Nix language.
Definition eval.hh:112
Definition nixexpr.hh:104
Definition value.hh:190
ValueType type(bool invalidIsThunk=false) const
Definition value.hh:619