1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-15 23:12:44 +01:00

Remove a word from Env

This commit is contained in:
Eelco Dolstra 2019-04-23 01:11:50 +02:00
parent ae5b76a5a4
commit e392ff53e9
4 changed files with 55 additions and 31 deletions

View file

@ -523,8 +523,6 @@ inline Value * EvalState::lookupVar(Env * env, const ExprVar & var, bool noEval)
{ {
for (size_t l = var.level; l; --l, env = env->up) ; for (size_t l = var.level; l; --l, env = env->up) ;
assert(((Object *) env)->type == tEnv);
if (!var.fromWith) { if (!var.fromWith) {
auto v = env->values[var.displ]; auto v = env->values[var.displ];
if (v) gc.assertObject(v); if (v) gc.assertObject(v);
@ -532,12 +530,12 @@ inline Value * EvalState::lookupVar(Env * env, const ExprVar & var, bool noEval)
} }
while (1) { while (1) {
if (env->type == Env::HasWithExpr) { if (env->type == tWithExprEnv) {
if (noEval) return 0; if (noEval) return 0;
auto v = allocValue(); auto v = allocValue();
evalAttrs(*env->up, (Expr *) env->values[0], *v); evalAttrs(*env->up, (Expr *) env->values[0], *v);
env->values[0] = v; env->values[0] = v;
env->type = Env::HasWithAttrs; env->type = tWithAttrsEnv;
} }
Bindings::iterator j = env->values[0]->attrs->find(var.name); Bindings::iterator j = env->values[0]->attrs->find(var.name);
if (j != env->values[0]->attrs->end()) { if (j != env->values[0]->attrs->end()) {
@ -545,9 +543,9 @@ inline Value * EvalState::lookupVar(Env * env, const ExprVar & var, bool noEval)
gc.assertObject(j->value); gc.assertObject(j->value);
return j->value; return j->value;
} }
if (!env->prevWith) if (!env->getPrevWith())
throwUndefinedVarError("undefined variable '%1%' at %2%", var.name, var.pos); throwUndefinedVarError("undefined variable '%1%' at %2%", var.name, var.pos);
for (size_t l = env->prevWith; l; --l, env = env->up) ; for (size_t l = env->getPrevWith(); l; --l, env = env->up) ;
} }
} }
@ -559,15 +557,11 @@ Ptr<Value> EvalState::allocValue()
} }
Ptr<Env> EvalState::allocEnv(size_t size) Ptr<Env> EvalState::allocEnv(size_t size, size_t prevWith, Tag type)
{ {
if (size > std::numeric_limits<decltype(Env::size)>::max()) // FIXME
throw Error("environment size %d is too big", size);
nrEnvs++; nrEnvs++;
nrValuesInEnvs += size; nrValuesInEnvs += size;
return gc.alloc<Env>(Env::wordsFor(size), type, size, prevWith);
return gc.alloc<Env>(Env::wordsFor(size), size);
} }
@ -1181,12 +1175,9 @@ void EvalState::autoCallFunction(Bindings & args, Value & fun, Value & res)
void ExprWith::eval(EvalState & state, Env & env, Value & v) void ExprWith::eval(EvalState & state, Env & env, Value & v)
{ {
auto env2 = state.allocEnv(1); auto env2 = state.allocEnv(1, prevWith, tWithExprEnv);
env2->up = &env; env2->up = &env;
env2->prevWith = prevWith;
env2->type = Env::HasWithExpr;
env2->values[0] = (Value *) attrs; env2->values[0] = (Value *) attrs;
body->eval(state, env2, v); body->eval(state, env2, v);
} }
@ -1880,10 +1871,10 @@ size_t valueSize(Value & v)
if (seen.find(&env) != seen.end()) return 0; if (seen.find(&env) != seen.end()) return 0;
seen.insert(&env); seen.insert(&env);
size_t sz = sizeof(Env) + sizeof(Value *) * env.size; size_t sz = sizeof(Env) + sizeof(Value *) * env.getSize();
if (env.type != Env::HasWithExpr) if (env.type != tWithExprEnv)
for (size_t i = 0; i < env.size; ++i) for (size_t i = 0; i < env.getSize(); ++i)
if (env.values[i]) if (env.values[i])
sz += doValue(*env.values[i]); sz += doValue(*env.values[i]);

