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 8679 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8690 } | 8690 } |
8691 | 8691 |
8692 namespace v8 { | 8692 namespace v8 { |
8693 namespace internal { | 8693 namespace internal { |
8694 | 8694 |
8695 class ScopeTestHelper { | 8695 class ScopeTestHelper { |
8696 public: | 8696 public: |
8697 static bool MustAllocateInContext(Variable* var) { | 8697 static bool MustAllocateInContext(Variable* var) { |
8698 return var->scope()->MustAllocateInContext(var); | 8698 return var->scope()->MustAllocateInContext(var); |
8699 } | 8699 } |
| 8700 |
| 8701 static void CompareScopeToData(Scope* scope, const PreParsedScopeData* data, |
| 8702 size_t& index) { |
| 8703 CHECK_EQ(data->backing_store_[index++], scope->scope_type()); |
| 8704 CHECK_EQ(data->backing_store_[index++], scope->start_position()); |
| 8705 CHECK_EQ(data->backing_store_[index++], scope->end_position()); |
| 8706 |
| 8707 int inner_scope_count = 0; |
| 8708 for (Scope* inner = scope->inner_scope(); inner != nullptr; |
| 8709 inner = inner->sibling()) { |
| 8710 ++inner_scope_count; |
| 8711 } |
| 8712 CHECK_EQ(data->backing_store_[index++], inner_scope_count); |
| 8713 |
| 8714 // Variable count is 0. TODO(marja): implement. |
| 8715 CHECK_EQ(data->backing_store_[index++], 0); |
| 8716 |
| 8717 for (Scope* inner = scope->inner_scope(); inner != nullptr; |
| 8718 inner = inner->sibling()) { |
| 8719 CompareScopeToData(inner, data, index); |
| 8720 } |
| 8721 } |
8700 }; | 8722 }; |
8701 } // namespace internal | 8723 } // namespace internal |
8702 } // namespace v8 | 8724 } // namespace v8 |
8703 | 8725 |
8704 // Test that lazily parsed inner functions don't result in overly pessimistic | 8726 // Test that lazily parsed inner functions don't result in overly pessimistic |
8705 // context allocations. | 8727 // context allocations. |
8706 TEST(NoPessimisticContextAllocation) { | 8728 TEST(NoPessimisticContextAllocation) { |
8707 i::FLAG_lazy_inner_functions = true; | 8729 i::FLAG_lazy_inner_functions = true; |
8708 i::Isolate* isolate = CcTest::i_isolate(); | 8730 i::Isolate* isolate = CcTest::i_isolate(); |
8709 i::Factory* factory = isolate->factory(); | 8731 i::Factory* factory = isolate->factory(); |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8968 DCHECK_NULL(scope->sibling()); | 8990 DCHECK_NULL(scope->sibling()); |
8969 DCHECK(scope->is_function_scope()); | 8991 DCHECK(scope->is_function_scope()); |
8970 const i::AstRawString* var_name = | 8992 const i::AstRawString* var_name = |
8971 info.ast_value_factory()->GetOneByteString("my_var"); | 8993 info.ast_value_factory()->GetOneByteString("my_var"); |
8972 i::Variable* var = scope->Lookup(var_name); | 8994 i::Variable* var = scope->Lookup(var_name); |
8973 CHECK_EQ(inners[i].ctxt_allocate, | 8995 CHECK_EQ(inners[i].ctxt_allocate, |
8974 i::ScopeTestHelper::MustAllocateInContext(var)); | 8996 i::ScopeTestHelper::MustAllocateInContext(var)); |
8975 } | 8997 } |
8976 } | 8998 } |
8977 } | 8999 } |
| 9000 |
| 9001 TEST(PreParserScopeAnalysis) { |
| 9002 i::FLAG_lazy_inner_functions = true; |
| 9003 i::FLAG_preparser_scope_analysis = true; |
| 9004 i::Isolate* isolate = CcTest::i_isolate(); |
| 9005 i::Factory* factory = isolate->factory(); |
| 9006 i::HandleScope scope(isolate); |
| 9007 LocalContext env; |
| 9008 |
| 9009 const char* prefix = "(function outer() { "; |
| 9010 const char* suffix = " })();"; |
| 9011 int prefix_len = Utf8LengthHelper(prefix); |
| 9012 int suffix_len = Utf8LengthHelper(suffix); |
| 9013 |
| 9014 // The scope start positions must match; note the extra space in lazy_inner. |
| 9015 const char* lazy_inner = " function inner(%s) { %s }"; |
| 9016 const char* eager_inner = "(function inner(%s) { %s })()"; |
| 9017 |
| 9018 struct { |
| 9019 const char* params; |
| 9020 const char* source; |
| 9021 } inners[] = { |
| 9022 {"", "var1"}, |
| 9023 {"", "if (true) {}"}, |
| 9024 {"", "function f1() {}"}, |
| 9025 {"", "if (true) { function f1() {} }"}, |
| 9026 }; |
| 9027 |
| 9028 for (unsigned i = 0; i < arraysize(inners); ++i) { |
| 9029 // First compile with the lazy inner function and extract the scope data. |
| 9030 const char* inner_function = lazy_inner; |
| 9031 int inner_function_len = Utf8LengthHelper(inner_function) - 4; |
| 9032 |
| 9033 int params_len = Utf8LengthHelper(inners[i].params); |
| 9034 int source_len = Utf8LengthHelper(inners[i].source); |
| 9035 int len = |
| 9036 prefix_len + inner_function_len + params_len + source_len + suffix_len; |
| 9037 |
| 9038 i::ScopedVector<char> lazy_program(len + 1); |
| 9039 i::SNPrintF(lazy_program, "%s", prefix); |
| 9040 i::SNPrintF(lazy_program + prefix_len, inner_function, inners[i].params, |
| 9041 inners[i].source); |
| 9042 i::SNPrintF(lazy_program + prefix_len + inner_function_len + params_len + |
| 9043 source_len, |
| 9044 "%s", suffix); |
| 9045 |
| 9046 i::Handle<i::String> source = |
| 9047 factory->InternalizeUtf8String(lazy_program.start()); |
| 9048 source->PrintOn(stdout); |
| 9049 printf("\n"); |
| 9050 |
| 9051 i::Handle<i::Script> script = factory->NewScript(source); |
| 9052 i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME); |
| 9053 i::ParseInfo lazy_info(&zone, script); |
| 9054 |
| 9055 // No need to run scope analysis; preparser scope data is produced when |
| 9056 // parsing. |
| 9057 CHECK(i::parsing::ParseProgram(&lazy_info)); |
| 9058 |
| 9059 // Then parse eagerly and check against the scope data. |
| 9060 inner_function = eager_inner; |
| 9061 inner_function_len = Utf8LengthHelper(inner_function) - 4; |
| 9062 len = |
| 9063 prefix_len + inner_function_len + params_len + source_len + suffix_len; |
| 9064 |
| 9065 i::ScopedVector<char> eager_program(len + 1); |
| 9066 i::SNPrintF(eager_program, "%s", prefix); |
| 9067 i::SNPrintF(eager_program + prefix_len, inner_function, inners[i].params, |
| 9068 inners[i].source); |
| 9069 i::SNPrintF(eager_program + prefix_len + inner_function_len + params_len + |
| 9070 source_len, |
| 9071 "%s", suffix); |
| 9072 |
| 9073 source = factory->InternalizeUtf8String(eager_program.start()); |
| 9074 source->PrintOn(stdout); |
| 9075 printf("\n"); |
| 9076 |
| 9077 script = factory->NewScript(source); |
| 9078 i::ParseInfo eager_info(&zone, script); |
| 9079 |
| 9080 CHECK(i::parsing::ParseProgram(&eager_info)); |
| 9081 CHECK(i::Compiler::Analyze(&eager_info)); |
| 9082 |
| 9083 i::Scope* scope = |
| 9084 eager_info.literal()->scope()->inner_scope()->inner_scope(); |
| 9085 DCHECK_NOT_NULL(scope); |
| 9086 DCHECK_NULL(scope->sibling()); |
| 9087 DCHECK(scope->is_function_scope()); |
| 9088 |
| 9089 size_t index = 0; |
| 9090 i::ScopeTestHelper::CompareScopeToData( |
| 9091 scope, lazy_info.preparsed_scope_data(), index); |
| 9092 } |
| 9093 } |
OLD | NEW |