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 8387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8398 const char* data[] = { | 8398 const char* data[] = { |
8399 "const arguments = 1", | 8399 "const arguments = 1", |
8400 "let arguments", | 8400 "let arguments", |
8401 "var arguments", | 8401 "var arguments", |
8402 NULL | 8402 NULL |
8403 }; | 8403 }; |
8404 // clang-format on | 8404 // clang-format on |
8405 RunParserSyncTest(context_data, data, kSuccess); | 8405 RunParserSyncTest(context_data, data, kSuccess); |
8406 } | 8406 } |
8407 } | 8407 } |
| 8408 |
| 8409 namespace v8 { |
| 8410 namespace internal { |
| 8411 |
| 8412 class ScopeTestHelper { |
| 8413 public: |
| 8414 static bool MustAllocateInContext(Variable* var) { |
| 8415 return var->scope()->MustAllocateInContext(var); |
| 8416 } |
| 8417 }; |
| 8418 } // namespace internal |
| 8419 } // namespace v8 |
| 8420 |
| 8421 // Test that lazily parsed inner functions don't result in overly pessimistic |
| 8422 // context allocations. |
| 8423 TEST(NoPessimisticContextAllocation) { |
| 8424 i::FLAG_lazy_inner_functions = true; |
| 8425 i::Isolate* isolate = CcTest::i_isolate(); |
| 8426 i::Factory* factory = isolate->factory(); |
| 8427 i::HandleScope scope(isolate); |
| 8428 LocalContext env; |
| 8429 |
| 8430 const char* prefix = "(function outer() { var my_var; "; |
| 8431 const char* suffix = " })();"; |
| 8432 int prefix_len = Utf8LengthHelper(prefix); |
| 8433 int suffix_len = Utf8LengthHelper(suffix); |
| 8434 |
| 8435 struct { |
| 8436 const char* source; |
| 8437 bool ctxt_allocate; |
| 8438 } inners[] = { |
| 8439 // Context allocating because we need to: |
| 8440 {"function inner() { my_var; }", true}, |
| 8441 {"function inner() { eval(\"foo\"); }", true}, |
| 8442 // No pessimistic context allocation: |
| 8443 {"function inner() { var my_var; my_var; }", false}, |
| 8444 {"function inner() { var my_var; }", false}, |
| 8445 {"function inner() { let my_var; my_var; }", false}, |
| 8446 {"function inner() { let my_var; }", false}, |
| 8447 {"function inner() { const my_var = 0; my_var; }", false}, |
| 8448 {"function inner() { const my_var = 0; }", false}, |
| 8449 {"function inner(my_var) { my_var; }", false}, |
| 8450 {"function inner(my_var) { }", false}, |
| 8451 {"function inner(...my_var) { my_var; }", false}, |
| 8452 {"function inner(...my_var) { }", false}, |
| 8453 {"function inner([a, my_var, b]) { my_var; }", false}, |
| 8454 {"function inner([a, my_var, b]) { }", false}, |
| 8455 {"function inner({x: my_var}) { my_var; }", false}, |
| 8456 {"function inner({x: my_var}) { }", false}, |
| 8457 {"function inner({my_var}) { my_var; }", false}, |
| 8458 {"function inner({my_var}) { }", false}, |
| 8459 {"my_var => my_var; ", false}, |
| 8460 {"my_var => { }", false}, |
| 8461 {"(...my_var) => my_var;", false}, |
| 8462 {"(...my_var) => { }", false}, |
| 8463 {"([a, my_var, b]) => my_var;", false}, |
| 8464 {"([a, my_var, b]) => { }", false}, |
| 8465 {"({x: my_var}) => my_var;", false}, |
| 8466 {"({x: my_var}) => { }", false}, |
| 8467 {"({my_var}) => my_var;", false}, |
| 8468 {"({my_var}) => { }", false}, |
| 8469 {"function inner() { try { } catch (my_var) { } }", false}, |
| 8470 {"function inner() { class my_var {}; }", false}, |
| 8471 // In the following cases we still context allocate pessimistically: |
| 8472 {"function inner() { function my_var() {} my_var; }", true}, |
| 8473 {"function inner() { if (true) { function my_var() {} } my_var; }", |
| 8474 true}, |
| 8475 {"function inner() { try { } catch (my_var) { my_var; } }", true}, |
| 8476 {"function inner() { for (my_var of {}) { my_var; } }", true}, |
| 8477 {"function inner() { for (my_var of {}) { } }", true}, |
| 8478 {"function inner() { for (my_var in []) { my_var; } }", true}, |
| 8479 {"function inner() { for (my_var in []) { } }", true}, |
| 8480 {"function inner() { class my_var {}; my_var }", true}, |
| 8481 }; |
| 8482 |
| 8483 for (unsigned i = 0; i < arraysize(inners); ++i) { |
| 8484 const char* inner = inners[i].source; |
| 8485 int inner_len = Utf8LengthHelper(inner); |
| 8486 int len = prefix_len + inner_len + suffix_len; |
| 8487 i::ScopedVector<char> program(len + 1); |
| 8488 i::SNPrintF(program, "%s%s%s", prefix, inner, suffix); |
| 8489 i::Handle<i::String> source = |
| 8490 factory->InternalizeUtf8String(program.start()); |
| 8491 source->PrintOn(stdout); |
| 8492 printf("\n"); |
| 8493 |
| 8494 i::Handle<i::Script> script = factory->NewScript(source); |
| 8495 i::Zone zone(isolate->allocator(), ZONE_NAME); |
| 8496 i::ParseInfo info(&zone, script); |
| 8497 |
| 8498 i::Parser parser(&info); |
| 8499 CHECK(parser.Parse(&info)); |
| 8500 CHECK(i::Compiler::Analyze(&info)); |
| 8501 CHECK(info.literal() != NULL); |
| 8502 |
| 8503 i::Scope* scope = info.literal()->scope()->inner_scope(); |
| 8504 DCHECK_NOT_NULL(scope); |
| 8505 DCHECK_NULL(scope->sibling()); |
| 8506 DCHECK(scope->is_function_scope()); |
| 8507 const i::AstRawString* var_name = |
| 8508 info.ast_value_factory()->GetOneByteString("my_var"); |
| 8509 i::Variable* var = scope->Lookup(var_name); |
| 8510 CHECK_EQ(inners[i].ctxt_allocate, |
| 8511 i::ScopeTestHelper::MustAllocateInContext(var)); |
| 8512 } |
| 8513 } |
OLD | NEW |