View file

@ -36,16 +36,23 @@ struct PrimOp
struct Env : Object struct Env : Object
{ {
Env * up; Env * up;
// FIXME: use misc field
unsigned short size; // used by valueSize
unsigned short prevWith:14; // nr of levels up to next `with' environment
enum { Plain = 0, HasWithExpr, HasWithAttrs } type:2; // FIXME: fold into type?
Value * values[0]; Value * values[0];
private: private:
Env(unsigned short size) : Object(tEnv, 0), size(size) { constexpr static size_t maxSize = 1 << 16;
for (auto i = 0; i < size; i++) constexpr static size_t maxPrevWith = 1 << 10;
Env(Tag type, size_t size, size_t prevWith)
: Object(type, size | (prevWith << 16))
{
if (size >= maxSize)
throw Error("environment size %d is too big", size);
if (prevWith >= maxPrevWith)
throw Error("too many nesting levels");
for (size_t i = 0; i < size; i++)
values[i] = nullptr; values[i] = nullptr;
} }
@ -53,14 +60,24 @@ private:
public: public:
unsigned short getPrevWith() const
{
return getMisc() >> 16;
}
unsigned short getSize() const
{
return getMisc() & 0xffff;
}
Size words() const Size words() const
{ {
return wordsFor(size); return wordsFor(getSize());
} }
static Size wordsFor(unsigned short size) static Size wordsFor(unsigned short size)
{ {
return 3 + size; // FIXME return 2 + size;
} }
}; };
@ -276,7 +293,7 @@ public:
/* Allocation primitives. */ /* Allocation primitives. */
Ptr<Value> allocValue(); Ptr<Value> allocValue();
Ptr<Env> allocEnv(size_t size); Ptr<Env> allocEnv(size_t size, size_t prevWith = 0, Tag type = tEnv);
// Note: the resulting Value is only reachable as long as vAttrs // Note: the resulting Value is only reachable as long as vAttrs
// is reachable. // is reachable.

View file

@ -82,12 +82,24 @@ void GC::gc()
case tEnv: { case tEnv: {
auto obj2 = (Env *) obj; auto obj2 = (Env *) obj;
push(obj2->up); push(obj2->up);
if (obj2->type != Env::HasWithExpr) for (auto i = obj2->values; i < obj2->values + obj2->getSize(); ++i)
for (auto i = obj2->values; i < obj2->values + obj2->size; ++i)
push(*i); push(*i);
break; break;
} }
case tWithExprEnv: {
auto obj2 = (Env *) obj;
push(obj2->up);
break;
}
case tWithAttrsEnv: {
auto obj2 = (Env *) obj;
push(obj2->up);
push(obj2->values[0]);
break;
}
case tInt: case tInt:
case tBool: case tBool:
case tNull: case tNull:
@ -229,6 +241,8 @@ std::pair<Size, Size> GC::Arena::freeUnmarked()
objSize = ((PtrList<Value> *) obj)->words(); objSize = ((PtrList<Value> *) obj)->words();
break; break;
case tEnv: case tEnv:
case tWithExprEnv:
case tWithAttrsEnv:
objSize = ((Env *) obj)->words(); objSize = ((Env *) obj)->words();
break; break;
default: default:

View file

@ -18,6 +18,8 @@ enum Tag {
tBindings, tBindings,
tValueList, tValueList,
tEnv, tEnv,
tWithExprEnv,
tWithAttrsEnv,
// Value tags // Value tags
tInt, tInt,