Index: src/scopes.cc |
=================================================================== |
--- src/scopes.cc (revision 1926) |
+++ src/scopes.cc (working copy) |
@@ -112,7 +112,9 @@ |
locals_(false), |
temps_(0), |
params_(0), |
- nonlocals_(0), |
+ dynamics_(false), |
+ dynamics_local_(false), |
+ dynamics_global_(false), |
unresolved_(0), |
decls_(0) { |
} |
@@ -126,7 +128,6 @@ |
locals_(), |
temps_(4), |
params_(4), |
- nonlocals_(4), |
unresolved_(16), |
decls_(4), |
receiver_(NULL), |
@@ -405,6 +406,14 @@ |
} |
+static void PrintMap(PrettyPrinter* printer, int indent, LocalsMap* map) { |
+ for (LocalsMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) { |
+ Variable* var = reinterpret_cast<Variable*>(p->value); |
+ PrintVar(printer, indent, var); |
+ } |
+} |
+ |
+ |
void Scope::Print(int n) { |
int n0 = (n > 0 ? n : 0); |
int n1 = n0 + 2; // indentation |
@@ -465,14 +474,12 @@ |
} |
Indent(n1, "// local vars\n"); |
- for (LocalsMap::Entry* p = locals_.Start(); p != NULL; p = locals_.Next(p)) { |
- Variable* var = reinterpret_cast<Variable*>(p->value); |
- PrintVar(&printer, n1, var); |
- } |
+ PrintMap(&printer, n1, &locals_); |
- Indent(n1, "// nonlocal vars\n"); |
- for (int i = 0; i < nonlocals_.length(); i++) |
- PrintVar(&printer, n1, nonlocals_[i]); |
+ Indent(n1, "// dynamic vars\n"); |
+ PrintMap(&printer, n1, &dynamics_); |
+ PrintMap(&printer, n1, &dynamics_local_); |
+ PrintMap(&printer, n1, &dynamics_global_); |
// Print inner scopes (disable by providing negative n). |
if (n >= 0) { |
@@ -490,20 +497,28 @@ |
Variable* Scope::NonLocal(Handle<String> name, Variable::Mode mode) { |
// Space optimization: reuse existing non-local with the same name |
// and mode. |
- for (int i = 0; i < nonlocals_.length(); i++) { |
- Variable* var = nonlocals_[i]; |
- if (var->name().is_identical_to(name) && var->mode() == mode) { |
- return var; |
- } |
+ LocalsMap* map = NULL; |
+ switch (mode) { |
+ case Variable::DYNAMIC: |
+ map = &dynamics_; |
+ break; |
+ case Variable::DYNAMIC_LOCAL: |
+ map = &dynamics_local_; |
+ break; |
+ case Variable::DYNAMIC_GLOBAL: |
+ map = &dynamics_global_; |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ break; |
} |
- |
- // Otherwise create a new non-local and add it to the list. |
- Variable* var = new Variable(NULL, name, mode, true, false); |
- nonlocals_.Add(var); |
- |
- // Allocate it by giving it a dynamic lookup. |
- var->rewrite_ = new Slot(var, Slot::LOOKUP, -1); |
- |
+ Variable* var = map->Lookup(name); |
+ if (var == NULL) { |
+ // Declare a new non-local. |
+ var = map->Declare(NULL, name, mode, true, false); |
+ // Allocate it by giving it a dynamic lookup. |
+ var->rewrite_ = new Slot(var, Slot::LOOKUP, -1); |
+ } |
return var; |
} |
@@ -617,14 +632,6 @@ |
ASSERT(global_scope != NULL); |
var = new Variable(global_scope, proxy->name(), |
Variable::DYNAMIC, true, false); |
- // Ideally we simply rewrite these variables into property |
- // accesses. Unfortunately, we cannot do this here at the |
- // moment because then we can't differentiate between |
- // global variable ('x') and global property ('this.x') access. |
- // If 'x' doesn't exist, the former leads to an error, while the |
- // latter returns undefined. Sigh... |
- // var->rewrite_ = new Property(new Literal(env_->global()), |
- // new Literal(proxy->name())); |
} else if (scope_inside_with_) { |
// If we are inside a with statement we give up and look up |