Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: NixOS/nix
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 4237414f4d78^
Choose a base ref
...
head repository: NixOS/nix
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 69adbf5c7701
Choose a head ref
  • 12 commits
  • 36 files changed
  • 1 contributor

Commits on Apr 15, 2019

  1. Checkpoint

    edolstra committed Apr 15, 2019

    Verified

    This commit was signed with the committer’s verified signature. The key has expired.
    angerman Moritz Angermann
    Copy the full SHA
    4237414 View commit details

Commits on Apr 22, 2019

  1. Checkpoint

    edolstra committed Apr 22, 2019
    Copy the full SHA
    7c716b4 View commit details
  2. Checkpoint

    edolstra committed Apr 22, 2019
    Copy the full SHA
    ae5b76a View commit details
  3. Remove a word from Env

    edolstra committed Apr 22, 2019
    Copy the full SHA
    e392ff5 View commit details

Commits on Apr 23, 2019

  1. Store contexts as symbols

    This provides some deduplication since most contexts are used multiple
    times.
    
    Also, store singleton contexts directly in the Value object. This
    saves a 16-byte Context object. This is useful because the vast
    majority of contexts are singletons, e.g. 23723 out of 26138 in a
    NixOS 19.03 system configuration.
    edolstra committed Apr 23, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    2160258 View commit details
  2. Store short strings in Values

    The vast majority of strings are < 16 bytes, and so can be stored
    directly in a Value. This saves a heap allocation and an indirection.
    edolstra committed Apr 23, 2019
    Copy the full SHA
    742a804 View commit details
  3. Use Value::misc to store strings

    This allows strings < 23 characters (up from 16) to be stored directly
    in Value. On a NixOS 19.03 system configuration evaluation, this
    allows 1060588 out of 1189295 (89%) strings to be stored in Value.
    edolstra committed Apr 23, 2019
    Copy the full SHA
    a38a7b4 View commit details
  4. Copy the full SHA
    f7f73cf View commit details
  5. Move parseSize() to libutil

    edolstra committed Apr 23, 2019
    Copy the full SHA
    93b3d25 View commit details
  6. Freelist improvements

    edolstra committed Apr 23, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    ba36d43 View commit details
  7. Size -> size_t

    edolstra committed Apr 23, 2019
    Copy the full SHA
    35b76b2 View commit details
  8. Rename

    edolstra committed Apr 23, 2019
    Copy the full SHA
    69adbf5 View commit details
8 changes: 4 additions & 4 deletions src/libexpr/attr-path.cc
Original file line number Diff line number Diff line change
@@ -32,15 +32,15 @@ static Strings parseAttrPath(const string & s)
}


