Reviewers: Michael Starzinger,
Description:
[es6] Make sure temporaries are not allocated in block scope
While at it, remove the notion of INTERNAL variables.
[email protected]
BUG=cr:512574
Please review this at https://codereview.chromium.org/1250513004/
Base URL: https://chromium.googlesource.com/v8/v8.git@master
Affected files (+39, -47 lines):
M src/contexts.cc
M src/globals.h
M src/parser.cc
M src/pattern-rewriter.cc
M src/runtime/runtime-scopes.cc
M src/scopeinfo.cc
M src/scopes.h
M src/scopes.cc
M src/variables.cc
M test/cctest/test-parsing.cc
A + test/mjsunit/es6/regress/regress-cr512574.js
Index: src/contexts.cc
diff --git a/src/contexts.cc b/src/contexts.cc
index
b29405b505b2316236fad7168366207d54bfbd92..88f593fab8525a197cc2d13d47dbdf8ece4a3292
100644
--- a/src/contexts.cc
+++ b/src/contexts.cc
@@ -140,7 +140,6 @@ static void GetAttributesAndBindingFlags(VariableMode
mode,
PropertyAttributes* attributes,
BindingFlags* binding_flags) {
switch (mode) {
- case INTERNAL: // Fall through.
case VAR:
*attributes = NONE;
*binding_flags = MUTABLE_IS_INITIALIZED;
Index: src/globals.h
diff --git a/src/globals.h b/src/globals.h
index
749d6e1c3beb8a06a15c656021d8b14f8f4d22bc..7ab6fdbd5f5cced8ce0b66a40d267950f6b9f2fb
100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -810,9 +810,6 @@ enum VariableMode {
IMPORT, // declared via 'import' declarations (last lexical)
// Variables introduced by the compiler:
- INTERNAL, // like VAR, but not user-visible (may or may not
- // be in a context)
-
TEMPORARY, // temporary variables (not user-visible),
stack-allocated
// unless the scope as a whole has forced context
allocation
Index: src/parser.cc
diff --git a/src/parser.cc b/src/parser.cc
index
60b72282c1f454d2d74a0864fe599cc0ed1ae72b..4644452b3fd42c0baf5ce0956a16b1e07660c0f3
100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -2827,7 +2827,7 @@ Statement* Parser::ParseReturnStatement(bool* ok) {
//
// return (temp = expr) === undefined ? this :
// %_IsSpecObject(temp) ? temp : throw new TypeError(...);
- Variable* temp = scope_->DeclarationScope()->NewTemporary(
+ Variable* temp = scope_->NewTemporary(
ast_value_factory()->empty_string());
Assignment* assign = factory()->NewAssignment(
Token::ASSIGN, factory()->NewVariableProxy(temp), return_value,
pos);
@@ -3181,9 +3181,9 @@ void
Parser::InitializeForEachStatement(ForEachStatement* stmt,
ForOfStatement* for_of = stmt->AsForOfStatement();
if (for_of != NULL) {
- Variable* iterator = scope_->DeclarationScope()->NewTemporary(
+ Variable* iterator = scope_->NewTemporary(
ast_value_factory()->dot_iterator_string());
- Variable* result = scope_->DeclarationScope()->NewTemporary(
+ Variable* result = scope_->NewTemporary(
ast_value_factory()->dot_result_string());
Expression* assign_iterator;
@@ -3299,7 +3299,7 @@ Statement*
Parser::DesugarLexicalBindingsInForStatement(
// make statement: temp_x = x.
for (int i = 0; i < names->length(); i++) {
VariableProxy* proxy = NewUnresolved(names->at(i), LET);
- Variable* temp = scope_->DeclarationScope()->NewTemporary(temp_name);
+ Variable* temp = scope_->NewTemporary(temp_name);
VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
Assignment* assignment = factory()->NewAssignment(
Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition);
@@ -3312,7 +3312,7 @@ Statement*
Parser::DesugarLexicalBindingsInForStatement(
Variable* first = NULL;
// Make statement: first = 1.
if (next) {
- first = scope_->DeclarationScope()->NewTemporary(temp_name);
+ first = scope_->NewTemporary(temp_name);
VariableProxy* first_proxy = factory()->NewVariableProxy(first);
Expression* const1 = factory()->NewSmiLiteral(1,
RelocInfo::kNoPosition);
Assignment* assignment = factory()->NewAssignment(
@@ -3392,7 +3392,7 @@ Statement*
Parser::DesugarLexicalBindingsInForStatement(
ignore_completion_block->AddStatement(clear_first_or_next, zone());
}
- Variable* flag = scope_->DeclarationScope()->NewTemporary(temp_name);
+ Variable* flag = scope_->NewTemporary(temp_name);
// Make statement: flag = 1.
{
VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
@@ -3578,7 +3578,7 @@ Statement* Parser::ParseForStatement(ZoneList<const
AstRawString*>* labels,
// let x; // for TDZ
// }
- Variable* temp = scope_->DeclarationScope()->NewTemporary(
+ Variable* temp = scope_->NewTemporary(
ast_value_factory()->dot_for_string());
ForEachStatement* loop =
factory()->NewForEachStatement(mode, labels, stmt_pos);
@@ -4007,7 +4007,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
// Calling a generator returns a generator object. That object is
stored
// in a temporary variable, a definition that is used by "yield"
// expressions. This also marks the FunctionState as a generator.
- Variable* temp = scope_->DeclarationScope()->NewTemporary(
+ Variable* temp = scope_->NewTemporary(
ast_value_factory()->dot_generator_object_string());
function_state.set_generator_object_variable(temp);
}
Index: src/pattern-rewriter.cc
diff --git a/src/pattern-rewriter.cc b/src/pattern-rewriter.cc
index
6969cf214ed70034fce8f58a737724ab4b600700..10702d65cee6a49c1db4aa0029cff66a868d496e
100644
--- a/src/pattern-rewriter.cc
+++ b/src/pattern-rewriter.cc
@@ -214,8 +214,8 @@ void
Parser::PatternRewriter::VisitVariableProxy(VariableProxy* pattern) {
Variable* Parser::PatternRewriter::CreateTempVar(Expression* value) {
- auto temp_scope = descriptor_->parser->scope_->DeclarationScope();
- auto temp =
temp_scope->NewTemporary(ast_value_factory()->empty_string());
+ auto temp = descriptor_->parser->scope_->NewTemporary(
+ ast_value_factory()->empty_string());
if (value != nullptr) {
auto assignment = factory()->NewAssignment(
Token::ASSIGN, factory()->NewVariableProxy(temp), value,
Index: src/runtime/runtime-scopes.cc
diff --git a/src/runtime/runtime-scopes.cc b/src/runtime/runtime-scopes.cc
index
b4506512a188e92ee9a02e341582a7fbe1ce30f6..948f7295537378fbc886d9b7bf86e40b18983b66
100644
--- a/src/runtime/runtime-scopes.cc
+++ b/src/runtime/runtime-scopes.cc
@@ -830,7 +830,6 @@ RUNTIME_FUNCTION(Runtime_DeclareModules) {
USE(result);
break;
}
- case INTERNAL:
case TEMPORARY:
case DYNAMIC:
case DYNAMIC_GLOBAL:
Index: src/scopeinfo.cc
diff --git a/src/scopeinfo.cc b/src/scopeinfo.cc
index
4ed22b19dcd9a37b60f07aacd92b09c923079ca2..a621083f9679afe6dc9ca61b5b8f22322a8ce33f
100644
--- a/src/scopeinfo.cc
+++ b/src/scopeinfo.cc
@@ -564,7 +564,7 @@ int ScopeInfo::ContextSlotIndex(Handle<ScopeInfo>
scope_info,
}
// Cache as not found. Mode, location, init flag and maybe assigned
flag
// don't matter.
- context_slot_cache->Update(scope_info, name, INTERNAL,
+ context_slot_cache->Update(scope_info, name, TEMPORARY,
VariableLocation::CONTEXT,
kNeedsInitialization,
kNotAssigned, -1);
}
Index: src/scopes.cc
diff --git a/src/scopes.cc b/src/scopes.cc
index
6e1c18dc2e11b346c3c3e4914d58160a8027eb5c..4aca42042233652d3ad0b597804793652e8b106d
100644
--- a/src/scopes.cc
+++ b/src/scopes.cc
@@ -527,26 +527,15 @@ void Scope::RemoveUnresolved(VariableProxy* var) {
}
-Variable* Scope::NewInternal(const AstRawString* name) {
- DCHECK(!already_resolved());
- Variable* var = new(zone()) Variable(this,
- name,
- INTERNAL,
- Variable::NORMAL,
- kCreatedInitialized);
- internals_.Add(var, zone());
- return var;
-}
-
-
Variable* Scope::NewTemporary(const AstRawString* name) {
DCHECK(!already_resolved());
- Variable* var = new(zone()) Variable(this,
+ Scope* scope = this->TemporaryScope();
+ Variable* var = new(zone()) Variable(scope,
name,
TEMPORARY,
Variable::NORMAL,
kCreatedInitialized);
- temps_.Add(var, zone());
+ scope->temps_.Add(var, zone());
return var;
}
@@ -772,6 +761,15 @@ Scope* Scope::DeclarationScope() {
}
+Scope* Scope::TemporaryScope() {
+ Scope* scope = this;
+ while (!scope->is_declaration_scope() || scope->is_block_scope()) {
+ scope = scope->outer_scope();
+ }
+ return scope;
+}
+
+
Scope* Scope::ReceiverScope() {
Scope* scope = this;
while (!scope->is_script_scope() &&
@@ -1354,7 +1352,6 @@ bool Scope::MustAllocateInContext(Variable* var) {
// always context-allocated.
if (has_forced_context_allocation()) return true;
if (var->mode() == TEMPORARY) return false;
- if (var->mode() == INTERNAL) return true;
if (is_catch_scope() || is_module_scope()) return true;
if (is_script_scope() && IsLexicalVariableMode(var->mode())) return true;
return var->has_forced_context_allocation() ||
@@ -1609,7 +1606,8 @@ void Scope::AllocateModules() {
DCHECK(!scope->already_resolved());
DCHECK(scope->module_descriptor_->IsFrozen());
DCHECK_NULL(scope->module_var_);
- scope->module_var_ =
NewInternal(ast_value_factory_->dot_module_string());
+ scope->module_var_ =
+ NewTemporary(ast_value_factory_->dot_module_string());
++num_modules_;
}
}
Index: src/scopes.h
diff --git a/src/scopes.h b/src/scopes.h
index
e565ff69fe25f7c1197a341a5e96940ced953773..73277252e3ed1bb451f8507603256358ab03ac29
100644
--- a/src/scopes.h
+++ b/src/scopes.h
@@ -168,16 +168,11 @@ class Scope: public ZoneObject {
// such a variable again if it was added; otherwise this is a no-op.
void RemoveUnresolved(VariableProxy* var);
- // Creates a new internal variable in this scope. The name is only used
- // for printing and cannot be used to find the variable. In particular,
- // the only way to get hold of the temporary is by keeping the Variable*
- // around.
- Variable* NewInternal(const AstRawString* name);
-
- // Creates a new temporary variable in this scope. The name is only used
- // for printing and cannot be used to find the variable. In particular,
- // the only way to get hold of the temporary is by keeping the Variable*
- // around. The name should not clash with a legitimate variable names.
+ // Creates a new temporary variable in this scope's TemporaryScope. The
+ // name is only used for printing and cannot be used to find the
variable.
+ // In particular, the only way to get hold of the temporary is by
keeping the
+ // Variable* around. The name should not clash with a legitimate
variable
+ // names.
Variable* NewTemporary(const AstRawString* name);
// Adds the specific declaration node to the list of declarations in
@@ -487,6 +482,11 @@ class Scope: public ZoneObject {
// the scope where var declarations will be hoisted to in the
implementation.
Scope* DeclarationScope();
+ // Find the first non-block declaration scope. This should be either a
script,
+ // function, or eval scope. Same as DeclarationScope(), but skips
+ // declaration "block" scopes. Used for declaring temporaries.
+ Scope* TemporaryScope();
+
// Find the first (non-arrow) function or script scope. This is where
// 'this' is bound, and what determines the function kind.
Scope* ReceiverScope();
Index: src/variables.cc
diff --git a/src/variables.cc b/src/variables.cc
index
b8fddd306df59ff86b15d00a7e7df009e4662261..5833d860aab2af36b36c60296b9447689bb0014e
100644
--- a/src/variables.cc
+++ b/src/variables.cc
@@ -24,7 +24,6 @@ const char* Variable::Mode2String(VariableMode mode) {
case DYNAMIC: return "DYNAMIC";
case DYNAMIC_GLOBAL: return "DYNAMIC_GLOBAL";
case DYNAMIC_LOCAL: return "DYNAMIC_LOCAL";
- case INTERNAL: return "INTERNAL";
case TEMPORARY: return "TEMPORARY";
}
UNREACHABLE();
Index: test/cctest/test-parsing.cc
diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc
index
e14b6f63601708ada88f950d1cc53db51e029e08..703f74d947cdaba3fb1da8f9cea83a0c0c6226ac
100644
--- a/test/cctest/test-parsing.cc
+++ b/test/cctest/test-parsing.cc
@@ -5527,7 +5527,7 @@ TEST(ModuleParsingInternals) {
CHECK_EQ(1, outer_scope->num_modules());
CHECK(module_scope->is_module_scope());
CHECK_NOT_NULL(module_scope->module_var());
- CHECK_EQ(i::INTERNAL, module_scope->module_var()->mode());
+ CHECK_EQ(i::TEMPORARY, module_scope->module_var()->mode());
i::ModuleDescriptor* descriptor = module_scope->module();
CHECK_NOT_NULL(descriptor);
CHECK_EQ(1, descriptor->Length());
Index: test/mjsunit/es6/regress/regress-cr512574.js
diff --git a/test/message/destructuring-modify-const.js
b/test/mjsunit/es6/regress/regress-cr512574.js
similarity index 76%
copy from test/message/destructuring-modify-const.js
copy to test/mjsunit/es6/regress/regress-cr512574.js
index
cabd924b37ea9f178259f4c979c3b3268920c713..2c10e193156550e1f23d35a070027054ba652eb8
100644
--- a/test/message/destructuring-modify-const.js
+++ b/test/mjsunit/es6/regress/regress-cr512574.js
@@ -3,7 +3,7 @@
// found in the LICENSE file.
// Flags: --harmony-destructuring
-'use strict';
-const { x : x, y : y } = { x : 1, y : 2 };
-x++;
+function f({}) {
+ for (var v in []);
+};
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.