Commit 70110bc1 authored by kasperl@chromium.org's avatar kasperl@chromium.org

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
parent 6d319c72
...@@ -112,7 +112,9 @@ Scope::Scope() ...@@ -112,7 +112,9 @@ Scope::Scope()
locals_(false), locals_(false),
temps_(0), temps_(0),
params_(0), params_(0),
nonlocals_(0), dynamics_(false),
dynamics_local_(false),
dynamics_global_(false),
unresolved_(0), unresolved_(0),
decls_(0) { decls_(0) {
} }
...@@ -126,7 +128,6 @@ Scope::Scope(Scope* outer_scope, Type type) ...@@ -126,7 +128,6 @@ Scope::Scope(Scope* outer_scope, Type type)
locals_(), locals_(),
temps_(4), temps_(4),
params_(4), params_(4),
nonlocals_(4),
unresolved_(16), unresolved_(16),
decls_(4), decls_(4),
receiver_(NULL), receiver_(NULL),
...@@ -405,6 +406,14 @@ static void PrintVar(PrettyPrinter* printer, int indent, Variable* var) { ...@@ -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) { void Scope::Print(int n) {
int n0 = (n > 0 ? n : 0); int n0 = (n > 0 ? n : 0);
int n1 = n0 + 2; // indentation int n1 = n0 + 2; // indentation
...@@ -465,14 +474,12 @@ void Scope::Print(int n) { ...@@ -465,14 +474,12 @@ void Scope::Print(int n) {
} }
Indent(n1, "// local vars\n"); Indent(n1, "// local vars\n");
for (LocalsMap::Entry* p = locals_.Start(); p != NULL; p = locals_.Next(p)) { PrintMap(&printer, n1, &locals_);
Variable* var = reinterpret_cast<Variable*>(p->value);
PrintVar(&printer, n1, var);
}
Indent(n1, "// nonlocal vars\n"); Indent(n1, "// dynamic vars\n");
for (int i = 0; i < nonlocals_.length(); i++) PrintMap(&printer, n1, &dynamics_);
PrintVar(&printer, n1, nonlocals_[i]); PrintMap(&printer, n1, &dynamics_local_);
PrintMap(&printer, n1, &dynamics_global_);
// Print inner scopes (disable by providing negative n). // Print inner scopes (disable by providing negative n).
if (n >= 0) { if (n >= 0) {
...@@ -490,20 +497,28 @@ void Scope::Print(int n) { ...@@ -490,20 +497,28 @@ void Scope::Print(int n) {
Variable* Scope::NonLocal(Handle<String> name, Variable::Mode mode) { Variable* Scope::NonLocal(Handle<String> name, Variable::Mode mode) {
// Space optimization: reuse existing non-local with the same name // Space optimization: reuse existing non-local with the same name
// and mode. // and mode.
for (int i = 0; i < nonlocals_.length(); i++) { LocalsMap* map = NULL;
Variable* var = nonlocals_[i]; switch (mode) {
if (var->name().is_identical_to(name) && var->mode() == mode) { case Variable::DYNAMIC:
return var; 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; return var;
} }
...@@ -617,14 +632,6 @@ void Scope::ResolveVariable(Scope* global_scope, ...@@ -617,14 +632,6 @@ void Scope::ResolveVariable(Scope* global_scope,
ASSERT(global_scope != NULL); ASSERT(global_scope != NULL);
var = new Variable(global_scope, proxy->name(), var = new Variable(global_scope, proxy->name(),
Variable::DYNAMIC, true, false); 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_) { } else if (scope_inside_with_) {
// If we are inside a with statement we give up and look up // If we are inside a with statement we give up and look up
......
...@@ -278,7 +278,9 @@ class Scope: public ZoneObject { ...@@ -278,7 +278,9 @@ class Scope: public ZoneObject {
// parameter list in source order // parameter list in source order
ZoneList<Variable*> params_; ZoneList<Variable*> params_;
// variables that must be looked up dynamically // 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 // unresolved variables referred to from this scope
ZoneList<VariableProxy*> unresolved_; ZoneList<VariableProxy*> unresolved_;
// declarations // declarations
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment