forked from lix-project/lix
* In environments, store pointers to values rather than values. This
improves GC effectiveness a bit more (because a live value doesn't keep other values in the environment plus the parent environments alive), and removes the need for copy nodes.
This commit is contained in:
parent
cf7e645a48
commit
4dee289550
|
@ -72,7 +72,6 @@ std::ostream & operator << (std::ostream & str, const Value & v)
|
||||||
break;
|
break;
|
||||||
case tThunk:
|
case tThunk:
|
||||||
case tApp:
|
case tApp:
|
||||||
case tCopy:
|
|
||||||
str << "<CODE>";
|
str << "<CODE>";
|
||||||
break;
|
break;
|
||||||
case tLambda:
|
case tLambda:
|
||||||
|
@ -104,7 +103,6 @@ string showType(const Value & v)
|
||||||
case tThunk: return "a thunk";
|
case tThunk: return "a thunk";
|
||||||
case tApp: return "a function application";
|
case tApp: return "a function application";
|
||||||
case tLambda: return "a function";
|
case tLambda: return "a function";
|
||||||
case tCopy: return "a copy";
|
|
||||||
case tBlackhole: return "a black hole";
|
case tBlackhole: return "a black hole";
|
||||||
case tPrimOp: return "a built-in function";
|
case tPrimOp: return "a built-in function";
|
||||||
case tPrimOpApp: return "a partially applied built-in function";
|
case tPrimOpApp: return "a partially applied built-in function";
|
||||||
|
@ -148,9 +146,9 @@ void EvalState::addConstant(const string & name, Value & v)
|
||||||
Value * v2 = allocValue();
|
Value * v2 = allocValue();
|
||||||
*v2 = v;
|
*v2 = v;
|
||||||
staticBaseEnv.vars[symbols.create(name)] = baseEnvDispl;
|
staticBaseEnv.vars[symbols.create(name)] = baseEnvDispl;
|
||||||
baseEnv.values[baseEnvDispl++] = v;
|
baseEnv.values[baseEnvDispl++] = v2;
|
||||||
string name2 = string(name, 0, 2) == "__" ? string(name, 2) : name;
|
string name2 = string(name, 0, 2) == "__" ? string(name, 2) : name;
|
||||||
(*baseEnv.values[0].attrs)[symbols.create(name2)].value = v2;
|
(*baseEnv.values[0]->attrs)[symbols.create(name2)].value = v2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -164,8 +162,8 @@ void EvalState::addPrimOp(const string & name,
|
||||||
v->primOp.fun = primOp;
|
v->primOp.fun = primOp;
|
||||||
v->primOp.name = GC_STRDUP(name2.c_str());
|
v->primOp.name = GC_STRDUP(name2.c_str());
|
||||||
staticBaseEnv.vars[symbols.create(name)] = baseEnvDispl;
|
staticBaseEnv.vars[symbols.create(name)] = baseEnvDispl;
|
||||||
baseEnv.values[baseEnvDispl++] = *v;
|
baseEnv.values[baseEnvDispl++] = v;
|
||||||
(*baseEnv.values[0].attrs)[symbols.create(name2)].value = v;
|
(*baseEnv.values[0]->attrs)[symbols.create(name2)].value = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -265,15 +263,15 @@ Value * EvalState::lookupVar(Env * env, const VarRef & var)
|
||||||
|
|
||||||
if (var.fromWith) {
|
if (var.fromWith) {
|
||||||
while (1) {
|
while (1) {
|
||||||
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())
|
||||||
return j->second.value;
|
return j->second.value;
|
||||||
if (env->prevWith == 0)
|
if (env->prevWith == 0)
|
||||||
throwEvalError("undefined variable `%1%'", var.name);
|
throwEvalError("undefined variable `%1%'", var.name);
|
||||||
for (unsigned int l = env->prevWith; l; --l, env = env->up) ;
|
for (unsigned int l = env->prevWith; l; --l, env = env->up) ;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
return &env->values[var.displ];
|
return env->values[var.displ];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -295,7 +293,7 @@ Env & EvalState::allocEnv(unsigned int size)
|
||||||
{
|
{
|
||||||
nrEnvs++;
|
nrEnvs++;
|
||||||
nrValuesInEnvs += size;
|
nrValuesInEnvs += size;
|
||||||
Env * env = (Env *) GC_MALLOC(sizeof(Env) + size * sizeof(Value));
|
Env * env = (Env *) GC_MALLOC(sizeof(Env) + size * sizeof(Value *));
|
||||||
return *env;
|
return *env;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -465,7 +463,7 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
|
||||||
nix::Attr & a = (*v.attrs)[i->first];
|
nix::Attr & a = (*v.attrs)[i->first];
|
||||||
a.value = state.allocValue();
|
a.value = state.allocValue();
|
||||||
mkThunk(*a.value, env2, i->second.first);
|
mkThunk(*a.value, env2, i->second.first);
|
||||||
mkCopy(env2.values[displ++], *a.value);
|
env2.values[displ++] = a.value;
|
||||||
a.pos = &i->second.second;
|
a.pos = &i->second.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -475,7 +473,7 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
|
||||||
nix::Attr & a = (*v.attrs)[i->first.name];
|
nix::Attr & a = (*v.attrs)[i->first.name];
|
||||||
Value * v2 = state.lookupVar(&env, i->first);
|
Value * v2 = state.lookupVar(&env, i->first);
|
||||||
a.value = v2;
|
a.value = v2;
|
||||||
mkCopy(env2.values[displ++], *v2);
|
env2.values[displ++] = v2;
|
||||||
a.pos = &i->second;
|
a.pos = &i->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -493,7 +491,7 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
|
||||||
foreach (Bindings::iterator, i, *overrides->second.value->attrs) {
|
foreach (Bindings::iterator, i, *overrides->second.value->attrs) {
|
||||||
nix::Attr & a = (*v.attrs)[i->first];
|
nix::Attr & a = (*v.attrs)[i->first];
|
||||||
if (a.value)
|
if (a.value)
|
||||||
mkCopy(env2.values[displs[i->first]], *i->second.value);
|
env2.values[displs[i->first]] = i->second.value;
|
||||||
a = i->second;
|
a = i->second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -527,13 +525,15 @@ void ExprLet::eval(EvalState & state, Env & env, Value & v)
|
||||||
|
|
||||||
/* The recursive attributes are evaluated in the new
|
/* The recursive attributes are evaluated in the new
|
||||||
environment. */
|
environment. */
|
||||||
foreach (ExprAttrs::Attrs::iterator, i, attrs->attrs)
|
foreach (ExprAttrs::Attrs::iterator, i, attrs->attrs) {
|
||||||
mkThunk(env2.values[displ++], env2, i->second.first);
|
env2.values[displ] = state.allocValue();
|
||||||
|
mkThunk(*env2.values[displ++], env2, i->second.first);
|
||||||
|
}
|
||||||
|
|
||||||
/* The inherited attributes, on the other hand, are evaluated in
|
/* The inherited attributes, on the other hand, are evaluated in
|
||||||
the original environment. */
|
the original environment. */
|
||||||
foreach (list<ExprAttrs::Inherited>::iterator, i, attrs->inherited)
|
foreach (list<ExprAttrs::Inherited>::iterator, i, attrs->inherited)
|
||||||
mkCopy(env2.values[displ++], *state.lookupVar(&env, i->first));
|
env2.values[displ++] = state.lookupVar(&env, i->first);
|
||||||
|
|
||||||
state.eval(env2, body, v);
|
state.eval(env2, body, v);
|
||||||
}
|
}
|
||||||
|
@ -654,13 +654,13 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v)
|
||||||
unsigned int displ = 0;
|
unsigned int displ = 0;
|
||||||
|
|
||||||
if (!fun.lambda.fun->matchAttrs)
|
if (!fun.lambda.fun->matchAttrs)
|
||||||
env2.values[displ++] = arg;
|
env2.values[displ++] = &arg;
|
||||||
|
|
||||||
else {
|
else {
|
||||||
forceAttrs(arg);
|
forceAttrs(arg);
|
||||||
|
|
||||||
if (!fun.lambda.fun->arg.empty())
|
if (!fun.lambda.fun->arg.empty())
|
||||||
env2.values[displ++] = arg;
|
env2.values[displ++] = &arg;
|
||||||
|
|
||||||
/* For each formal argument, get the actual argument. If
|
/* For each formal argument, get the actual argument. If
|
||||||
there is no matching actual argument but the formal
|
there is no matching actual argument but the formal
|
||||||
|
@ -670,11 +670,12 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v)
|
||||||
Bindings::iterator j = arg.attrs->find(i->name);
|
Bindings::iterator j = arg.attrs->find(i->name);
|
||||||
if (j == arg.attrs->end()) {
|
if (j == arg.attrs->end()) {
|
||||||
if (!i->def) throwTypeError("function at %1% called without required argument `%2%'",
|
if (!i->def) throwTypeError("function at %1% called without required argument `%2%'",
|
||||||
fun.lambda.fun->pos, i->name);
|
fun.lambda.fun->pos, i->name);
|
||||||
mkThunk(env2.values[displ++], env2, i->def);
|
env2.values[displ] = allocValue();
|
||||||
|
mkThunk(*env2.values[displ++], env2, i->def);
|
||||||
} else {
|
} else {
|
||||||
attrsUsed++;
|
attrsUsed++;
|
||||||
mkCopy(env2.values[displ++], *j->second.value);
|
env2.values[displ++] = j->second.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -725,7 +726,8 @@ void ExprWith::eval(EvalState & state, Env & env, Value & v)
|
||||||
env2.up = &env;
|
env2.up = &env;
|
||||||
env2.prevWith = prevWith;
|
env2.prevWith = prevWith;
|
||||||
|
|
||||||
state.evalAttrs(env, attrs, env2.values[0]);
|
env2.values[0] = state.allocValue();
|
||||||
|
state.evalAttrs(env, attrs, *env2.values[0]);
|
||||||
|
|
||||||
state.eval(env2, body, v);
|
state.eval(env2, body, v);
|
||||||
}
|
}
|
||||||
|
@ -864,10 +866,6 @@ void EvalState::forceValue(Value & v)
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (v.type == tCopy) {
|
|
||||||
forceValue(*v.val);
|
|
||||||
v = *v.val;
|
|
||||||
}
|
|
||||||
else if (v.type == tApp)
|
else if (v.type == tApp)
|
||||||
callFunction(*v.app.left, *v.app.right, v);
|
callFunction(*v.app.left, *v.app.right, v);
|
||||||
else if (v.type == tBlackhole)
|
else if (v.type == tBlackhole)
|
||||||
|
|
|
@ -38,7 +38,6 @@ typedef enum {
|
||||||
tThunk,
|
tThunk,
|
||||||
tApp,
|
tApp,
|
||||||
tLambda,
|
tLambda,
|
||||||
tCopy,
|
|
||||||
tBlackhole,
|
tBlackhole,
|
||||||
tPrimOp,
|
tPrimOp,
|
||||||
tPrimOpApp,
|
tPrimOpApp,
|
||||||
|
@ -116,7 +115,7 @@ struct Env
|
||||||
{
|
{
|
||||||
Env * up;
|
Env * up;
|
||||||
unsigned int prevWith; // nr of levels up to next `with' environment
|
unsigned int prevWith; // nr of levels up to next `with' environment
|
||||||
Value values[0];
|
Value * values[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -150,13 +149,6 @@ static inline void mkThunk(Value & v, Env & env, Expr * expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline void mkCopy(Value & v, Value & src)
|
|
||||||
{
|
|
||||||
v.type = tCopy;
|
|
||||||
v.val = &src;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline void mkApp(Value & v, Value & left, Value & right)
|
static inline void mkApp(Value & v, Value & left, Value & right)
|
||||||
{
|
{
|
||||||
v.type = tApp;
|
v.type = tApp;
|
||||||
|
|
Loading…
Reference in a new issue