Commit 05696362 authored by Marja Hölttä's avatar Marja Hölttä Committed by Commit Bot

[parser] Skipping inner funcs: fix preparsing super.

Super calls need to refer to .this_function, .new.target and this, and super
property references need to refer to .this_function and this, so that the
is_used for those variables will be set and they will be allocated correctly.

BUG=v8:5516

Change-Id: Idc58539fccad70c995e029051b59a67ea66bff91
Reviewed-on: https://chromium-review.googlesource.com/506094Reviewed-by: 's avatarDaniel Vogelheim <vogelheim@chromium.org>
Commit-Queue: Marja Hölttä <marja@chromium.org>
Cr-Commit-Position: refs/heads/master@{#45376}
parent e33fd307
...@@ -660,7 +660,12 @@ class V8_EXPORT_PRIVATE DeclarationScope : public Scope { ...@@ -660,7 +660,12 @@ class V8_EXPORT_PRIVATE DeclarationScope : public Scope {
} }
// Inform the scope that the corresponding code uses "super". // Inform the scope that the corresponding code uses "super".
void RecordSuperPropertyUsage() { scope_uses_super_property_ = true; } void RecordSuperPropertyUsage() {
DCHECK((IsConciseMethod(function_kind()) ||
IsAccessorFunction(function_kind()) ||
IsClassConstructor(function_kind())));
scope_uses_super_property_ = true;
}
// Does this scope access "super" property (super.foo). // Does this scope access "super" property (super.foo).
bool uses_super_property() const { return scope_uses_super_property_; } bool uses_super_property() const { return scope_uses_super_property_; }
......
...@@ -335,8 +335,7 @@ bool PreParsedScopeData::ScopeNeedsData(Scope* scope) { ...@@ -335,8 +335,7 @@ bool PreParsedScopeData::ScopeNeedsData(Scope* scope) {
if (scope->scope_type() == ScopeType::FUNCTION_SCOPE) { if (scope->scope_type() == ScopeType::FUNCTION_SCOPE) {
// Default constructors don't need data (they cannot contain inner functions // Default constructors don't need data (they cannot contain inner functions
// defined by the user). Other functions do. // defined by the user). Other functions do.
return (scope->AsDeclarationScope()->function_kind() & return !IsDefaultConstructor(scope->AsDeclarationScope()->function_kind());
kDefaultConstructor) == 0;
} }
if (!scope->is_hidden()) { if (!scope->is_hidden()) {
for (Variable* var : *scope->locals()) { for (Variable* var : *scope->locals()) {
......
...@@ -1521,10 +1521,29 @@ class PreParser : public ParserBase<PreParser> { ...@@ -1521,10 +1521,29 @@ class PreParser : public ParserBase<PreParser> {
} }
V8_INLINE PreParserExpression NewSuperPropertyReference(int pos) { V8_INLINE PreParserExpression NewSuperPropertyReference(int pos) {
if (track_unresolved_variables_) {
scope()->NewUnresolved(factory()->ast_node_factory(),
ast_value_factory()->this_function_string(), pos,
NORMAL_VARIABLE);
scope()->NewUnresolved(factory()->ast_node_factory(),
ast_value_factory()->this_string(), pos,
THIS_VARIABLE);
}
return PreParserExpression::Default(); return PreParserExpression::Default();
} }
V8_INLINE PreParserExpression NewSuperCallReference(int pos) { V8_INLINE PreParserExpression NewSuperCallReference(int pos) {
if (track_unresolved_variables_) {
scope()->NewUnresolved(factory()->ast_node_factory(),
ast_value_factory()->this_function_string(), pos,
NORMAL_VARIABLE);
scope()->NewUnresolved(factory()->ast_node_factory(),
ast_value_factory()->new_target_string(), pos,
NORMAL_VARIABLE);
scope()->NewUnresolved(factory()->ast_node_factory(),
ast_value_factory()->this_string(), pos,
THIS_VARIABLE);
}
return PreParserExpression::SuperCallReference(); return PreParserExpression::SuperCallReference();
} }
......
...@@ -163,6 +163,15 @@ TEST(PreParserScopeAnalysis) { ...@@ -163,6 +163,15 @@ TEST(PreParserScopeAnalysis) {
// Methods containing skippable functions. Cannot test at the laziness // Methods containing skippable functions. Cannot test at the laziness
// boundary, since there's no way to force eager parsing of a method. // boundary, since there's no way to force eager parsing of a method.
{"class MyClass { constructor() {",
"} }",
" function test(%s) { %s }",
"(function test(%s) { %s })()",
true,
true,
false,
{0, 0, 0}},
{"class MyClass { mymethod() {", {"class MyClass { mymethod() {",
"} }", "} }",
" function test(%s) { %s }", " function test(%s) { %s }",
...@@ -618,7 +627,6 @@ TEST(PreParserScopeAnalysis) { ...@@ -618,7 +627,6 @@ TEST(PreParserScopeAnalysis) {
{"try { } catch(var1) { var var1 = 3; function f() { var1 = 3; } }"}, {"try { } catch(var1) { var var1 = 3; function f() { var1 = 3; } }"},
// Classes // Classes
// FIXME(marja): Add more complex class cases.
{"class MyClass {}"}, {"class MyClass {}"},
{"var1 = class MyClass {}"}, {"var1 = class MyClass {}"},
{"var var1 = class MyClass {}"}, {"var var1 = class MyClass {}"},
...@@ -628,6 +636,12 @@ TEST(PreParserScopeAnalysis) { ...@@ -628,6 +636,12 @@ TEST(PreParserScopeAnalysis) {
{"let var1 = class {}"}, {"let var1 = class {}"},
{"const var1 = class {}"}, {"const var1 = class {}"},
{"class MyClass { constructor() {} }"},
{"class MyClass { constructor() { var var1; } }"},
{"class MyClass { constructor() { var var1 = 11; } }"},
{"class MyClass { constructor() { var var1; function foo() { var1 = 11; "
"} } }"},
{"class MyClass { m() {} }"}, {"class MyClass { m() {} }"},
{"class MyClass { m() { var var1; } }"}, {"class MyClass { m() { var var1; } }"},
{"class MyClass { m() { var var1 = 11; } }"}, {"class MyClass { m() { var var1 = 11; } }"},
...@@ -638,6 +652,28 @@ TEST(PreParserScopeAnalysis) { ...@@ -638,6 +652,28 @@ TEST(PreParserScopeAnalysis) {
{"class MyClass { static m() { var var1 = 11; } }"}, {"class MyClass { static m() { var var1 = 11; } }"},
{"class MyClass { static m() { var var1; function foo() { var1 = 11; } } " {"class MyClass { static m() { var var1; function foo() { var1 = 11; } } "
"}"}, "}"},
{"class MyBase {} class MyClass extends MyBase {}"},
{"class MyClass extends MyBase { constructor() {} }"},
{"class MyClass extends MyBase { constructor() { super(); } }"},
{"class MyClass extends MyBase { constructor() { var var1; } }"},
{"class MyClass extends MyBase { constructor() { var var1 = 11; } }"},
{"class MyClass extends MyBase { constructor() { var var1; function "
"foo() { var1 = 11; } } }"},
{"class MyClass extends MyBase { m() {} }"},
{"class MyClass extends MyBase { m() { super.foo; } }"},
{"class MyClass extends MyBase { m() { var var1; } }"},
{"class MyClass extends MyBase { m() { var var1 = 11; } }"},
{"class MyClass extends MyBase { m() { var var1; function foo() { var1 = "
"11; } } }"},
{"class MyClass extends MyBase { static m() {} }"},
{"class MyClass extends MyBase { static m() { super.foo; } }"},
{"class MyClass extends MyBase { static m() { var var1; } }"},
{"class MyClass extends MyBase { static m() { var var1 = 11; } }"},
{"class MyClass extends MyBase { static m() { var var1; function foo() { "
"var1 = 11; } } }"},
}; };
for (unsigned outer_ix = 0; outer_ix < arraysize(outers); ++outer_ix) { for (unsigned outer_ix = 0; outer_ix < arraysize(outers); ++outer_ix) {
......
...@@ -23,7 +23,15 @@ class ScopeTestHelper { ...@@ -23,7 +23,15 @@ class ScopeTestHelper {
static void CompareScopes(Scope* baseline, Scope* scope, static void CompareScopes(Scope* baseline, Scope* scope,
bool precise_maybe_assigned) { bool precise_maybe_assigned) {
if (!scope->is_hidden()) { CHECK_EQ(baseline->scope_type(), scope->scope_type());
CHECK_IMPLIES(baseline->is_declaration_scope(),
baseline->AsDeclarationScope()->function_kind() ==
scope->AsDeclarationScope()->function_kind());
if (!PreParsedScopeData::ScopeNeedsData(baseline)) {
return;
}
for (auto baseline_local = baseline->locals()->begin(), for (auto baseline_local = baseline->locals()->begin(),
scope_local = scope->locals()->begin(); scope_local = scope->locals()->begin();
baseline_local != baseline->locals()->end(); baseline_local != baseline->locals()->end();
...@@ -50,7 +58,6 @@ class ScopeTestHelper { ...@@ -50,7 +58,6 @@ class ScopeTestHelper {
} }
} }
} }
}
for (Scope *baseline_inner = baseline->inner_scope(), for (Scope *baseline_inner = baseline->inner_scope(),
*scope_inner = scope->inner_scope(); *scope_inner = scope->inner_scope();
......
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