Avoid linear search for non-locals in the scope code
when resolving variables inside with and eval scopes. Review URL: http://codereview.chromium.org/114024 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1937 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
6d319c7229
commit
70110bc17b
@ -112,7 +112,9 @@ Scope::Scope()
|
||||
locals_(false),
|
||||
temps_(0),
|
||||
params_(0),
|
||||
nonlocals_(0),
|
||||
dynamics_(false),
|
||||
dynamics_local_(false),
|
||||
dynamics_global_(false),
|
||||
unresolved_(0),
|
||||
decls_(0) {
|
||||
}
|
||||
@ -126,7 +128,6 @@ Scope::Scope(Scope* outer_scope, Type type)
|
||||
locals_(),
|
||||
temps_(4),
|
||||
params_(4),
|
||||
nonlocals_(4),
|
||||
unresolved_(16),
|
||||
decls_(4),
|
||||
receiver_(NULL),
|
||||
@ -405,6 +406,14 @@ static void PrintVar(PrettyPrinter* printer, int indent, Variable* var) {
|
||||
}
|
||||
|
||||
|
||||
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 @@ void Scope::Print(int n) {
|
||||
}
|
||||
|
||||
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 @@ void Scope::Print(int n) {
|
||||
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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
return var;
|
||||
}
|
||||
|
||||
@ -617,14 +632,6 @@ void Scope::ResolveVariable(Scope* global_scope,
|
||||
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
|
||||
|
@ -278,7 +278,9 @@ class Scope: public ZoneObject {
|
||||
// parameter list in source order
|
||||
ZoneList<Variable*> params_;
|
||||
// variables that must be looked up dynamically
|
||||
ZoneList<Variable*> nonlocals_;
|
||||
LocalsMap dynamics_;
|
||||
LocalsMap dynamics_local_;
|
||||
LocalsMap dynamics_global_;
|
||||
// unresolved variables referred to from this scope
|
||||
ZoneList<VariableProxy*> unresolved_;
|
||||
// declarations
|
||||
|
Loading…
Reference in New Issue
Block a user