Value * findAlongAttrPath(EvalState & state, const string & attrPath,
Ptr<Value> findAlongAttrPath(EvalState & state, const string & attrPath,
Bindings & autoArgs, Value & vIn)
{
Strings tokens = parseAttrPath(attrPath);

Error attrError =
Error(format("attribute selection path '%1%' does not match expression") % attrPath);

Value * v = &vIn;
Ptr<Value> v(&vIn);

for (auto & attr : tokens) {

@@ -50,7 +50,7 @@ Value * findAlongAttrPath(EvalState & state, const string & attrPath,
if (string2Int(attr, attrIndex)) apType = apIndex;

/* Evaluate the expression. */
Value * vNew = state.allocValue();
auto vNew = state.allocValue();
state.autoCallFunction(autoArgs, *v, *vNew);
v = vNew;
state.forceValue(*v);
@@ -71,7 +71,7 @@ Value * findAlongAttrPath(EvalState & state, const string & attrPath,
Bindings::iterator a = v->attrs->find(state.symbols.create(attr));
if (a == v->attrs->end())
throw Error(format("attribute '%1%' in selection path '%2%' not found") % attr % attrPath);
v = &*a->value;
v = a->value;
}

else if (apType == apIndex) {
2 changes: 1 addition & 1 deletion src/libexpr/attr-path.hh
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@

namespace nix {

Value * findAlongAttrPath(EvalState & state, const string & attrPath,
Ptr<Value> findAlongAttrPath(EvalState & state, const string & attrPath,
Bindings & autoArgs, Value & vIn);

}
28 changes: 14 additions & 14 deletions src/libexpr/attr-set.cc
Original file line number Diff line number Diff line change
@@ -7,28 +7,28 @@
namespace nix {


/* Allocate a new array of attributes for an attribute set with a specific
capacity. The space is implicitly reserved after the Bindings
structure. */
Bindings * EvalState::allocBindings(size_t capacity)
/* Allocate a new array of attributes for an attribute set with a
specific capacity. The space is implicitly reserved after the
Bindings structure. */
Ptr<Bindings> Bindings::allocBindings(size_t capacity)
{
if (capacity > std::numeric_limits<Bindings::size_t>::max())
if (capacity >= 1UL << Object::miscBytes * 8)
throw Error("attribute set of size %d is too big", capacity);
return new (allocBytes(sizeof(Bindings) + sizeof(Attr) * capacity)) Bindings((Bindings::size_t) capacity);
return gc.alloc<Bindings>(Bindings::wordsFor(capacity), capacity);
}


void EvalState::mkAttrs(Value & v, size_t capacity)
{
if (capacity == 0) {
v = vEmptySet;
return;
v.attrs = emptyBindings;
v.type = tAttrs;
} else {
v.attrs = Bindings::allocBindings(capacity);
v.type = tAttrs;
nrAttrsets++;
nrAttrsInAttrsets += capacity;
}
clearValue(v);
v.type = tAttrs;
v.attrs = allocBindings(capacity);
nrAttrsets++;
nrAttrsInAttrsets += capacity;
}


@@ -37,7 +37,7 @@ void EvalState::mkAttrs(Value & v, size_t capacity)
this attribute. */
Value * EvalState::allocAttr(Value & vAttrs, const Symbol & name)
{
Value * v = allocValue();
auto v = allocValue();
vAttrs.attrs->push_back(Attr(name, v));
return v;
}
29 changes: 23 additions & 6 deletions src/libexpr/attr-set.hh
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@

#include "nixexpr.hh"
#include "symbol-table.hh"
#include "gc.hh"

#include <algorithm>

@@ -30,19 +31,22 @@ struct Attr
by its size and its capacity, the capacity being the number of Attr
elements allocated after this structure, while the size corresponds to
the number of elements already inserted in this structure. */
class Bindings
class Bindings : public Object
{
public:
typedef uint32_t size_t;

private:
size_t size_, capacity_;
// FIXME: eliminate size_. We can just rely on capacity by sorting
// null entries towards the end of the vector.
size_t size_;
Attr attrs[0];

Bindings(size_t capacity) : size_(0), capacity_(capacity) { }
Bindings(size_t capacity) : Object(tBindings, capacity), size_(0) {}
Bindings(const Bindings & bindings) = delete;

public:

size_t size() const { return size_; }

bool empty() const { return !size_; }
@@ -51,7 +55,8 @@ public:

void push_back(const Attr & attr)
{
assert(size_ < capacity_);
assert(size_ < capacity());
gc.assertObject(attr.value);
attrs[size_++] = attr;
}

@@ -73,7 +78,7 @@ public:

void sort();

size_t capacity() { return capacity_; }
size_t capacity() const { return getMisc(); }

/* Returns the attributes in lexicographically sorted order. */
std::vector<const Attr *> lexicographicOrder() const
@@ -88,7 +93,19 @@ public:
return res;
}

friend class EvalState;
size_t words() const
{
return wordsFor(capacity());
}

static size_t wordsFor(size_t capacity)
{
return 2 + 3 * capacity; // FIXME
}

static Ptr<Bindings> allocBindings(size_t capacity);

friend class GC;
};


4 changes: 2 additions & 2 deletions src/libexpr/common-eval-args.cc
Original file line number Diff line number Diff line change
@@ -28,9 +28,9 @@ MixEvalArgs::MixEvalArgs()
.handler([&](std::string s) { searchPath.push_back(s); });
}

Bindings * MixEvalArgs::getAutoArgs(EvalState & state)
Ptr<Bindings> MixEvalArgs::getAutoArgs(EvalState & state)
{
Bindings * res = state.allocBindings(autoArgs.size());
auto res = Bindings::allocBindings(autoArgs.size());
for (auto & i : autoArgs) {
Value * v = state.allocValue();
if (i.second[0] == 'E')
5 changes: 4 additions & 1 deletion src/libexpr/common-eval-args.hh
Original file line number Diff line number Diff line change
@@ -8,11 +8,14 @@ class Store;
class EvalState;
class Bindings;

template<class T>
struct Ptr;

struct MixEvalArgs : virtual Args
{
MixEvalArgs();

Bindings * getAutoArgs(EvalState & state);
Ptr<Bindings> getAutoArgs(EvalState & state);

Strings searchPath;

25 changes: 9 additions & 16 deletions src/libexpr/eval-inline.hh
Original file line number Diff line number Diff line change
@@ -27,21 +27,27 @@ LocalNoInlineNoReturn(void throwTypeError(const char * s, const Value & v, const
void EvalState::forceValue(Value & v, const Pos & pos)
{
if (v.type == tThunk) {
Env * env = v.thunk.env;
// FIXME: this is necessary because some values (like vList2)
// are created non-atomically.
Ptr<Env> env(v.thunk.env);
Expr * expr = v.thunk.expr;
try {
v.type = tBlackhole;
//checkInterrupt();
expr->eval(*this, *env, v);
} catch (...) {
v.type = tThunk;
v.thunk.env = env;
v.thunk.expr = expr;
v.type = tThunk;
throw;
}
}
else if (v.type == tApp)
else if (v.type == tApp) {
// FIXME: idem.
Ptr<Value> left(v.app.left);
Ptr<Value> right(v.app.right);
callFunction(*v.app.left, *v.app.right, v, noPos);
}
else if (v.type == tBlackhole)
throwEvalError("infinite recursion encountered, at %1%", pos);
}
@@ -78,18 +84,5 @@ inline void EvalState::forceList(Value & v, const Pos & pos)
throwTypeError("value is %1% while a list was expected, at %2%", v, pos);
}

/* Note: Various places expect the allocated memory to be zeroed. */
inline void * allocBytes(size_t n)
{
void * p;
#if HAVE_BOEHMGC
p = GC_MALLOC(n);
#else
p = calloc(n, 1);
#endif
if (!p) throw std::bad_alloc();
return p;
}


}
Loading