diff --git a/src/ast/ast-value-factory.cc b/src/ast/ast-value-factory.cc index 4dab59fdae..94d364ce54 100644 --- a/src/ast/ast-value-factory.cc +++ b/src/ast/ast-value-factory.cc @@ -353,16 +353,18 @@ const AstRawString* AstValueFactory::GetString( } AstConsString* AstValueFactory::NewConsString() { - return zone()->New(); + return single_parse_zone()->New(); } AstConsString* AstValueFactory::NewConsString(const AstRawString* str) { - return NewConsString()->AddString(zone(), str); + return NewConsString()->AddString(single_parse_zone(), str); } AstConsString* AstValueFactory::NewConsString(const AstRawString* str1, const AstRawString* str2) { - return NewConsString()->AddString(zone(), str1)->AddString(zone(), str2); + return NewConsString() + ->AddString(single_parse_zone(), str1) + ->AddString(single_parse_zone(), str2); } template @@ -395,9 +397,9 @@ const AstRawString* AstValueFactory::GetString( [&]() { // Copy literal contents for later comparison. int length = literal_bytes.length(); - byte* new_literal_bytes = zone()->NewArray(length); + byte* new_literal_bytes = ast_raw_string_zone()->NewArray(length); memcpy(new_literal_bytes, literal_bytes.begin(), length); - AstRawString* new_string = zone()->New( + AstRawString* new_string = ast_raw_string_zone()->New( is_one_byte, base::Vector(new_literal_bytes, length), raw_hash_field); CHECK_NOT_NULL(new_string); diff --git a/src/ast/ast-value-factory.h b/src/ast/ast-value-factory.h index d036d99604..aa6a99852f 100644 --- a/src/ast/ast-value-factory.h +++ b/src/ast/ast-value-factory.h @@ -311,24 +311,40 @@ class AstValueFactory { public: AstValueFactory(Zone* zone, const AstStringConstants* string_constants, uint64_t hash_seed) + : AstValueFactory(zone, zone, string_constants, hash_seed) {} + + AstValueFactory(Zone* ast_raw_string_zone, Zone* single_parse_zone, + const AstStringConstants* string_constants, + uint64_t hash_seed) : string_table_(string_constants->string_table()), strings_(nullptr), strings_end_(&strings_), string_constants_(string_constants), empty_cons_string_(nullptr), - zone_(zone), + ast_raw_string_zone_(ast_raw_string_zone), + single_parse_zone_(single_parse_zone), hash_seed_(hash_seed) { - DCHECK_NOT_NULL(zone_); + DCHECK_NOT_NULL(ast_raw_string_zone_); + DCHECK_NOT_NULL(single_parse_zone_); DCHECK_EQ(hash_seed, string_constants->hash_seed()); std::fill(one_character_strings_, one_character_strings_ + arraysize(one_character_strings_), nullptr); - empty_cons_string_ = NewConsString(); + + // Allocate the empty ConsString in the AstRawString Zone instead of the + // single parse Zone like other ConsStrings, because unlike those it can be + // reused across parses. + empty_cons_string_ = ast_raw_string_zone_->New(); } - Zone* zone() const { - DCHECK_NOT_NULL(zone_); - return zone_; + Zone* ast_raw_string_zone() const { + DCHECK_NOT_NULL(ast_raw_string_zone_); + return ast_raw_string_zone_; + } + + Zone* single_parse_zone() const { + DCHECK_NOT_NULL(single_parse_zone_); + return single_parse_zone_; } const AstRawString* GetOneByteString(base::Vector literal) { @@ -394,7 +410,8 @@ class AstValueFactory { static const int kMaxOneCharStringValue = 128; const AstRawString* one_character_strings_[kMaxOneCharStringValue]; - Zone* zone_; + Zone* ast_raw_string_zone_; + Zone* single_parse_zone_; uint64_t hash_seed_; }; diff --git a/src/ast/scopes.cc b/src/ast/scopes.cc index 1375c26f15..a68c6349c9 100644 --- a/src/ast/scopes.cc +++ b/src/ast/scopes.cc @@ -166,17 +166,19 @@ DeclarationScope::DeclarationScope(Zone* zone, Scope* outer_scope, ModuleScope::ModuleScope(DeclarationScope* script_scope, AstValueFactory* avfactory) - : DeclarationScope(avfactory->zone(), script_scope, MODULE_SCOPE, - FunctionKind::kModule), - module_descriptor_(avfactory->zone()->New( - avfactory->zone())) { + : DeclarationScope(avfactory->single_parse_zone(), script_scope, + MODULE_SCOPE, FunctionKind::kModule), + module_descriptor_( + avfactory->single_parse_zone()->New( + avfactory->single_parse_zone())) { set_language_mode(LanguageMode::kStrict); DeclareThis(avfactory); } ModuleScope::ModuleScope(Handle scope_info, AstValueFactory* avfactory) - : DeclarationScope(avfactory->zone(), MODULE_SCOPE, avfactory, scope_info), + : DeclarationScope(avfactory->single_parse_zone(), MODULE_SCOPE, avfactory, + scope_info), module_descriptor_(nullptr) { set_language_mode(LanguageMode::kStrict); } @@ -1623,7 +1625,7 @@ void DeclarationScope::ResetAfterPreparsing(AstValueFactory* ast_value_factory, has_rest_ = false; function_ = nullptr; - DCHECK_NE(zone(), ast_value_factory->zone()); + DCHECK_NE(zone(), ast_value_factory->single_parse_zone()); // Make sure this scope and zone aren't used for allocation anymore. { // Get the zone, while variables_ is still valid @@ -1634,7 +1636,7 @@ void DeclarationScope::ResetAfterPreparsing(AstValueFactory* ast_value_factory, if (aborted) { // Prepare scope for use in the outer zone. - variables_ = VariableMap(ast_value_factory->zone()); + variables_ = VariableMap(ast_value_factory->single_parse_zone()); if (!IsArrowFunction(function_kind_)) { has_simple_parameters_ = true; DeclareDefaultFunctionVariables(ast_value_factory); diff --git a/src/parsing/func-name-inferrer.cc b/src/parsing/func-name-inferrer.cc index b61224fbbb..aff064b8c8 100644 --- a/src/parsing/func-name-inferrer.cc +++ b/src/parsing/func-name-inferrer.cc @@ -60,7 +60,7 @@ AstConsString* FuncNameInferrer::MakeNameFromStack() { continue; } // Add name. Separate names with ".". - Zone* zone = ast_value_factory_->zone(); + Zone* zone = ast_value_factory_->single_parse_zone(); if (!result->IsEmpty()) { result->AddString(zone, ast_value_factory_->dot_string()); } diff --git a/src/parsing/parse-info.cc b/src/parsing/parse-info.cc index 048948ed3c..e706704d26 100644 --- a/src/parsing/parse-info.cc +++ b/src/parsing/parse-info.cc @@ -176,9 +176,12 @@ ReusableUnoptimizedCompileState::ReusableUnoptimizedCompileState( logger_(isolate->logger()), dispatcher_(isolate->lazy_compile_dispatcher()), ast_string_constants_(isolate->ast_string_constants()), - zone_(allocator_, "unoptimized-compile-zone"), + ast_raw_string_zone_(allocator_, + "unoptimized-compile-ast-raw-string-zone"), + single_parse_zone_(allocator_, "unoptimized-compile-parse-zone"), ast_value_factory_( - new AstValueFactory(zone(), ast_string_constants(), hash_seed())) {} + new AstValueFactory(ast_raw_string_zone(), single_parse_zone(), + ast_string_constants(), hash_seed())) {} ReusableUnoptimizedCompileState::ReusableUnoptimizedCompileState( LocalIsolate* isolate) @@ -187,9 +190,12 @@ ReusableUnoptimizedCompileState::ReusableUnoptimizedCompileState( logger_(isolate->main_thread_logger()), dispatcher_(isolate->lazy_compile_dispatcher()), ast_string_constants_(isolate->ast_string_constants()), - zone_(allocator_, "unoptimized-compile-zone"), + ast_raw_string_zone_(allocator_, + "unoptimized-compile-ast-raw-string-zone"), + single_parse_zone_(allocator_, "unoptimized-compile-parse-zone"), ast_value_factory_( - new AstValueFactory(zone(), ast_string_constants(), hash_seed())) {} + new AstValueFactory(ast_raw_string_zone(), single_parse_zone(), + ast_string_constants(), hash_seed())) {} ReusableUnoptimizedCompileState::~ReusableUnoptimizedCompileState() = default; @@ -235,7 +241,7 @@ ParseInfo::ParseInfo(LocalIsolate* isolate, const UnoptimizedCompileFlags flags, : ParseInfo(flags, state, reusable_state, stack_limit, isolate->runtime_call_stats()) {} -ParseInfo::~ParseInfo() = default; +ParseInfo::~ParseInfo() { reusable_state_->NotifySingleParseCompleted(); } DeclarationScope* ParseInfo::scope() const { return literal()->scope(); } diff --git a/src/parsing/parse-info.h b/src/parsing/parse-info.h index 8ceccdd514..b497bfb752 100644 --- a/src/parsing/parse-info.h +++ b/src/parsing/parse-info.h @@ -184,7 +184,21 @@ class V8_EXPORT_PRIVATE ReusableUnoptimizedCompileState { explicit ReusableUnoptimizedCompileState(LocalIsolate* isolate); ~ReusableUnoptimizedCompileState(); - Zone* zone() { return &zone_; } + // The AstRawString Zone stores the AstRawStrings in the AstValueFactory that + // can be reused across parses, and thereforce should stay alive between + // parses that reuse this reusable state and its AstValueFactory. + Zone* ast_raw_string_zone() { return &ast_raw_string_zone_; } + + // The single parse Zone stores the data of a single parse, and can be cleared + // when that parse completes. + // + // This is in "reusable" state despite being wiped per-parse, because it + // allows us to reuse the Zone itself, and e.g. keep the same single parse + // Zone pointer in the AstValueFactory. + Zone* single_parse_zone() { return &single_parse_zone_; } + + void NotifySingleParseCompleted() { single_parse_zone_.ReleaseMemory(); } + AstValueFactory* ast_value_factory() const { return ast_value_factory_.get(); } @@ -202,7 +216,8 @@ class V8_EXPORT_PRIVATE ReusableUnoptimizedCompileState { Logger* logger_; LazyCompileDispatcher* dispatcher_; const AstStringConstants* ast_string_constants_; - Zone zone_; + Zone ast_raw_string_zone_; + Zone single_parse_zone_; std::unique_ptr ast_value_factory_; }; @@ -226,7 +241,7 @@ class V8_EXPORT_PRIVATE ParseInfo { ScriptOriginOptions origin_options, NativesFlag natives = NOT_NATIVES_CODE); - Zone* zone() const { return reusable_state_->zone(); } + Zone* zone() const { return reusable_state_->single_parse_zone(); } const UnoptimizedCompileFlags& flags() const { return flags_; } diff --git a/src/parsing/parser-base.h b/src/parsing/parser-base.h index b44a5407a6..f15cce5421 100644 --- a/src/parsing/parser-base.h +++ b/src/parsing/parser-base.h @@ -300,7 +300,7 @@ class ParserBase { void ResetFunctionLiteralId() { function_literal_id_ = 0; } // The Zone where the parsing outputs are stored. - Zone* main_zone() const { return ast_value_factory()->zone(); } + Zone* main_zone() const { return ast_value_factory()->single_parse_zone(); } // The current Zone, which might be the main zone or a temporary Zone. Zone* zone() const { return zone_; } diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc index f2b3842774..5501c5f80a 100644 --- a/test/cctest/test-parsing.cc +++ b/test/cctest/test-parsing.cc @@ -3657,7 +3657,6 @@ TEST(MaybeAssignedParameters) { base::ScopedVector program(Utf8LengthHelper(source) + Utf8LengthHelper(suffix) + 1); base::SNPrintF(program, "%s%s", source, suffix); - std::unique_ptr info; printf("%s\n", program.begin()); v8::Local v = CompileRun(program.begin()); i::Handle o = v8::Utils::OpenHandle(*v); @@ -3668,16 +3667,15 @@ TEST(MaybeAssignedParameters) { i::UnoptimizedCompileFlags flags = i::UnoptimizedCompileFlags::ForFunctionCompile(isolate, *shared); flags.set_allow_lazy_parsing(allow_lazy); - info = std::make_unique(isolate, flags, &state, - &reusable_state); - CHECK_PARSE_FUNCTION(info.get(), shared, isolate); + i::ParseInfo info(isolate, flags, &state, &reusable_state); + CHECK_PARSE_FUNCTION(&info, shared, isolate); - i::Scope* scope = info->literal()->scope(); + i::Scope* scope = info.literal()->scope(); CHECK(!scope->AsDeclarationScope()->was_lazily_parsed()); CHECK_NULL(scope->sibling()); CHECK(scope->is_function_scope()); const i::AstRawString* var_name = - info->ast_value_factory()->GetOneByteString("arg"); + info.ast_value_factory()->GetOneByteString("arg"); i::Variable* var = scope->LookupForTesting(var_name); CHECK(var->is_used() || !assigned); bool is_maybe_assigned = var->maybe_assigned() == i::kMaybeAssigned; @@ -3708,12 +3706,11 @@ static void TestMaybeAssigned(Input input, const char* variable, bool module, i::UnoptimizedCompileFlags::ForScriptCompile(isolate, *script); flags.set_is_module(module); flags.set_allow_lazy_parsing(allow_lazy_parsing); - std::unique_ptr info = - std::make_unique(isolate, flags, &state, &reusable_state); + i::ParseInfo info(isolate, flags, &state, &reusable_state); - CHECK_PARSE_PROGRAM(info.get(), script, isolate); + CHECK_PARSE_PROGRAM(&info, script, isolate); - i::Scope* scope = info->literal()->scope(); + i::Scope* scope = info.literal()->scope(); CHECK(!scope->AsDeclarationScope()->was_lazily_parsed()); CHECK_NULL(scope->sibling()); CHECK(module ? scope->is_module_scope() : scope->is_script_scope()); @@ -3723,7 +3720,7 @@ static void TestMaybeAssigned(Input input, const char* variable, bool module, // Find the variable. scope = i::ScopeTestHelper::FindScope(scope, input.location); const i::AstRawString* var_name = - info->ast_value_factory()->GetOneByteString(variable); + info.ast_value_factory()->GetOneByteString(variable); var = scope->LookupForTesting(var_name); }