[parsing/test] Skipping inner funcs: add more (structured tests).

Test both cases where the interesting constructs occur at the
laziness boundary and cases where they occur deeper.

BUG=v8:5501
R=vogelheim@chromium.org

Change-Id: I99e32cb0c829616011bf7d1f389a8d309b54d67e
Reviewed-on: https://chromium-review.googlesource.com/441844
Reviewed-by: Daniel Vogelheim <vogelheim@chromium.org>
Commit-Queue: Marja Hölttä <marja@chromium.org>
Cr-Commit-Position: refs/heads/master@{#43157}
This commit is contained in:
Marja Hölttä 2017-02-13 13:09:06 +01:00 committed by Commit Bot
parent cb7e3d39fd
commit 8c449e39b5

View File

@ -20,17 +20,56 @@ TEST(PreParserScopeAnalysis) {
i::HandleScope scope(isolate);
LocalContext env;
// FIXME(marja): Add tests where the test cases are deeper (in a second-level
// inner function or second-level inner arrow function). Remove redundant test
// cases.
const char* prefix = "(function outer() { ";
const char* suffix = " })();";
int prefix_len = Utf8LengthHelper(prefix);
int suffix_len = Utf8LengthHelper(suffix);
/* Test the following cases:
1)
(function outer() {
function test() { ... }
})();
against:
(function outer() {
(function test() { ... })();
})();
// The scope start positions must match; note the extra space in lazy_inner.
const char* lazy_inner = " function inner(%s) { %s }";
const char* eager_inner = "(function inner(%s) { %s })()";
2)
(function outer() {
function inner() { function test() { ... } }
})();
against:
(function outer() {
(function inner() { function test() { ... } })();
})();
(Modified function is deeper inside the laziness boundary.)
3)
(function outer() {
function inner() { () => { ... } }
})();
against:
(function outer() {
(function inner() { () => { ... } })();
})();
Inner arrow functions are never lazy, so the corresponding case is missing.
*/
struct {
const char* prefix;
const char* suffix;
const char* lazy_inner;
const char* eager_inner;
} outers[] = {
// The scope start positions must match; note the extra space in
// lazy_inner.
{"(function outer() { ", "})();", " function test(%s) { %s }",
"(function test(%s) { %s })()"},
{"(function outer() { ", "})();",
" function inner() { function test(%s) { %s } }",
"(function inner() { function test(%s) { %s } })()"},
// FIXME(marja): enable test for arrow functions once it passes.
// {"(function outer() { ", "})();",
// " function inner() { (%s) => { %s } }",
// "(function inner() { (%s) => { %s } })()"},
};
struct Inner {
Inner(const char* s) : source(s) {} // NOLINT
@ -97,12 +136,9 @@ TEST(PreParserScopeAnalysis) {
{"arguments = 5;"},
{"if (true) { arguments; }"},
{"if (true) { arguments = 5; }"},
{"function f() { arguments; }"},
{"function f() { arguments = 5; }"},
{"this;"},
{"if (true) { this; }"},
{"function f() { this; }"},
// Variable called "arguments"
{"var arguments;"},
@ -154,16 +190,15 @@ TEST(PreParserScopeAnalysis) {
{"const {var1: var2, var3: [var4, var5]} = {var1: 1, var3: [2, 3]};"},
// Referencing the function variable.
{"inner;"},
{"test;"},
{"function f1() { f1; }"},
{"function f1() { inner; }"},
{"function f1() { function f2() { f1; } }"},
{"function arguments() {}"},
{"function f1() {} function f1() {}"},
{"var f1; function f1() {}"},
// Assigning to the function variable.
{"inner = 3;"},
{"test = 3;"},
{"function f1() { f1 = 3; }"},
{"function f1() { f1; } f1 = 3;"},
{"function arguments() {} arguments = 8"},
@ -282,9 +317,6 @@ TEST(PreParserScopeAnalysis) {
{"if (true) { function f1() {} f1 = 3; function foo() { f1; } }"},
{"if (true) { function f1() {} f1 = 3; } function foo() { f1; }"},
{"function inner2() { if (true) { function f1() {} } }"},
{"function inner2() { if (true) { function f1() {} f1 = 3; } }"},
{"var f1 = 1; if (true) { function f1() {} }"},
{"var f1 = 1; if (true) { function f1() {} } function foo() { f1; }"},
@ -316,70 +348,77 @@ TEST(PreParserScopeAnalysis) {
// value, locals shadowing params.
};
for (unsigned i = 0; i < arraysize(inners); ++i) {
// First compile with the lazy inner function and extract the scope data.
const char* inner_function = lazy_inner;
int inner_function_len = Utf8LengthHelper(inner_function) - 4;
for (unsigned outer_ix = 0; outer_ix < arraysize(outers); ++outer_ix) {
for (unsigned inner_ix = 0; inner_ix < arraysize(inners); ++inner_ix) {
const char* prefix = outers[outer_ix].prefix;
const char* suffix = outers[outer_ix].suffix;
int prefix_len = Utf8LengthHelper(prefix);
int suffix_len = Utf8LengthHelper(suffix);
int params_len = Utf8LengthHelper(inners[i].params);
int source_len = Utf8LengthHelper(inners[i].source);
int len =
prefix_len + inner_function_len + params_len + source_len + suffix_len;
// First compile with the lazy inner function and extract the scope data.
const char* inner_function = outers[outer_ix].lazy_inner;
int inner_function_len = Utf8LengthHelper(inner_function) - 4;
i::ScopedVector<char> lazy_program(len + 1);
i::SNPrintF(lazy_program, "%s", prefix);
i::SNPrintF(lazy_program + prefix_len, inner_function, inners[i].params,
inners[i].source);
i::SNPrintF(lazy_program + prefix_len + inner_function_len + params_len +
source_len,
"%s", suffix);
int params_len = Utf8LengthHelper(inners[inner_ix].params);
int source_len = Utf8LengthHelper(inners[inner_ix].source);
int len = prefix_len + inner_function_len + params_len + source_len +
suffix_len;
i::Handle<i::String> source =
factory->InternalizeUtf8String(lazy_program.start());
source->PrintOn(stdout);
printf("\n");
i::ScopedVector<char> lazy_program(len + 1);
i::SNPrintF(lazy_program, "%s", prefix);
i::SNPrintF(lazy_program + prefix_len, inner_function,
inners[inner_ix].params, inners[inner_ix].source);
i::SNPrintF(lazy_program + prefix_len + inner_function_len + params_len +
source_len,
"%s", suffix);
i::Handle<i::Script> script = factory->NewScript(source);
i::ParseInfo lazy_info(script);
i::Handle<i::String> source =
factory->InternalizeUtf8String(lazy_program.start());
source->PrintOn(stdout);
printf("\n");
// No need to run scope analysis; preparser scope data is produced when
// parsing.
CHECK(i::parsing::ParseProgram(&lazy_info));
i::Handle<i::Script> script = factory->NewScript(source);
i::ParseInfo lazy_info(script);
// Then parse eagerly and check against the scope data.
inner_function = eager_inner;
inner_function_len = Utf8LengthHelper(inner_function) - 4;
len =
prefix_len + inner_function_len + params_len + source_len + suffix_len;
// No need to run scope analysis; preparser scope data is produced when
// parsing.
CHECK(i::parsing::ParseProgram(&lazy_info));
i::ScopedVector<char> eager_program(len + 1);
i::SNPrintF(eager_program, "%s", prefix);
i::SNPrintF(eager_program + prefix_len, inner_function, inners[i].params,
inners[i].source);
i::SNPrintF(eager_program + prefix_len + inner_function_len + params_len +
source_len,
"%s", suffix);
// Then parse eagerly and check against the scope data.
inner_function = outers[outer_ix].eager_inner;
inner_function_len = Utf8LengthHelper(inner_function) - 4;
len = prefix_len + inner_function_len + params_len + source_len +
suffix_len;
source = factory->InternalizeUtf8String(eager_program.start());
source->PrintOn(stdout);
printf("\n");
i::ScopedVector<char> eager_program(len + 1);
i::SNPrintF(eager_program, "%s", prefix);
i::SNPrintF(eager_program + prefix_len, inner_function,
inners[inner_ix].params, inners[inner_ix].source);
i::SNPrintF(eager_program + prefix_len + inner_function_len + params_len +
source_len,
"%s", suffix);
script = factory->NewScript(source);
i::ParseInfo eager_info(script);
eager_info.set_allow_lazy_parsing(false);
source = factory->InternalizeUtf8String(eager_program.start());
source->PrintOn(stdout);
printf("\n");
CHECK(i::parsing::ParseProgram(&eager_info));
CHECK(i::Compiler::Analyze(&eager_info));
script = factory->NewScript(source);
i::ParseInfo eager_info(script);
eager_info.set_allow_lazy_parsing(false);
i::Scope* scope =
eager_info.literal()->scope()->inner_scope()->inner_scope();
DCHECK_NOT_NULL(scope);
DCHECK_NULL(scope->sibling());
DCHECK(scope->is_function_scope());
CHECK(i::parsing::ParseProgram(&eager_info));
CHECK(i::Compiler::Analyze(&eager_info));
size_t index = 0;
i::ScopeTestHelper::CompareScopeToData(
scope, lazy_info.preparsed_scope_data(), index,
inners[i].precise_maybe_assigned);
i::Scope* scope =
eager_info.literal()->scope()->inner_scope()->inner_scope();
DCHECK_NOT_NULL(scope);
DCHECK_NULL(scope->sibling());
DCHECK(scope->is_function_scope());
size_t index = 0;
i::ScopeTestHelper::CompareScopeToData(
scope, lazy_info.preparsed_scope_data(), index,
inners[inner_ix].precise_maybe_assigned);
}
}
}