Index: test/cctest/test-parsing.cc |
diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc |
index 3bf3857389c8746facbc8f31f4b602da3fcf59ba..9a4904652e36df72295792e581db9b417ab688d5 100644 |
--- a/test/cctest/test-parsing.cc |
+++ b/test/cctest/test-parsing.cc |
@@ -53,6 +53,8 @@ |
#include "src/utils.h" |
#include "test/cctest/cctest.h" |
+#include "test/cctest/scope-test-helper.h" |
+#include "test/cctest/unicode-helpers.h" |
TEST(ScanKeywords) { |
struct KeywordToken { |
@@ -702,29 +704,6 @@ TEST(RegExpScanning) { |
TestScanRegExp("/=?/", "=?"); |
} |
-static int Ucs2CharLength(unibrow::uchar c) { |
- if (c == unibrow::Utf8::kIncomplete || c == unibrow::Utf8::kBufferEmpty) { |
- return 0; |
- } else if (c < 0xffff) { |
- return 1; |
- } else { |
- return 2; |
- } |
-} |
- |
-static int Utf8LengthHelper(const char* s) { |
- unibrow::Utf8::Utf8IncrementalBuffer buffer(unibrow::Utf8::kBufferEmpty); |
- int length = 0; |
- for (; *s != '\0'; s++) { |
- unibrow::uchar tmp = unibrow::Utf8::ValueOfIncremental(*s, &buffer); |
- length += Ucs2CharLength(tmp); |
- } |
- unibrow::uchar tmp = unibrow::Utf8::ValueOfIncrementalFinish(&buffer); |
- length += Ucs2CharLength(tmp); |
- return length; |
-} |
- |
- |
TEST(ScopeUsesArgumentsSuperThis) { |
static const struct { |
const char* prefix; |
@@ -8826,82 +8805,6 @@ TEST(ArgumentsRedeclaration) { |
} |
} |
-namespace v8 { |
-namespace internal { |
- |
-class ScopeTestHelper { |
- public: |
- static bool MustAllocateInContext(Variable* var) { |
- return var->scope()->MustAllocateInContext(var); |
- } |
- |
- // True if the scope is and its entire subscope tree are hidden. |
- static bool ScopeTreeIsHidden(Scope* scope) { |
- if (!scope->is_hidden()) { |
- return false; |
- } |
- for (Scope* inner = scope->inner_scope(); inner != nullptr; |
- inner = inner->sibling()) { |
- if (!ScopeTreeIsHidden(inner)) { |
- return false; |
- } |
- } |
- return true; |
- } |
- |
- static void CompareScopeToData(Scope* scope, const PreParsedScopeData* data, |
- size_t& index) { |
- CHECK_EQ(data->backing_store_[index++], scope->scope_type()); |
- CHECK_EQ(data->backing_store_[index++], scope->start_position()); |
- CHECK_EQ(data->backing_store_[index++], scope->end_position()); |
- |
- int inner_scope_count = 0; |
- for (Scope* inner = scope->inner_scope(); inner != nullptr; |
- inner = inner->sibling()) { |
- // FIXME(marja): This is probably not the right condition for knowing what |
- // scopes are present in the preparse data. |
- if (!ScopeTreeIsHidden(inner)) { |
- ++inner_scope_count; |
- } |
- } |
- CHECK_EQ(data->backing_store_[index++], inner_scope_count); |
- |
- int variable_count = 0; |
- for (Variable* local : scope->locals_) { |
- if (local->mode() == VAR || local->mode() == LET || |
- local->mode() == CONST) { |
- ++variable_count; |
- } |
- } |
- |
- CHECK_EQ(data->backing_store_[index++], variable_count); |
- |
- for (Variable* local : scope->locals_) { |
- if (local->mode() == VAR || local->mode() == LET || |
- local->mode() == CONST) { |
-#ifdef DEBUG |
- const AstRawString* local_name = local->raw_name(); |
- int name_length = data->backing_store_[index++]; |
- CHECK_EQ(name_length, local_name->length()); |
- for (int i = 0; i < name_length; ++i) { |
- CHECK_EQ(data->backing_store_[index++], local_name->raw_data()[i]); |
- } |
-#endif |
- CHECK_EQ(data->backing_store_[index++], local->location()); |
- CHECK_EQ(data->backing_store_[index++], local->maybe_assigned()); |
- } |
- } |
- |
- for (Scope* inner = scope->inner_scope(); inner != nullptr; |
- inner = inner->sibling()) { |
- if (!ScopeTreeIsHidden(inner)) { |
- CompareScopeToData(inner, data, index); |
- } |
- } |
- } |
-}; |
-} // namespace internal |
-} // namespace v8 |
// Test that lazily parsed inner functions don't result in overly pessimistic |
// context allocations. |
@@ -9189,353 +9092,3 @@ TEST(NoPessimisticContextAllocation) { |
} |
} |
} |
- |
-TEST(PreParserScopeAnalysis) { |
- i::FLAG_lazy_inner_functions = true; |
- i::FLAG_preparser_scope_analysis = true; |
- i::Isolate* isolate = CcTest::i_isolate(); |
- i::Factory* factory = isolate->factory(); |
- i::HandleScope scope(isolate); |
- LocalContext env; |
- |
- const char* prefix = "(function outer() { "; |
- const char* suffix = " })();"; |
- int prefix_len = Utf8LengthHelper(prefix); |
- int suffix_len = Utf8LengthHelper(suffix); |
- |
- // 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 })()"; |
- |
- struct { |
- const char* params; |
- const char* source; |
- } inners[] = { |
- // Simple cases |
- {"", "var1;"}, |
- {"", "var1 = 5;"}, |
- {"", "if (true) {}"}, |
- {"", "function f1() {}"}, |
- |
- // Var declarations and assignments. |
- {"", "var var1;"}, |
- {"", "var var1; var1 = 5;"}, |
- {"", "if (true) { var var1; }"}, |
- {"", "if (true) { var var1; var1 = 5; }"}, |
- {"", "var var1; function f() { var1; }"}, |
- {"", "var var1; var1 = 5; function f() { var1; }"}, |
- {"", "var var1; function f() { var1 = 5; }"}, |
- |
- // Let declarations and assignments. |
- {"", "let var1;"}, |
- {"", "let var1; var1 = 5;"}, |
- {"", "if (true) { let var1; }"}, |
- {"", "if (true) { let var1; var1 = 5; }"}, |
- {"", "let var1; function f() { var1; }"}, |
- {"", "let var1; var1 = 5; function f() { var1; }"}, |
- {"", "let var1; function f() { var1 = 5; }"}, |
- |
- // Const declarations. |
- {"", "const var1 = 5;"}, |
- {"", "if (true) { const var1 = 5; }"}, |
- {"", "const var1 = 5; function f() { var1; }"}, |
- |
- // Redeclarations. |
- {"", "var var1; var var1;"}, |
- {"", "var var1; var var1; var1 = 5;"}, |
- {"", "var var1; if (true) { var var1; }"}, |
- {"", "if (true) { var var1; var var1; }"}, |
- {"", "var var1; if (true) { var var1; var1 = 5; }"}, |
- {"", "if (true) { var var1; var var1; var1 = 5; }"}, |
- {"", "var var1; var var1; function f() { var1; }"}, |
- {"", "var var1; var var1; function f() { var1 = 5; }"}, |
- |
- // Shadowing declarations. |
- {"", "var var1; if (true) { var var1; }"}, |
- {"", "var var1; if (true) { let var1; }"}, |
- {"", "let var1; if (true) { let var1; }"}, |
- |
- {"", "var var1; if (true) { const var1 = 0; }"}, |
- {"", "const var1 = 0; if (true) { const var1 = 0; }"}, |
- |
- // Arguments and this. |
- {"", "arguments;"}, |
- {"", "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;"}, |
- {"", "var arguments; arguments = 5;"}, |
- {"", "if (true) { var arguments; }"}, |
- {"", "if (true) { var arguments; arguments = 5; }"}, |
- {"", "var arguments; function f() { arguments; }"}, |
- {"", "var arguments; arguments = 5; function f() { arguments; }"}, |
- {"", "var arguments; function f() { arguments = 5; }"}, |
- |
- {"", "let arguments;"}, |
- {"", "let arguments; arguments = 5;"}, |
- {"", "if (true) { let arguments; }"}, |
- {"", "if (true) { let arguments; arguments = 5; }"}, |
- {"", "let arguments; function f() { arguments; }"}, |
- {"", "let arguments; arguments = 5; function f() { arguments; }"}, |
- {"", "let arguments; function f() { arguments = 5; }"}, |
- |
- {"", "const arguments = 5;"}, |
- {"", "if (true) { const arguments = 5; }"}, |
- {"", "const arguments = 5; function f() { arguments; }"}, |
- |
- // Destructuring declarations. |
- {"", "var [var1, var2] = [1, 2];"}, |
- {"", "var [var1, var2, [var3, var4]] = [1, 2, [3, 4]];"}, |
- {"", "var [{var1: var2}, {var3: var4}] = [{var1: 1}, {var3: 2}];"}, |
- {"", "var [var1, ...var2] = [1, 2, 3];"}, |
- |
- {"", "var {var1: var2, var3: var4} = {var1: 1, var3: 2};"}, |
- {"", |
- "var {var1: var2, var3: {var4: var5}} = {var1: 1, var3: {var4: 2}};"}, |
- {"", "var {var1: var2, var3: [var4, var5]} = {var1: 1, var3: [2, 3]};"}, |
- |
- {"", "let [var1, var2] = [1, 2];"}, |
- {"", "let [var1, var2, [var3, var4]] = [1, 2, [3, 4]];"}, |
- {"", "let [{var1: var2}, {var3: var4}] = [{var1: 1}, {var3: 2}];"}, |
- {"", "let [var1, ...var2] = [1, 2, 3];"}, |
- |
- {"", "let {var1: var2, var3: var4} = {var1: 1, var3: 2};"}, |
- {"", |
- "let {var1: var2, var3: {var4: var5}} = {var1: 1, var3: {var4: 2}};"}, |
- {"", "let {var1: var2, var3: [var4, var5]} = {var1: 1, var3: [2, 3]};"}, |
- |
- {"", "const [var1, var2] = [1, 2];"}, |
- {"", "const [var1, var2, [var3, var4]] = [1, 2, [3, 4]];"}, |
- {"", "const [{var1: var2}, {var3: var4}] = [{var1: 1}, {var3: 2}];"}, |
- {"", "const [var1, ...var2] = [1, 2, 3];"}, |
- |
- {"", "const {var1: var2, var3: var4} = {var1: 1, var3: 2};"}, |
- {"", |
- "const {var1: var2, var3: {var4: var5}} = {var1: 1, var3: {var4: 2}};"}, |
- {"", "const {var1: var2, var3: [var4, var5]} = {var1: 1, var3: [2, 3]};"}, |
- |
- // Referencing the function variable. |
- {"", "inner;"}, |
- {"", "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;"}, |
- {"", "function f1() { f1 = 3; }"}, |
- {"", "function f1() { f1; } f1 = 3;"}, |
- {"", "function arguments() {} arguments = 8"}, |
- {"", "function f1() {} f1 = 3; function f1() {}"}, |
- |
- // Evals. |
- {"", "var var1; eval('');"}, |
- {"", "var var1; function f1() { eval(''); }"}, |
- {"", "let var1; eval('');"}, |
- {"", "let var1; function f1() { eval(''); }"}, |
- {"", "const var1 = 10; eval('');"}, |
- {"", "const var1 = 10; function f1() { eval(''); }"}, |
- |
- // Standard for loops. |
- {"", "for (var var1 = 0; var1 < 10; ++var1) { }"}, |
- {"", "for (let var1 = 0; var1 < 10; ++var1) { }"}, |
- {"", "for (const var1 = 0; var1 < 10; ++var1) { }"}, |
- |
- {"", |
- "for (var var1 = 0; var1 < 10; ++var1) { function foo() { var1; } }"}, |
- {"", |
- "for (let var1 = 0; var1 < 10; ++var1) { function foo() { var1; } }"}, |
- {"", |
- "for (const var1 = 0; var1 < 10; ++var1) { function foo() { var1; } }"}, |
- {"", |
- "'use strict'; for (var var1 = 0; var1 < 10; ++var1) { function foo() { " |
- "var1; } }"}, |
- {"", |
- "'use strict'; for (let var1 = 0; var1 < 10; ++var1) { function foo() { " |
- "var1; } }"}, |
- {"", |
- "'use strict'; for (const var1 = 0; var1 < 10; ++var1) { function foo() " |
- "{ var1; } }"}, |
- |
- // For of loops |
- {"", "for (var1 of [1, 2]) { }"}, |
- {"", "for (var var1 of [1, 2]) { }"}, |
- {"", "for (let var1 of [1, 2]) { }"}, |
- {"", "for (const var1 of [1, 2]) { }"}, |
- |
- {"", "for (var1 of [1, 2]) { var1; }"}, |
- {"", "for (var var1 of [1, 2]) { var1; }"}, |
- {"", "for (let var1 of [1, 2]) { var1; }"}, |
- {"", "for (const var1 of [1, 2]) { var1; }"}, |
- |
- {"", "for (var1 of [1, 2]) { var1 = 0; }"}, |
- {"", "for (var var1 of [1, 2]) { var1 = 0; }"}, |
- {"", "for (let var1 of [1, 2]) { var1 = 0; }"}, |
- {"", "for (const var1 of [1, 2]) { var1 = 0; }"}, |
- |
- {"", "for (var1 of [1, 2]) { function foo() { var1; } }"}, |
- {"", "for (var var1 of [1, 2]) { function foo() { var1; } }"}, |
- {"", "for (let var1 of [1, 2]) { function foo() { var1; } }"}, |
- {"", "for (const var1 of [1, 2]) { function foo() { var1; } }"}, |
- |
- {"", "for (var1 of [1, 2]) { function foo() { var1 = 0; } }"}, |
- {"", "for (var var1 of [1, 2]) { function foo() { var1 = 0; } }"}, |
- {"", "for (let var1 of [1, 2]) { function foo() { var1 = 0; } }"}, |
- {"", "for (const var1 of [1, 2]) { function foo() { var1 = 0; } }"}, |
- |
- // For in loops |
- {"", "for (var1 in {a: 6}) { }"}, |
- {"", "for (var var1 in {a: 6}) { }"}, |
- {"", "for (let var1 in {a: 6}) { }"}, |
- {"", "for (const var1 in {a: 6}) { }"}, |
- |
- {"", "for (var1 in {a: 6}) { var1; }"}, |
- {"", "for (var var1 in {a: 6}) { var1; }"}, |
- {"", "for (let var1 in {a: 6}) { var1; }"}, |
- {"", "for (const var1 in {a: 6}) { var1; }"}, |
- |
- {"", "for (var1 in {a: 6}) { var1 = 0; }"}, |
- {"", "for (var var1 in {a: 6}) { var1 = 0; }"}, |
- {"", "for (let var1 in {a: 6}) { var1 = 0; }"}, |
- {"", "for (const var1 in {a: 6}) { var1 = 0; }"}, |
- |
- {"", "for (var1 in {a: 6}) { function foo() { var1; } }"}, |
- {"", "for (var var1 in {a: 6}) { function foo() { var1; } }"}, |
- {"", "for (let var1 in {a: 6}) { function foo() { var1; } }"}, |
- {"", "for (const var1 in {a: 6}) { function foo() { var1; } }"}, |
- |
- {"", "for (var1 in {a: 6}) { function foo() { var1 = 0; } }"}, |
- {"", "for (var var1 in {a: 6}) { function foo() { var1 = 0; } }"}, |
- {"", "for (let var1 in {a: 6}) { function foo() { var1 = 0; } }"}, |
- {"", "for (const var1 in {a: 6}) { function foo() { var1 = 0; } }"}, |
- |
- {"", "for (var1 in {a: 6}) { function foo() { var1 = 0; } }"}, |
- {"", "for (var var1 in {a: 6}) { function foo() { var1 = 0; } }"}, |
- {"", "for (let var1 in {a: 6}) { function foo() { var1 = 0; } }"}, |
- {"", "for (const var1 in {a: 6}) { function foo() { var1 = 0; } }"}, |
- |
- // Loops without declarations |
- {"", "var var1 = 0; for ( ; var1 < 2; ++var1) { }"}, |
- {"", |
- "var var1 = 0; for ( ; var1 < 2; ++var1) { function foo() { var1; } }"}, |
- {"", "var var1 = 0; for ( ; var1 > 2; ) { }"}, |
- {"", "var var1 = 0; for ( ; var1 > 2; ) { function foo() { var1; } }"}, |
- {"", |
- "var var1 = 0; for ( ; var1 > 2; ) { function foo() { var1 = 6; } }"}, |
- |
- {"", "var var1 = 0; for(var1; var1 < 2; ++var1) { }"}, |
- {"", |
- "var var1 = 0; for (var1; var1 < 2; ++var1) { function foo() { var1; } " |
- "}"}, |
- {"", "var var1 = 0; for (var1; var1 > 2; ) { }"}, |
- {"", "var var1 = 0; for (var1; var1 > 2; ) { function foo() { var1; } }"}, |
- {"", |
- "var var1 = 0; for (var1; var1 > 2; ) { function foo() { var1 = 6; } }"}, |
- |
- // Sloppy block functions. |
- {"", "if (true) { function f1() {} }"}, |
- {"", "if (true) { function f1() {} function f1() {} }"}, |
- {"", "if (true) { if (true) { function f1() {} } }"}, |
- {"", "if (true) { if (true) { function f1() {} function f1() {} } }"}, |
- {"", "if (true) { function f1() {} f1 = 3; }"}, |
- |
- {"", "if (true) { function f1() {} function foo() { f1; } }"}, |
- {"", "if (true) { function f1() {} } function foo() { f1; }"}, |
- {"", |
- "if (true) { function f1() {} function f1() {} function foo() { f1; } " |
- "}"}, |
- {"", |
- "if (true) { function f1() {} function f1() {} } function foo() { f1; " |
- "}"}, |
- {"", |
- "if (true) { if (true) { function f1() {} } function foo() { f1; } }"}, |
- {"", |
- "if (true) { if (true) { function f1() {} function f1() {} } function " |
- "foo() { f1; } }"}, |
- {"", "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; }"}, |
- }; |
- |
- 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; |
- |
- 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; |
- |
- 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); |
- |
- i::Handle<i::String> source = |
- factory->InternalizeUtf8String(lazy_program.start()); |
- source->PrintOn(stdout); |
- printf("\n"); |
- |
- i::Handle<i::Script> script = factory->NewScript(source); |
- i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME); |
- i::ParseInfo lazy_info(&zone, script); |
- |
- // No need to run scope analysis; preparser scope data is produced when |
- // parsing. |
- CHECK(i::parsing::ParseProgram(&lazy_info)); |
- |
- // 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; |
- |
- 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); |
- |
- source = factory->InternalizeUtf8String(eager_program.start()); |
- source->PrintOn(stdout); |
- printf("\n"); |
- |
- script = factory->NewScript(source); |
- i::ParseInfo eager_info(&zone, script); |
- eager_info.set_allow_lazy_parsing(false); |
- |
- CHECK(i::parsing::ParseProgram(&eager_info)); |
- CHECK(i::Compiler::Analyze(&eager_info)); |
- |
- 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); |
- } |
-} |