* 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
					
				
					 2 changed files with 25 additions and 35 deletions
				
			
		|  | @ -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 | ||||||
|  | @ -671,10 +671,11 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v) | ||||||
|             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…
	
	Add table
		Add a link
		
	
		Reference in a new issue