| 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
|
|
|