 Chromium Code Reviews
 Chromium Code Reviews Issue 792083002:
  Add materialized literals for tagged templates in preparser  (Closed) 
  Base URL: https://chromium.googlesource.com/v8/v8.git@master
    
  
    Issue 792083002:
  Add materialized literals for tagged templates in preparser  (Closed) 
  Base URL: https://chromium.googlesource.com/v8/v8.git@master| OLD | NEW | 
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. | 
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without | 
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are | 
| 4 // met: | 4 // met: | 
| 5 // | 5 // | 
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright | 
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. | 
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above | 
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following | 
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided | 
| (...skipping 1372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1383 flags.Contains(kAllowHarmonyArrowFunctions)); | 1383 flags.Contains(kAllowHarmonyArrowFunctions)); | 
| 1384 parser->set_allow_harmony_classes(flags.Contains(kAllowHarmonyClasses)); | 1384 parser->set_allow_harmony_classes(flags.Contains(kAllowHarmonyClasses)); | 
| 1385 parser->set_allow_harmony_templates(flags.Contains(kAllowHarmonyTemplates)); | 1385 parser->set_allow_harmony_templates(flags.Contains(kAllowHarmonyTemplates)); | 
| 1386 parser->set_allow_harmony_sloppy(flags.Contains(kAllowHarmonySloppy)); | 1386 parser->set_allow_harmony_sloppy(flags.Contains(kAllowHarmonySloppy)); | 
| 1387 parser->set_allow_harmony_unicode(flags.Contains(kAllowHarmonyUnicode)); | 1387 parser->set_allow_harmony_unicode(flags.Contains(kAllowHarmonyUnicode)); | 
| 1388 } | 1388 } | 
| 1389 | 1389 | 
| 1390 | 1390 | 
| 1391 void TestParserSyncWithFlags(i::Handle<i::String> source, | 1391 void TestParserSyncWithFlags(i::Handle<i::String> source, | 
| 1392 i::EnumSet<ParserFlag> flags, | 1392 i::EnumSet<ParserFlag> flags, | 
| 1393 ParserSyncTestResult result) { | 1393 ParserSyncTestResult result, | 
| 1394 int literals = -1) { | |
| 
Dmitry Lomov (no reviews)
2014/12/10 18:49:31
Instead of passing the expected number of literals
 | |
| 1394 i::Isolate* isolate = CcTest::i_isolate(); | 1395 i::Isolate* isolate = CcTest::i_isolate(); | 
| 1395 i::Factory* factory = isolate->factory(); | 1396 i::Factory* factory = isolate->factory(); | 
| 1396 | 1397 | 
| 1397 uintptr_t stack_limit = isolate->stack_guard()->real_climit(); | 1398 uintptr_t stack_limit = isolate->stack_guard()->real_climit(); | 
| 1398 | 1399 | 
| 1399 // Preparse the data. | 1400 // Preparse the data. | 
| 1400 i::CompleteParserRecorder log; | 1401 i::CompleteParserRecorder log; | 
| 1401 { | 1402 { | 
| 1402 i::Scanner scanner(isolate->unicode_cache()); | 1403 i::Scanner scanner(isolate->unicode_cache()); | 
| 1403 i::GenericStringUtf16CharacterStream stream(source, 0, source->length()); | 1404 i::GenericStringUtf16CharacterStream stream(source, 0, source->length()); | 
| 1404 i::PreParser preparser(&scanner, &log, stack_limit); | 1405 i::PreParser preparser(&scanner, &log, stack_limit); | 
| 1405 SetParserFlags(&preparser, flags); | 1406 SetParserFlags(&preparser, flags); | 
| 1406 scanner.Initialize(&stream); | 1407 scanner.Initialize(&stream); | 
| 1407 i::PreParser::PreParseResult result = preparser.PreParseProgram(); | 1408 i::PreParser::PreParseResult result = preparser.PreParseProgram(); | 
| 1408 CHECK_EQ(i::PreParser::kPreParseSuccess, result); | 1409 CHECK_EQ(i::PreParser::kPreParseSuccess, result); | 
| 1409 } | 1410 } | 
| 1410 | 1411 | 
| 1411 bool preparse_error = log.HasError(); | 1412 bool preparse_error = log.HasError(); | 
| 1412 | 1413 int actual_materialized_literals; | 
| 1413 // Parse the data | 1414 // Parse the data | 
| 1414 i::FunctionLiteral* function; | 1415 i::FunctionLiteral* function; | 
| 1415 { | 1416 { | 
| 1416 i::Handle<i::Script> script = factory->NewScript(source); | 1417 i::Handle<i::Script> script = factory->NewScript(source); | 
| 1417 i::CompilationInfoWithZone info(script); | 1418 i::CompilationInfoWithZone info(script); | 
| 1418 i::Parser::ParseInfo parse_info = {isolate->stack_guard()->real_climit(), | 1419 i::Parser::ParseInfo parse_info = {isolate->stack_guard()->real_climit(), | 
| 1419 isolate->heap()->HashSeed(), | 1420 isolate->heap()->HashSeed(), | 
| 1420 isolate->unicode_cache()}; | 1421 isolate->unicode_cache()}; | 
| 1421 i::Parser parser(&info, &parse_info); | 1422 i::Parser parser(&info, &parse_info); | 
| 1422 SetParserFlags(&parser, flags); | 1423 SetParserFlags(&parser, flags); | 
| 1423 info.MarkAsGlobal(); | 1424 info.MarkAsGlobal(); | 
| 1424 parser.Parse(); | 1425 parser.Parse(); | 
| 1425 function = info.function(); | 1426 function = info.function(); | 
| 1427 if (function) { | |
| 1428 actual_materialized_literals = function->materialized_literal_count(); | |
| 
caitp (gmail)
2014/12/10 18:17:49
have to do this here because the contents of the f
 | |
| 1429 } | |
| 1426 } | 1430 } | 
| 1427 | 1431 | 
| 1428 // Check that preparsing fails iff parsing fails. | 1432 // Check that preparsing fails iff parsing fails. | 
| 1429 if (function == NULL) { | 1433 if (function == NULL) { | 
| 1430 // Extract exception from the parser. | 1434 // Extract exception from the parser. | 
| 1431 CHECK(isolate->has_pending_exception()); | 1435 CHECK(isolate->has_pending_exception()); | 
| 1432 i::Handle<i::JSObject> exception_handle( | 1436 i::Handle<i::JSObject> exception_handle( | 
| 1433 i::JSObject::cast(isolate->pending_exception())); | 1437 i::JSObject::cast(isolate->pending_exception())); | 
| 1434 i::Handle<i::String> message_string = | 1438 i::Handle<i::String> message_string = | 
| 1435 i::Handle<i::String>::cast(i::Object::GetProperty( | 1439 i::Handle<i::String>::cast(i::Object::GetProperty( | 
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1481 source->ToCString().get(), | 1485 source->ToCString().get(), | 
| 1482 FormatMessage(log.ErrorMessageData())->ToCString().get()); | 1486 FormatMessage(log.ErrorMessageData())->ToCString().get()); | 
| 1483 CHECK(false); | 1487 CHECK(false); | 
| 1484 } else if (result == kError) { | 1488 } else if (result == kError) { | 
| 1485 v8::base::OS::Print( | 1489 v8::base::OS::Print( | 
| 1486 "Expected error on:\n" | 1490 "Expected error on:\n" | 
| 1487 "\t%s\n" | 1491 "\t%s\n" | 
| 1488 "However, parser and preparser succeeded", | 1492 "However, parser and preparser succeeded", | 
| 1489 source->ToCString().get()); | 1493 source->ToCString().get()); | 
| 1490 CHECK(false); | 1494 CHECK(false); | 
| 1495 } else if (literals > -1) { | |
| 1496 if (actual_materialized_literals != literals) { | |
| 1497 v8::base::OS::Print( | |
| 1498 "Expected parsed function to have %d materialized literals, " | |
| 1499 "but it had %d.", literals, actual_materialized_literals | |
| 1500 ); | |
| 1501 CHECK(false); | |
| 1502 } | |
| 1491 } | 1503 } | 
| 1492 } | 1504 } | 
| 1493 | 1505 | 
| 1494 | 1506 | 
| 1495 void TestParserSync(const char* source, | 1507 void TestParserSync(const char* source, | 
| 1496 const ParserFlag* varying_flags, | 1508 const ParserFlag* varying_flags, | 
| 1497 size_t varying_flags_length, | 1509 size_t varying_flags_length, | 
| 1498 ParserSyncTestResult result = kSuccessOrError, | 1510 ParserSyncTestResult result = kSuccessOrError, | 
| 1499 const ParserFlag* always_true_flags = NULL, | 1511 const ParserFlag* always_true_flags = NULL, | 
| 1500 size_t always_true_flags_length = 0, | 1512 size_t always_true_flags_length = 0, | 
| 1501 const ParserFlag* always_false_flags = NULL, | 1513 const ParserFlag* always_false_flags = NULL, | 
| 1502 size_t always_false_flags_length = 0) { | 1514 size_t always_false_flags_length = 0, | 
| 1515 int literals = -1) { | |
| 1503 i::Handle<i::String> str = | 1516 i::Handle<i::String> str = | 
| 1504 CcTest::i_isolate()->factory()->NewStringFromAsciiChecked(source); | 1517 CcTest::i_isolate()->factory()->NewStringFromAsciiChecked(source); | 
| 1505 for (int bits = 0; bits < (1 << varying_flags_length); bits++) { | 1518 for (int bits = 0; bits < (1 << varying_flags_length); bits++) { | 
| 1506 i::EnumSet<ParserFlag> flags; | 1519 i::EnumSet<ParserFlag> flags; | 
| 1507 for (size_t flag_index = 0; flag_index < varying_flags_length; | 1520 for (size_t flag_index = 0; flag_index < varying_flags_length; | 
| 1508 ++flag_index) { | 1521 ++flag_index) { | 
| 1509 if ((bits & (1 << flag_index)) != 0) flags.Add(varying_flags[flag_index]); | 1522 if ((bits & (1 << flag_index)) != 0) flags.Add(varying_flags[flag_index]); | 
| 1510 } | 1523 } | 
| 1511 for (size_t flag_index = 0; flag_index < always_true_flags_length; | 1524 for (size_t flag_index = 0; flag_index < always_true_flags_length; | 
| 1512 ++flag_index) { | 1525 ++flag_index) { | 
| 1513 flags.Add(always_true_flags[flag_index]); | 1526 flags.Add(always_true_flags[flag_index]); | 
| 1514 } | 1527 } | 
| 1515 for (size_t flag_index = 0; flag_index < always_false_flags_length; | 1528 for (size_t flag_index = 0; flag_index < always_false_flags_length; | 
| 1516 ++flag_index) { | 1529 ++flag_index) { | 
| 1517 flags.Remove(always_false_flags[flag_index]); | 1530 flags.Remove(always_false_flags[flag_index]); | 
| 1518 } | 1531 } | 
| 1519 TestParserSyncWithFlags(str, flags, result); | 1532 TestParserSyncWithFlags(str, flags, result, literals); | 
| 1520 } | 1533 } | 
| 1521 } | 1534 } | 
| 1522 | 1535 | 
| 1523 | 1536 | 
| 1524 TEST(ParserSync) { | 1537 TEST(ParserSync) { | 
| 1525 const char* context_data[][2] = { | 1538 const char* context_data[][2] = { | 
| 1526 { "", "" }, | 1539 { "", "" }, | 
| 1527 { "{", "}" }, | 1540 { "{", "}" }, | 
| 1528 { "if (true) ", " else {}" }, | 1541 { "if (true) ", " else {}" }, | 
| 1529 { "if (true) {} else ", "" }, | 1542 { "if (true) {} else ", "" }, | 
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1658 | 1671 | 
| 1659 | 1672 | 
| 1660 void RunParserSyncTest(const char* context_data[][2], | 1673 void RunParserSyncTest(const char* context_data[][2], | 
| 1661 const char* statement_data[], | 1674 const char* statement_data[], | 
| 1662 ParserSyncTestResult result, | 1675 ParserSyncTestResult result, | 
| 1663 const ParserFlag* flags = NULL, | 1676 const ParserFlag* flags = NULL, | 
| 1664 int flags_len = 0, | 1677 int flags_len = 0, | 
| 1665 const ParserFlag* always_true_flags = NULL, | 1678 const ParserFlag* always_true_flags = NULL, | 
| 1666 int always_true_len = 0, | 1679 int always_true_len = 0, | 
| 1667 const ParserFlag* always_false_flags = NULL, | 1680 const ParserFlag* always_false_flags = NULL, | 
| 1668 int always_false_len = 0) { | 1681 int always_false_len = 0, | 
| 1682 const int* expected_literals = NULL) { | |
| 1669 v8::HandleScope handles(CcTest::isolate()); | 1683 v8::HandleScope handles(CcTest::isolate()); | 
| 1670 v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate()); | 1684 v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate()); | 
| 1671 v8::Context::Scope context_scope(context); | 1685 v8::Context::Scope context_scope(context); | 
| 1672 | 1686 | 
| 1673 CcTest::i_isolate()->stack_guard()->SetStackLimit( | 1687 CcTest::i_isolate()->stack_guard()->SetStackLimit( | 
| 1674 i::GetCurrentStackPosition() - 128 * 1024); | 1688 i::GetCurrentStackPosition() - 128 * 1024); | 
| 1675 | 1689 | 
| 1676 // Experimental feature flags should not go here; pass the flags as | 1690 // Experimental feature flags should not go here; pass the flags as | 
| 1677 // always_true_flags if the test needs them. | 1691 // always_true_flags if the test needs them. | 
| 1678 static const ParserFlag default_flags[] = { | 1692 static const ParserFlag default_flags[] = { | 
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1710 int kSuffixLen = i::StrLength(context_data[i][1]); | 1724 int kSuffixLen = i::StrLength(context_data[i][1]); | 
| 1711 int kProgramSize = kPrefixLen + kStatementLen + kSuffixLen; | 1725 int kProgramSize = kPrefixLen + kStatementLen + kSuffixLen; | 
| 1712 | 1726 | 
| 1713 // Plug the source code pieces together. | 1727 // Plug the source code pieces together. | 
| 1714 i::ScopedVector<char> program(kProgramSize + 1); | 1728 i::ScopedVector<char> program(kProgramSize + 1); | 
| 1715 int length = i::SNPrintF(program, | 1729 int length = i::SNPrintF(program, | 
| 1716 "%s%s%s", | 1730 "%s%s%s", | 
| 1717 context_data[i][0], | 1731 context_data[i][0], | 
| 1718 statement_data[j], | 1732 statement_data[j], | 
| 1719 context_data[i][1]); | 1733 context_data[i][1]); | 
| 1734 int expected_literal_count = -1; | |
| 1735 if (expected_literals) { | |
| 1736 expected_literal_count = expected_literals[j]; | |
| 1737 } | |
| 1720 CHECK(length == kProgramSize); | 1738 CHECK(length == kProgramSize); | 
| 1721 TestParserSync(program.start(), | 1739 TestParserSync(program.start(), | 
| 1722 flags, | 1740 flags, | 
| 1723 flags_len, | 1741 flags_len, | 
| 1724 result, | 1742 result, | 
| 1725 always_true_flags, | 1743 always_true_flags, | 
| 1726 always_true_len, | 1744 always_true_len, | 
| 1727 always_false_flags, | 1745 always_false_flags, | 
| 1728 always_false_len); | 1746 always_false_len, | 
| 1747 expected_literal_count); | |
| 1729 } | 1748 } | 
| 1730 } | 1749 } | 
| 1731 delete[] generated_flags; | 1750 delete[] generated_flags; | 
| 1732 } | 1751 } | 
| 1733 | 1752 | 
| 1734 | 1753 | 
| 1735 TEST(ErrorsEvalAndArguments) { | 1754 TEST(ErrorsEvalAndArguments) { | 
| 1736 // Tests that both preparsing and parsing produce the right kind of errors for | 1755 // Tests that both preparsing and parsing produce the right kind of errors for | 
| 1737 // using "eval" and "arguments" as identifiers. Without the strict mode, it's | 1756 // using "eval" and "arguments" as identifiers. Without the strict mode, it's | 
| 1738 // ok to use "eval" or "arguments" as identifiers. With the strict mode, it | 1757 // ok to use "eval" or "arguments" as identifiers. With the strict mode, it | 
| (...skipping 2723 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4462 "tag`foo${\r\n a}`", | 4481 "tag`foo${\r\n a}`", | 
| 4463 "tag`foo${\r a}`", | 4482 "tag`foo${\r a}`", | 
| 4464 "tag`foo${'a' in a}`", | 4483 "tag`foo${'a' in a}`", | 
| 4465 NULL}; | 4484 NULL}; | 
| 4466 static const ParserFlag always_flags[] = {kAllowHarmonyTemplates}; | 4485 static const ParserFlag always_flags[] = {kAllowHarmonyTemplates}; | 
| 4467 RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags, | 4486 RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags, | 
| 4468 arraysize(always_flags)); | 4487 arraysize(always_flags)); | 
| 4469 } | 4488 } | 
| 4470 | 4489 | 
| 4471 | 4490 | 
| 4491 TEST(TaggedTemplateMaterializedLiterals) { | |
| 4492 const char* context_data[][2] = { | |
| 4493 { | |
| 4494 "// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n" | |
| 4495 "// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n" | |
| 4496 "// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n" | |
| 4497 "// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n" | |
| 4498 "// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n" | |
| 4499 "// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n" | |
| 4500 "// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n" | |
| 4501 "// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n" | |
| 4502 "// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n" | |
| 4503 "// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n" | |
| 4504 "// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n" | |
| 4505 "// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n" | |
| 4506 "// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n" | |
| 4507 "'use strict';", | |
| 
caitp (gmail)
2014/12/10 18:17:49
(lldb) p actual_materialized_literals
(int) $16 =
 | |
| 4508 "" | |
| 4509 }, | |
| 4510 { | |
| 4511 "function test(){ 'use strict';" | |
| 4512 " function tag() {}" | |
| 4513 " var a, b, c; return ", | |
| 4514 "}" | |
| 4515 }, | |
| 4516 {NULL, NULL} | |
| 4517 }; | |
| 4518 | |
| 4519 const char* data[] = { | |
| 4520 "tag``;", | |
| 4521 "tag`a`;", | |
| 4522 "tag`a${1}b`;", | |
| 4523 "tag`a${1}b${2}c`;", | |
| 4524 NULL | |
| 4525 }; | |
| 4526 | |
| 4527 const int literals[] = { | |
| 4528 2, | |
| 4529 2, | |
| 4530 2, | |
| 4531 2 | |
| 4532 }; | |
| 4533 | |
| 4534 static const ParserFlag always_flags[] = {kAllowHarmonyTemplates}; | |
| 4535 RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags, | |
| 4536 arraysize(always_flags), NULL, 0, literals); | |
| 4537 } | |
| 4538 | |
| 4539 | |
| 4472 TEST(ScanUnterminatedTemplateLiterals) { | 4540 TEST(ScanUnterminatedTemplateLiterals) { | 
| 4473 const char* context_data[][2] = {{"'use strict';", ""}, | 4541 const char* context_data[][2] = {{"'use strict';", ""}, | 
| 4474 {"function foo(){ 'use strict';" | 4542 {"function foo(){ 'use strict';" | 
| 4475 " var a, b, c; return ", "}"}, | 4543 " var a, b, c; return ", "}"}, | 
| 4476 {NULL, NULL}}; | 4544 {NULL, NULL}}; | 
| 4477 | 4545 | 
| 4478 const char* data[] = { | 4546 const char* data[] = { | 
| 4479 "`no-subst-template", | 4547 "`no-subst-template", | 
| 4480 "`template-head${a}", | 4548 "`template-head${a}", | 
| 4481 "`${a}template-tail", | 4549 "`${a}template-tail", | 
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4531 always_false_flags, arraysize(always_false_flags)); | 4599 always_false_flags, arraysize(always_false_flags)); | 
| 4532 | 4600 | 
| 4533 const char* good_data[] = { | 4601 const char* good_data[] = { | 
| 4534 "let = 1;", | 4602 "let = 1;", | 
| 4535 "for(let = 1;;){}", | 4603 "for(let = 1;;){}", | 
| 4536 NULL}; | 4604 NULL}; | 
| 4537 RunParserSyncTest(context_data, good_data, kSuccess, NULL, 0, | 4605 RunParserSyncTest(context_data, good_data, kSuccess, NULL, 0, | 
| 4538 always_true_flags, arraysize(always_true_flags), | 4606 always_true_flags, arraysize(always_true_flags), | 
| 4539 always_false_flags, arraysize(always_false_flags)); | 4607 always_false_flags, arraysize(always_false_flags)); | 
| 4540 } | 4608 } | 
| OLD | NEW |