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

[parser] Skipping inner funcs: arrow functions now work too.

BUG=v8:5516
R=verwaest@chromium.org

Change-Id: I1bb88e981b81fec85ba6da314e3be927085e6e76
Reviewed-on: https://chromium-review.googlesource.com/447438Reviewed-by: 's avatarAdam Klein <adamk@chromium.org>
Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Commit-Queue: Marja Hölttä <marja@chromium.org>
Cr-Commit-Position: refs/heads/master@{#43526}
parent 0b3e554e
...@@ -888,6 +888,7 @@ void Scope::Snapshot::Reparent(DeclarationScope* new_parent) const { ...@@ -888,6 +888,7 @@ void Scope::Snapshot::Reparent(DeclarationScope* new_parent) const {
// Move eval calls since Snapshot's creation into new_parent. // Move eval calls since Snapshot's creation into new_parent.
if (outer_scope_->scope_calls_eval_) { if (outer_scope_->scope_calls_eval_) {
new_parent->scope_calls_eval_ = true; new_parent->scope_calls_eval_ = true;
new_parent->inner_scope_calls_eval_ = true;
} }
// Reset the outer_scope's eval state. It will be restored to its // Reset the outer_scope's eval state. It will be restored to its
// original value as necessary in the destructor of this class. // original value as necessary in the destructor of this class.
......
...@@ -544,6 +544,7 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) { ...@@ -544,6 +544,7 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) {
// Temporary workaround that allows masking of 'this' in debug-evalute scopes. // Temporary workaround that allows masking of 'this' in debug-evalute scopes.
bool is_debug_evaluate_scope_ : 1; bool is_debug_evaluate_scope_ : 1;
// True if one of the inner scopes or the scope itself calls eval.
bool inner_scope_calls_eval_ : 1; bool inner_scope_calls_eval_ : 1;
bool force_context_allocation_ : 1; bool force_context_allocation_ : 1;
......
...@@ -14,12 +14,13 @@ ...@@ -14,12 +14,13 @@
namespace { namespace {
enum SkipStrict { enum SkipTests {
DONT_SKIP = 0, DONT_SKIP = 0,
// Skip if the test function declares itself strict, otherwise don't skip. // Skip if the test function declares itself strict, otherwise don't skip.
SKIP_STRICT_FUNCTION = 1, SKIP_STRICT_FUNCTION = 1,
// Skip if there's a "use strict" directive above the test. // Skip if there's a "use strict" directive above the test.
SKIP_STRICT_OUTER = 1 << 1, SKIP_STRICT_OUTER = 1 << 1,
SKIP_ARROW = 1 << 2,
SKIP_STRICT = SKIP_STRICT_FUNCTION | SKIP_STRICT_OUTER SKIP_STRICT = SKIP_STRICT_FUNCTION | SKIP_STRICT_OUTER
}; };
...@@ -72,54 +73,55 @@ TEST(PreParserScopeAnalysis) { ...@@ -72,54 +73,55 @@ TEST(PreParserScopeAnalysis) {
const char* eager_inner; const char* eager_inner;
bool strict_outer; bool strict_outer;
bool strict_test_function; bool strict_test_function;
bool arrow;
} outers[] = { } outers[] = {
// The scope start positions must match; note the extra space in // The scope start positions must match; note the extra space in
// lazy_inner. // lazy_inner.
{"(function outer() { ", "})();", " function test(%s) { %s }", {"(function outer() { ", "})();", " function test(%s) { %s }",
"(function test(%s) { %s })()", false, false}, "(function test(%s) { %s })()", false, false, false},
{"(function outer() { ", "})();", {"(function outer() { ", "})();",
" function inner() { function test(%s) { %s } }", " function inner() { function test(%s) { %s } }",
"(function inner() { function test(%s) { %s } })()", false, false}, "(function inner() { function test(%s) { %s } })()", false, false,
// FIXME(marja): enable test for arrow functions once it passes. false},
// {"(function outer() { ", "})();", {"(function outer() { ", "})();", " function inner() { (%s) => { %s } }",
// " function inner() { (%s) => { %s } }", "(function inner() { (%s) => { %s } })()", false, false, true},
// "(function inner() { (%s) => { %s } })()", false},
{"(function outer() { 'use strict'; ", "})();", {"(function outer() { 'use strict'; ", "})();",
" function test(%s) { %s }", "(function test(%s) { %s })()", true, " function test(%s) { %s }", "(function test(%s) { %s })()", true, false,
false}, false},
{"(function outer() { 'use strict'; ", "})();", {"(function outer() { 'use strict'; ", "})();",
" function inner() { function test(%s) { %s } }", " function inner() { function test(%s) { %s } }",
"(function inner() { function test(%s) { %s } })()", true, false}, "(function inner() { function test(%s) { %s } })()", true, false, false},
{"(function outer() { 'use strict'; ", "})();",
" function inner() { (%s) => { %s } }",
"(function inner() { (%s) => { %s } })()", true, false, true},
{"(function outer() { ", "})();", {"(function outer() { ", "})();",
" function test(%s) { 'use strict'; %s }", " function test(%s) { 'use strict'; %s }",
"(function test(%s) { 'use strict'; %s })()", false, true}, "(function test(%s) { 'use strict'; %s })()", false, true, false},
{"(function outer() { ", "})();", {"(function outer() { ", "})();",
" function inner() { function test(%s) { 'use strict'; %s } }", " function inner() { function test(%s) { 'use strict'; %s } }",
"(function inner() { function test(%s) { 'use strict'; %s } })()", false, "(function inner() { function test(%s) { 'use strict'; %s } })()", false,
true, false},
{"(function outer() { ", "})();",
" function inner() { (%s) => { 'use strict'; %s } }",
"(function inner() { (%s) => { 'use strict'; %s } })()", false, true,
true}, true},
}; };
struct Inner { struct Inner {
Inner(const char* s) : source(s) {} // NOLINT Inner(const char* s) : source(s) {} // NOLINT
Inner(const char* s, SkipStrict skip) Inner(const char* s, SkipTests skip) : source(s), skip(skip) {}
: source(s), skip_in_strict_mode(skip) {} Inner(const char* s, SkipTests skip, bool precise)
Inner(const char* s, SkipStrict skip, bool precise) : source(s), skip(skip), precise_maybe_assigned(precise) {}
: source(s),
skip_in_strict_mode(skip),
precise_maybe_assigned(precise) {}
Inner(const char* p, const char* s) : params(p), source(s) {} Inner(const char* p, const char* s) : params(p), source(s) {}
Inner(const char* p, const char* s, SkipStrict skip) Inner(const char* p, const char* s, SkipTests skip)
: params(p), source(s), skip_in_strict_mode(skip) {} : params(p), source(s), skip(skip) {}
Inner(const char* p, const char* s, SkipStrict skip, bool precise) Inner(const char* p, const char* s, SkipTests skip, bool precise)
: params(p), : params(p), source(s), skip(skip), precise_maybe_assigned(precise) {}
source(s),
skip_in_strict_mode(skip),
precise_maybe_assigned(precise) {}
const char* params = ""; const char* params = "";
const char* source; const char* source;
SkipStrict skip_in_strict_mode = DONT_SKIP; SkipTests skip = DONT_SKIP;
bool precise_maybe_assigned = true; bool precise_maybe_assigned = true;
} inners[] = { } inners[] = {
// Simple cases // Simple cases
...@@ -379,11 +381,13 @@ TEST(PreParserScopeAnalysis) { ...@@ -379,11 +381,13 @@ TEST(PreParserScopeAnalysis) {
{"var1, var2", "function f1() { var1 = 9; }"}, {"var1, var2", "function f1() { var1 = 9; }"},
// Duplicate parameters. // Duplicate parameters.
{"var1, var1", "", SKIP_STRICT}, {"var1, var1", "", SkipTests(SKIP_STRICT | SKIP_ARROW)},
{"var1, var1", "var1;", SKIP_STRICT}, {"var1, var1", "var1;", SkipTests(SKIP_STRICT | SKIP_ARROW)},
{"var1, var1", "var1 = 9;", SKIP_STRICT}, {"var1, var1", "var1 = 9;", SkipTests(SKIP_STRICT | SKIP_ARROW)},
{"var1, var1", "function f1() { var1; }", SKIP_STRICT}, {"var1, var1", "function f1() { var1; }",
{"var1, var1", "function f1() { var1 = 9; }", SKIP_STRICT}, SkipTests(SKIP_STRICT | SKIP_ARROW)},
{"var1, var1", "function f1() { var1 = 9; }",
SkipTests(SKIP_STRICT | SKIP_ARROW)},
// If the function declares itself strict, non-simple parameters aren't // If the function declares itself strict, non-simple parameters aren't
// allowed. // allowed.
...@@ -402,9 +406,9 @@ TEST(PreParserScopeAnalysis) { ...@@ -402,9 +406,9 @@ TEST(PreParserScopeAnalysis) {
{"var1, ...var2", "function f1() { var2 = 9; }", SKIP_STRICT_FUNCTION}, {"var1, ...var2", "function f1() { var2 = 9; }", SKIP_STRICT_FUNCTION},
// Default parameters. // Default parameters.
{"var1 = 3", "", SKIP_STRICT_FUNCTION}, {"var1 = 3", "", SKIP_STRICT_FUNCTION, false},
{"var1, var2 = var1", "", SKIP_STRICT_FUNCTION}, {"var1, var2 = var1", "", SKIP_STRICT_FUNCTION, false},
{"var1, var2 = 4, ...var3", "", SKIP_STRICT_FUNCTION}, {"var1, var2 = 4, ...var3", "", SKIP_STRICT_FUNCTION, false},
// Destructuring parameters. Because of the search space explosion, we // Destructuring parameters. Because of the search space explosion, we
// cannot test all interesting cases. Let's try to test a relevant subset. // cannot test all interesting cases. Let's try to test a relevant subset.
...@@ -446,15 +450,25 @@ TEST(PreParserScopeAnalysis) { ...@@ -446,15 +450,25 @@ TEST(PreParserScopeAnalysis) {
SKIP_STRICT_FUNCTION}, SKIP_STRICT_FUNCTION},
// Complicated params. // Complicated params.
{"var1, [var2], var3, [var4, var5], var6, {var7}, var8, {name9: var9, " {"var1, [var2], var3 = 24, [var4, var5] = [2, 4], var6, {var7}, var8, "
"name10: var10}, ...var11", "{name9: var9, name10: var10}, ...var11",
"", SKIP_STRICT_FUNCTION}, "", SKIP_STRICT_FUNCTION, false},
// Destructuring rest. Because we can. // Destructuring rest. Because we can.
{"var1, ...[var2]", "() => { }", SKIP_STRICT_FUNCTION}, {"var1, ...[var2]", "", SKIP_STRICT_FUNCTION},
{"var1, ...[var2]", "() => { var2; }", SKIP_STRICT_FUNCTION}, {"var1, ...[var2]", "() => { var2; }", SKIP_STRICT_FUNCTION},
{"var1, ...{0: var2}", "", SKIP_STRICT_FUNCTION},
{"var1, ...{0: var2}", "() => { var2; }", SKIP_STRICT_FUNCTION},
{"var1, ...[]", "", SKIP_STRICT_FUNCTION},
{"var1, ...{}", "", SKIP_STRICT_FUNCTION},
{"var1, ...[var2, var3]", "", SKIP_STRICT_FUNCTION},
{"var1, ...{0: var2, 1: var3}", "", SKIP_STRICT_FUNCTION},
// Default parameters for destruring parameters. // Default parameters for destruring parameters.
{"[var1, var2] = [2, 4]", "", SKIP_STRICT_FUNCTION, false},
{"{var1, var2} = {var1: 3, var2: 3}", "", SKIP_STRICT_FUNCTION, false},
// Default parameters inside destruring parameters.
{"[var1 = 4, var2 = var1]", "", SKIP_STRICT_FUNCTION, false}, {"[var1 = 4, var2 = var1]", "", SKIP_STRICT_FUNCTION, false},
{"{var1 = 4, var2 = var1}", "", SKIP_STRICT_FUNCTION, false}, {"{var1 = 4, var2 = var1}", "", SKIP_STRICT_FUNCTION, false},
...@@ -469,15 +483,17 @@ TEST(PreParserScopeAnalysis) { ...@@ -469,15 +483,17 @@ TEST(PreParserScopeAnalysis) {
{"var1, var2, ...var3", "var var3 = 16; () => { var3 = 17; }", {"var1, var2, ...var3", "var var3 = 16; () => { var3 = 17; }",
SKIP_STRICT_FUNCTION}, SKIP_STRICT_FUNCTION},
{"var1, var2 = var1", "var var1 = 16; () => { var1 = 17; }", {"var1, var2 = var1", "var var1 = 16; () => { var1 = 17; }",
SKIP_STRICT_FUNCTION}, SKIP_STRICT_FUNCTION, false},
// Hoisted sloppy block function shadowing a parameter. // Hoisted sloppy block function shadowing a parameter.
{"var1, var2", "for (;;) { function var1() { } }"}, // FIXME(marja): why is maybe_assigned inaccurate?
{"var1, var2", "for (;;) { function var1() { } }", DONT_SKIP, false},
// Eval in default parameter. // Eval in default parameter.
{"var1, var2 = eval(''), var3", "let var4 = 0;", SKIP_STRICT_FUNCTION}, {"var1, var2 = eval(''), var3", "let var4 = 0;", SKIP_STRICT_FUNCTION,
false},
{"var1, var2 = eval(''), var3 = eval('')", "let var4 = 0;", {"var1, var2 = eval(''), var3 = eval('')", "let var4 = 0;",
SKIP_STRICT_FUNCTION}, SKIP_STRICT_FUNCTION, false},
// FIXME(marja): arguments parameter // FIXME(marja): arguments parameter
}; };
...@@ -485,11 +501,14 @@ TEST(PreParserScopeAnalysis) { ...@@ -485,11 +501,14 @@ TEST(PreParserScopeAnalysis) {
for (unsigned outer_ix = 0; outer_ix < arraysize(outers); ++outer_ix) { for (unsigned outer_ix = 0; outer_ix < arraysize(outers); ++outer_ix) {
for (unsigned inner_ix = 0; inner_ix < arraysize(inners); ++inner_ix) { for (unsigned inner_ix = 0; inner_ix < arraysize(inners); ++inner_ix) {
if (outers[outer_ix].strict_outer && if (outers[outer_ix].strict_outer &&
(inners[inner_ix].skip_in_strict_mode & SKIP_STRICT_OUTER)) { (inners[inner_ix].skip & SKIP_STRICT_OUTER)) {
continue; continue;
} }
if (outers[outer_ix].strict_test_function && if (outers[outer_ix].strict_test_function &&
(inners[inner_ix].skip_in_strict_mode & SKIP_STRICT_FUNCTION)) { (inners[inner_ix].skip & SKIP_STRICT_FUNCTION)) {
continue;
}
if (outers[outer_ix].arrow && (inners[inner_ix].skip & SKIP_ARROW)) {
continue; continue;
} }
......
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