Commit 21557b48 authored by marja's avatar marja Committed by Commit bot

[strong] Simplify the classes-referring-to-classes check.

Follow up for r28032.

We don't need to store the "corresponding outer scope class variables", it's
enough if we transmit the declaration group start to the inner class
variable.

R=rossberg@chromium.org
BUG=v8:3956
LOG=N

Review URL: https://codereview.chromium.org/1102903002

Cr-Commit-Position: refs/heads/master@{#28048}
parent a4bb7643
...@@ -2199,6 +2199,10 @@ Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names, ...@@ -2199,6 +2199,10 @@ Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names,
scope_->class_declaration_group_start()); scope_->class_declaration_group_start());
Variable* outer_class_variable = Declare(declaration, true, CHECK_OK); Variable* outer_class_variable = Declare(declaration, true, CHECK_OK);
proxy->var()->set_initializer_position(position()); proxy->var()->set_initializer_position(position());
// This is needed because a class ("class Name { }") creates two bindings (one
// in the outer scope, and one in the class scope). The method is a function
// scope inside the inner scope (class scope). The consecutive class
// declarations are in the outer scope.
if (value->class_variable_proxy() && value->class_variable_proxy()->var() && if (value->class_variable_proxy() && value->class_variable_proxy()->var() &&
outer_class_variable->is_class()) { outer_class_variable->is_class()) {
// In some cases, the outer variable is not detected as a class variable; // In some cases, the outer variable is not detected as a class variable;
...@@ -2208,8 +2212,8 @@ Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names, ...@@ -2208,8 +2212,8 @@ Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names,
value->class_variable_proxy() value->class_variable_proxy()
->var() ->var()
->AsClassVariable() ->AsClassVariable()
->set_corresponding_outer_class_variable( ->set_declaration_group_start(
outer_class_variable->AsClassVariable()); outer_class_variable->AsClassVariable()->declaration_group_start());
} }
Token::Value init_op = Token::Value init_op =
......
...@@ -1168,48 +1168,40 @@ bool Scope::CheckStrongModeDeclaration(VariableProxy* proxy, Variable* var) { ...@@ -1168,48 +1168,40 @@ bool Scope::CheckStrongModeDeclaration(VariableProxy* proxy, Variable* var) {
for (scope = this; scope && scope != var->scope(); for (scope = this; scope && scope != var->scope();
scope = scope->outer_scope()) { scope = scope->outer_scope()) {
ClassVariable* class_var = scope->ClassVariableForMethod(); ClassVariable* class_var = scope->ClassVariableForMethod();
if (class_var) { // A method is referring to some other class, possibly declared
// A method is referring to some other class, possibly declared // later. Referring to a class declared earlier is always OK and covered
// later. Referring to a class declared earlier is always OK and covered // by the code outside this if. Here we only need to allow special cases
// by the code outside this if. Here we only need to allow special cases // for referring to a class which is declared later.
// for referring to a class which is declared later.
// Referring to a class C declared later is OK under the following
// Referring to a class C declared later is OK under the following // circumstances:
// circumstances:
// 1. The class declarations are in a consecutive group with no other
// 1. The class declarations are in a consecutive group with no other // declarations or statements in between, and
// declarations or statements in between, and
// 2. There is no dependency cycle where the first edge is an
// 2. There is no dependency cycle where the first edge is an // initialization time dependency (computed property name or extends
// initialization time dependency (computed property name or extends // clause) from C to something that depends on this class directly or
// clause) from C to something that depends on this class directly or // transitively.
// transitively. if (class_var &&
class_var->declaration_group_start() ==
// This is needed because a class ("class Name { }") creates two var->AsClassVariable()->declaration_group_start()) {
// bindings (one in the outer scope, and one in the class scope). The return true;
// method is a function scope inside the inner scope (class scope). The
// consecutive class declarations are in the outer scope.
class_var = class_var->corresponding_outer_class_variable();
if (class_var &&
class_var->declaration_group_start() ==
var->AsClassVariable()->declaration_group_start()) {
return true;
}
// TODO(marja,rossberg): implement the dependency cycle detection. Here
// we undershoot the target and allow referring to any class in the same
// consectuive declaration group.
// The cycle detection can work roughly like this: 1) detect init-time
// references here (they are free variables which are inside the class
// scope but not inside a method scope - no parser changes needed to
// detect them) 2) if we encounter an init-time reference here, allow
// it, but record it for a later dependency cycle check 3) also record
// non-init-time references here 4) after scope analysis is done,
// analyse the dependency cycles: an illegal cycle is one starting with
// an init-time reference and leading back to the starting point with
// either non-init-time and init-time references.
} }
// TODO(marja,rossberg): implement the dependency cycle detection. Here we
// undershoot the target and allow referring to any class in the same
// consectuive declaration group.
// The cycle detection can work roughly like this: 1) detect init-time
// references here (they are free variables which are inside the class
// scope but not inside a method scope - no parser changes needed to
// detect them) 2) if we encounter an init-time reference here, allow it,
// but record it for a later dependency cycle check 3) also record
// non-init-time references here 4) after scope analysis is done, analyse
// the dependency cycles: an illegal cycle is one starting with an
// init-time reference and leading back to the starting point with either
// non-init-time and init-time references.
} }
} }
......
...@@ -192,16 +192,11 @@ class ClassVariable : public Variable { ...@@ -192,16 +192,11 @@ class ClassVariable : public Variable {
int declaration_group_start = -1) int declaration_group_start = -1)
: Variable(scope, name, mode, Variable::CLASS, initialization_flag, : Variable(scope, name, mode, Variable::CLASS, initialization_flag,
maybe_assigned_flag), maybe_assigned_flag),
declaration_group_start_(declaration_group_start), declaration_group_start_(declaration_group_start) {}
corresponding_outer_class_variable_(nullptr) {}
int declaration_group_start() const { return declaration_group_start_; } int declaration_group_start() const { return declaration_group_start_; }
void set_declaration_group_start(int declaration_group_start) {
ClassVariable* corresponding_outer_class_variable() const { declaration_group_start_ = declaration_group_start;
return corresponding_outer_class_variable_;
}
void set_corresponding_outer_class_variable(ClassVariable* var) {
corresponding_outer_class_variable_ = var;
} }
private: private:
...@@ -209,7 +204,6 @@ class ClassVariable : public Variable { ...@@ -209,7 +204,6 @@ class ClassVariable : public Variable {
// needed for strong mode scoping checks. TODO(marja, rossberg): Implement // needed for strong mode scoping checks. TODO(marja, rossberg): Implement
// checks for functions too. // checks for functions too.
int declaration_group_start_; int declaration_group_start_;
ClassVariable* corresponding_outer_class_variable_;
}; };
} } // namespace v8::internal } } // namespace v8::internal
......
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