Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(284)

Unified Diff: src/parser.cc

Issue 8508052: Static resolution of outer variables in eval code. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/contexts.cc ('k') | src/runtime.cc » ('j') | src/runtime.cc » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/parser.cc
diff --git a/src/parser.cc b/src/parser.cc
index 80abc63b4b204a7e687fb6748498f049bcc067fb..32eaf91f2f1a26c55c4d522a06185f263ffe0fdf 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -735,7 +735,7 @@ FunctionLiteral* Parser::ParseLazy(CompilationInfo* info,
// Parse the function literal.
Scope* scope = NewScope(top_scope_, GLOBAL_SCOPE);
if (!info->closure().is_null()) {
- scope = Scope::DeserializeScopeChain(info, scope);
+ scope = Scope::DeserializeScopeChain(info->closure()->context(), scope);
}
FunctionState function_state(this, scope, isolate());
ASSERT(scope->strict_mode_flag() == kNonStrictMode ||
@@ -1362,6 +1362,8 @@ VariableProxy* Parser::Declare(Handle<String> name,
// enclosing scope.
Scope* declaration_scope = (mode == LET || mode == CONST_HARMONY)
? top_scope_ : top_scope_->DeclarationScope();
+ InitializationFlag init_flag = (fun != NULL || mode == VAR)
+ ? kCreatedInitialized : kNeedsInitialization;
// If a function scope exists, then we can statically declare this
// variable and also set its mode. In any case, a Declaration node
@@ -1380,8 +1382,6 @@ VariableProxy* Parser::Declare(Handle<String> name,
var = declaration_scope->LocalLookup(name);
if (var == NULL) {
// Declare the name.
- InitializationFlag init_flag = (fun != NULL || mode == VAR)
- ? kCreatedInitialized : kNeedsInitialization;
var = declaration_scope->DeclareLocal(name, mode, init_flag);
} else {
// The name was declared in this scope before; check for conflicting
@@ -1444,17 +1444,31 @@ VariableProxy* Parser::Declare(Handle<String> name,
declaration_scope->AddDeclaration(
new(zone()) Declaration(proxy, mode, fun, top_scope_));
- // For global const variables we bind the proxy to a variable.
if ((mode == CONST || mode == CONST_HARMONY) &&
declaration_scope->is_global_scope()) {
+ // For global const variables we bind the proxy to a variable.
ASSERT(resolve); // should be set by all callers
Variable::Kind kind = Variable::NORMAL;
var = new(zone()) Variable(declaration_scope,
name,
- CONST,
+ mode,
true,
kind,
kNeedsInitialization);
+ } else if (declaration_scope->is_eval_scope() &&
+ !declaration_scope->is_strict_mode()) {
+ // For variable declarations in a non-strict eval scope the proxy is bound
+ // to a lookup variable to force a dynamic declaration using the
+ // DeclareContextSlot runtime function.
+ Variable::Kind kind = Variable::NORMAL;
+ var = new(zone()) Variable(declaration_scope,
+ name,
+ mode,
+ true,
+ kind,
+ init_flag);
+ var->AllocateTo(Variable::LOOKUP, -1);
+ resolve = true;
}
// If requested and we have a local variable, bind the proxy to the variable
@@ -1901,22 +1915,30 @@ Block* Parser::ParseVariableDeclarations(
}
block->AddStatement(new(zone()) ExpressionStatement(initialize));
+ } else if (needs_init) {
+ // Constant initializations always assign to the declared constant which
+ // is always at the function scope level. This is only relevant for
+ // dynamically looked-up variables and constants (the start context for
+ // constant lookups is always the function context, while it is the top
+ // context for var declared variables). Sigh...
+ // For 'let' and 'const' declared variables in harmony mode the
+ // initialization also always assigns to the declared variable.
+ ASSERT(proxy != NULL);
+ ASSERT(proxy->var() != NULL);
+ ASSERT(value != NULL);
+ Assignment* assignment =
+ new(zone()) Assignment(isolate(), init_op, proxy, value, position);
+ block->AddStatement(new(zone()) ExpressionStatement(assignment));
+ value = NULL;
}
// Add an assignment node to the initialization statement block if we still
- // have a pending initialization value. We must distinguish between
- // different kinds of declarations: 'var' initializations are simply
- // assignments (with all the consequences if they are inside a 'with'
- // statement - they may change a 'with' object property). Constant
- // initializations always assign to the declared constant which is
- // always at the function scope level. This is only relevant for
- // dynamically looked-up variables and constants (the start context
- // for constant lookups is always the function context, while it is
- // the top context for var declared variables). Sigh...
- // For 'let' and 'const' declared variables in harmony mode the
- // initialization is in the same scope as the declaration. Thus dynamic
- // lookups are unnecessary even if the block scope is inside a with.
+ // have a pending initialization value.
if (value != NULL) {
+ ASSERT(mode == VAR);
+ // 'var' initializations are simply assignments (with all the consequences
+ // if they are inside a 'with' statement - they may change a 'with' object
+ // property).
VariableProxy* proxy = initialization_scope->NewUnresolved(name);
Assignment* assignment =
new(zone()) Assignment(isolate(), init_op, proxy, value, position);
« no previous file with comments | « src/contexts.cc ('k') | src/runtime.cc » ('j') | src/runtime.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698