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

Unified Diff: src/scopes.cc

Issue 345573002: Infer whether a variable is assigned (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: A few more tests Created 6 years, 6 months 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/scopes.h ('k') | src/variables.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/scopes.cc
diff --git a/src/scopes.cc b/src/scopes.cc
index 497f7940adfb3e42963ba21eb0f58b70adae6b5a..a756b50c0e1bfc063017fef17bfb75ffb6d9e244 100644
--- a/src/scopes.cc
+++ b/src/scopes.cc
@@ -170,6 +170,7 @@ void Scope::SetDefaults(ScopeType scope_type,
strict_mode_ = outer_scope != NULL ? outer_scope->strict_mode_ : SLOPPY;
outer_scope_calls_sloppy_eval_ = false;
inner_scope_calls_eval_ = false;
+ inner_scope_contains_with_ = false;
force_eager_compilation_ = false;
force_context_allocation_ = (outer_scope != NULL && !is_function_scope())
? outer_scope->has_forced_context_allocation() : false;
@@ -194,6 +195,7 @@ Scope* Scope::DeserializeScopeChain(Context* context, Scope* global_scope,
Scope* current_scope = NULL;
Scope* innermost_scope = NULL;
bool contains_with = false;
+ bool inner_contains_with = false;
while (!context->IsNativeContext()) {
if (context->IsWithContext()) {
Scope* with_scope = new(zone) Scope(current_scope,
@@ -236,7 +238,11 @@ Scope* Scope::DeserializeScopeChain(Context* context, Scope* global_scope,
current_scope = new(zone) Scope(
current_scope, Handle<String>(name), zone);
}
- if (contains_with) current_scope->RecordWithStatement();
+ if (inner_contains_with) current_scope->inner_scope_contains_with_ = true;
+ if (contains_with) {
+ current_scope->RecordWithStatement();
+ inner_contains_with = true;
+ }
if (innermost_scope == NULL) innermost_scope = current_scope;
// Forget about a with when we move to a context for a different function.
@@ -806,9 +812,15 @@ static void PrintVar(int indent, Variable* var) {
PrintName(var->name());
PrintF("; // ");
PrintLocation(var);
+ bool comma = !var->IsUnallocated();
if (var->has_forced_context_allocation()) {
- if (!var->IsUnallocated()) PrintF(", ");
+ if (comma) PrintF(", ");
PrintF("forced context allocation");
+ comma = true;
+ }
+ if (var->is_assigned_in_inner_function()) {
+ if (comma) PrintF(", ");
+ PrintF("inner assignment");
}
PrintF("\n");
}
@@ -862,6 +874,9 @@ void Scope::Print(int n) {
}
if (scope_inside_with_) Indent(n1, "// scope inside 'with'\n");
if (scope_contains_with_) Indent(n1, "// scope contains 'with'\n");
+ if (inner_scope_contains_with_) {
+ Indent(n1, "// inner scope contains 'with'\n");
+ }
if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n");
if (outer_scope_calls_sloppy_eval_) {
Indent(n1, "// outer scope calls 'eval' in sloppy context\n");
@@ -938,7 +953,7 @@ Variable* Scope::NonLocal(Handle<String> name, VariableMode mode) {
}
-Variable* Scope::LookupRecursive(Handle<String> name,
+Variable* Scope::LookupRecursive(VariableProxy* proxy,
BindingKind* binding_kind,
AstNodeFactory<AstNullVisitor>* factory) {
ASSERT(binding_kind != NULL);
@@ -950,7 +965,7 @@ Variable* Scope::LookupRecursive(Handle<String> name,
}
// Try to find the variable in this scope.
- Variable* var = LookupLocal(name);
+ Variable* var = LookupLocal(proxy->name());
// We found a variable and we are done. (Even if there is an 'eval' in
// this scope which introduces the same variable again, the resulting
@@ -964,11 +979,11 @@ Variable* Scope::LookupRecursive(Handle<String> name,
// if any. We can do this for all scopes, since the function variable is
// only present - if at all - for function scopes.
*binding_kind = UNBOUND;
- var = LookupFunctionVar(name, factory);
+ var = LookupFunctionVar(proxy->name(), factory);
if (var != NULL) {
*binding_kind = BOUND;
} else if (outer_scope_ != NULL) {
- var = outer_scope_->LookupRecursive(name, binding_kind, factory);
+ var = outer_scope_->LookupRecursive(proxy, binding_kind, factory);
if (*binding_kind == BOUND && (is_function_scope() || is_with_scope())) {
var->ForceContextAllocation();
}
@@ -984,6 +999,7 @@ Variable* Scope::LookupRecursive(Handle<String> name,
// the associated variable has to be marked as potentially being accessed
// from inside of an inner with scope (the property may not be in the 'with'
// object).
+ if (proxy->is_assigned()) var->set_maybe_assigned();
*binding_kind = DYNAMIC_LOOKUP;
return NULL;
} else if (calls_sloppy_eval()) {
@@ -1012,7 +1028,7 @@ bool Scope::ResolveVariable(CompilationInfo* info,
// Otherwise, try to resolve the variable.
BindingKind binding_kind;
- Variable* var = LookupRecursive(proxy->name(), &binding_kind, factory);
+ Variable* var = LookupRecursive(proxy, &binding_kind, factory);
switch (binding_kind) {
case BOUND:
// We found a variable binding.
@@ -1051,9 +1067,10 @@ bool Scope::ResolveVariable(CompilationInfo* info,
}
ASSERT(var != NULL);
+ if (proxy->is_assigned()) var->set_maybe_assigned();
if (FLAG_harmony_scoping && strict_mode() == STRICT &&
- var->is_const_mode() && proxy->IsLValue()) {
+ var->is_const_mode() && proxy->is_assigned()) {
// Assignment to const. Throw a syntax error.
MessageLocation location(
info->script(), proxy->position(), proxy->position());
@@ -1125,7 +1142,7 @@ bool Scope::ResolveVariablesRecursively(
}
-bool Scope::PropagateScopeInfo(bool outer_scope_calls_sloppy_eval ) {
+void Scope::PropagateScopeInfo(bool outer_scope_calls_sloppy_eval ) {
if (outer_scope_calls_sloppy_eval) {
outer_scope_calls_sloppy_eval_ = true;
}
@@ -1133,16 +1150,18 @@ bool Scope::PropagateScopeInfo(bool outer_scope_calls_sloppy_eval ) {
bool calls_sloppy_eval =
this->calls_sloppy_eval() || outer_scope_calls_sloppy_eval_;
for (int i = 0; i < inner_scopes_.length(); i++) {
- Scope* inner_scope = inner_scopes_[i];
- if (inner_scope->PropagateScopeInfo(calls_sloppy_eval)) {
+ Scope* inner = inner_scopes_[i];
+ inner->PropagateScopeInfo(calls_sloppy_eval);
+ if (inner->scope_calls_eval_ || inner->inner_scope_calls_eval_) {
inner_scope_calls_eval_ = true;
}
- if (inner_scope->force_eager_compilation_) {
+ if (inner->scope_contains_with_ || inner->inner_scope_contains_with_) {
+ inner_scope_contains_with_ = true;
+ }
+ if (inner->force_eager_compilation_) {
force_eager_compilation_ = true;
}
}
-
- return scope_calls_eval_ || inner_scope_calls_eval_;
}
@@ -1159,7 +1178,8 @@ bool Scope::MustAllocate(Variable* var) {
is_block_scope() ||
is_module_scope() ||
is_global_scope())) {
- var->set_is_used(true);
+ var->set_is_used();
+ if (scope_calls_eval_ || inner_scope_calls_eval_) var->set_maybe_assigned();
}
// Global variables do not need to be allocated.
return !var->IsGlobalObjectProperty() && var->is_used();
« no previous file with comments | « src/scopes.h ('k') | src/variables.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698