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