Commit e68b5941 authored by Leszek Swirski's avatar Leszek Swirski Committed by Commit Bot

[parser] Remove ParseInfo flag setting after script creation

Previously, ParseInfo would create a script (with CreateScript) based on
its flags, and then set its own flags based on that created script. This
created a weird circular dependency for some of those flags, and
sometimes we would have valid flags before script creation (main thread
compile), while other times not (streaming compile).

Now we set the ParseInfo flags manually and uniformly before script
creation, and check that they match the created script after it has been
created.

Bug: v8:10314
Change-Id: Ife886c77727cd228c944a4f97369a3e6365d8219
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2093433
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Auto-Submit: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/master@{#66648}
parent a05ee6cb
...@@ -720,6 +720,7 @@ bool FinalizeUnoptimizedCode( ...@@ -720,6 +720,7 @@ bool FinalizeUnoptimizedCode(
} }
Handle<Script> script(Script::cast(shared_info->script()), isolate); Handle<Script> script(Script::cast(shared_info->script()), isolate);
parse_info->CheckFlagsForFunctionFromScript(*script);
// Finalize the inner functions' compilation jobs. // Finalize the inner functions' compilation jobs.
for (auto&& inner_job : *inner_function_jobs) { for (auto&& inner_job : *inner_function_jobs) {
...@@ -1149,14 +1150,9 @@ BackgroundCompileTask::BackgroundCompileTask(ScriptStreamingData* streamed_data, ...@@ -1149,14 +1150,9 @@ BackgroundCompileTask::BackgroundCompileTask(ScriptStreamingData* streamed_data,
// will happen in the main thread after parsing. // will happen in the main thread after parsing.
LOG(isolate, ScriptEvent(Logger::ScriptEventType::kStreamingCompile, LOG(isolate, ScriptEvent(Logger::ScriptEventType::kStreamingCompile,
info_->script_id())); info_->script_id()));
info_->set_toplevel(); info_->SetFlagsForToplevelCompile(isolate->is_collecting_type_profile(), true,
info_->set_allow_lazy_parsing(); construct_language_mode(FLAG_use_strict),
if (V8_UNLIKELY(info_->block_coverage_enabled())) { REPLMode::kNo);
info_->AllocateSourceRangeMap();
}
LanguageMode language_mode = construct_language_mode(FLAG_use_strict);
info_->set_language_mode(
stricter_language_mode(info_->language_mode(), language_mode));
language_mode_ = info_->language_mode(); language_mode_ = info_->language_mode();
std::unique_ptr<Utf16CharacterStream> stream(ScannerStream::For( std::unique_ptr<Utf16CharacterStream> stream(ScannerStream::For(
...@@ -1277,10 +1273,10 @@ void BackgroundCompileTask::Run() { ...@@ -1277,10 +1273,10 @@ void BackgroundCompileTask::Run() {
// We don't have the script source or the script origin yet, so use a few // We don't have the script source or the script origin yet, so use a few
// default values for them. These will be fixed up during the main-thread // default values for them. These will be fixed up during the main-thread
// merge. // merge.
Handle<Script> script = info_->CreateScript( Handle<Script> script =
off_thread_isolate_.get(), info_->CreateScript(off_thread_isolate_.get(),
off_thread_isolate_->factory()->empty_string(), ScriptOriginOptions(), off_thread_isolate_->factory()->empty_string(),
REPLMode::kNo, NOT_NATIVES_CODE); ScriptOriginOptions(), NOT_NATIVES_CODE);
Handle<SharedFunctionInfo> outer_function_sfi = Handle<SharedFunctionInfo> outer_function_sfi =
FinalizeTopLevel(info_.get(), script, off_thread_isolate_.get(), FinalizeTopLevel(info_.get(), script, off_thread_isolate_.get(),
...@@ -1594,9 +1590,7 @@ bool Compiler::FinalizeBackgroundCompileTask( ...@@ -1594,9 +1590,7 @@ bool Compiler::FinalizeBackgroundCompileTask(
DCHECK(!shared_info->is_compiled()); DCHECK(!shared_info->is_compiled());
Handle<Script> script(Script::cast(shared_info->script()), isolate); Handle<Script> script(Script::cast(shared_info->script()), isolate);
// TODO(leszeks): We can probably remove this, the parse_info flags should parse_info->CheckFlagsForFunctionFromScript(*script);
// already match the script's.
parse_info->SetFlagsForFunctionFromScript(*script);
task->parser()->UpdateStatistics(isolate, script); task->parser()->UpdateStatistics(isolate, script);
task->parser()->HandleSourceURLComments(isolate, script); task->parser()->HandleSourceURLComments(isolate, script);
...@@ -1703,9 +1697,19 @@ MaybeHandle<JSFunction> Compiler::GetFunctionFromEval( ...@@ -1703,9 +1697,19 @@ MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
allow_eval_cache = true; allow_eval_cache = true;
} else { } else {
ParseInfo parse_info(isolate); ParseInfo parse_info(isolate);
parse_info.SetFlagsForToplevelCompile(isolate->is_collecting_type_profile(),
true, language_mode, REPLMode::kNo);
parse_info.set_eval();
parse_info.set_parse_restriction(restriction);
parse_info.set_parameters_end_pos(parameters_end_pos);
if (!context->IsNativeContext()) {
parse_info.set_outer_scope_info(handle(context->scope_info(), isolate));
}
DCHECK(!parse_info.is_module());
script = parse_info.CreateScript( script = parse_info.CreateScript(
isolate, source, OriginOptionsForEval(outer_info->script())); isolate, source, OriginOptionsForEval(outer_info->script()));
script->set_compilation_type(Script::COMPILATION_TYPE_EVAL);
script->set_eval_from_shared(*outer_info); script->set_eval_from_shared(*outer_info);
if (eval_position == kNoSourcePosition) { if (eval_position == kNoSourcePosition) {
// If the position is missing, attempt to get the code offset by // If the position is missing, attempt to get the code offset by
...@@ -1724,15 +1728,6 @@ MaybeHandle<JSFunction> Compiler::GetFunctionFromEval( ...@@ -1724,15 +1728,6 @@ MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
} }
script->set_eval_from_position(eval_position); script->set_eval_from_position(eval_position);
parse_info.set_eval();
parse_info.set_language_mode(language_mode);
parse_info.set_parse_restriction(restriction);
parse_info.set_parameters_end_pos(parameters_end_pos);
if (!context->IsNativeContext()) {
parse_info.set_outer_scope_info(handle(context->scope_info(), isolate));
}
DCHECK(!parse_info.is_module());
if (!CompileToplevel(&parse_info, script, isolate, &is_compiled_scope) if (!CompileToplevel(&parse_info, script, isolate, &is_compiled_scope)
.ToHandle(&shared_info)) { .ToHandle(&shared_info)) {
return MaybeHandle<JSFunction>(); return MaybeHandle<JSFunction>();
...@@ -2143,8 +2138,8 @@ Handle<Script> NewScript(Isolate* isolate, ParseInfo* parse_info, ...@@ -2143,8 +2138,8 @@ Handle<Script> NewScript(Isolate* isolate, ParseInfo* parse_info,
ScriptOriginOptions origin_options, ScriptOriginOptions origin_options,
NativesFlag natives) { NativesFlag natives) {
// Create a script object describing the script to be compiled. // Create a script object describing the script to be compiled.
Handle<Script> script = parse_info->CreateScript( Handle<Script> script =
isolate, source, origin_options, script_details.repl_mode, natives); parse_info->CreateScript(isolate, source, origin_options, natives);
SetScriptFieldsFromDetails(*script, script_details); SetScriptFieldsFromDetails(*script, script_details);
LOG(isolate, ScriptDetails(*script)); LOG(isolate, ScriptDetails(*script));
return script; return script;
...@@ -2234,19 +2229,24 @@ MaybeHandle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript( ...@@ -2234,19 +2229,24 @@ MaybeHandle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript(
} }
if (maybe_result.is_null()) { if (maybe_result.is_null()) {
ParseInfo parse_info(isolate);
// No cache entry found compile the script. // No cache entry found compile the script.
ParseInfo parse_info(isolate);
parse_info.SetFlagsForToplevelCompile(
isolate->is_collecting_type_profile(), natives == NOT_NATIVES_CODE,
language_mode, script_details.repl_mode);
parse_info.set_module(origin_options.IsModule());
parse_info.set_extension(extension);
parse_info.set_eager(compile_options == ScriptCompiler::kEagerCompile);
Handle<Script> script = NewScript(isolate, &parse_info, source, Handle<Script> script = NewScript(isolate, &parse_info, source,
script_details, origin_options, natives); script_details, origin_options, natives);
DCHECK_IMPLIES(parse_info.collect_type_profile(),
script->IsUserJavaScript());
DCHECK_EQ(parse_info.is_repl_mode(), script->is_repl_mode()); DCHECK_EQ(parse_info.is_repl_mode(), script->is_repl_mode());
// Compile the function and add it to the isolate cache. // Compile the function and add it to the isolate cache.
if (origin_options.IsModule()) parse_info.set_module();
parse_info.set_extension(extension);
parse_info.set_eager(compile_options == ScriptCompiler::kEagerCompile);
parse_info.set_language_mode(
stricter_language_mode(parse_info.language_mode(), language_mode));
maybe_result = maybe_result =
CompileToplevel(&parse_info, script, isolate, &is_compiled_scope); CompileToplevel(&parse_info, script, isolate, &is_compiled_scope);
Handle<SharedFunctionInfo> result; Handle<SharedFunctionInfo> result;
...@@ -2308,9 +2308,9 @@ MaybeHandle<JSFunction> Compiler::GetWrappedFunction( ...@@ -2308,9 +2308,9 @@ MaybeHandle<JSFunction> Compiler::GetWrappedFunction(
IsCompiledScope is_compiled_scope; IsCompiledScope is_compiled_scope;
if (!maybe_result.ToHandle(&wrapped)) { if (!maybe_result.ToHandle(&wrapped)) {
ParseInfo parse_info(isolate); ParseInfo parse_info(isolate);
script = NewScript(isolate, &parse_info, source, script_details, parse_info.SetFlagsForToplevelCompile(isolate->is_collecting_type_profile(),
origin_options, NOT_NATIVES_CODE); true, language_mode,
script->set_wrapped_arguments(*arguments); script_details.repl_mode);
parse_info.set_eval(); // Use an eval scope as declaration scope. parse_info.set_eval(); // Use an eval scope as declaration scope.
parse_info.set_function_syntax_kind(FunctionSyntaxKind::kWrapped); parse_info.set_function_syntax_kind(FunctionSyntaxKind::kWrapped);
...@@ -2323,8 +2323,9 @@ MaybeHandle<JSFunction> Compiler::GetWrappedFunction( ...@@ -2323,8 +2323,9 @@ MaybeHandle<JSFunction> Compiler::GetWrappedFunction(
if (!context->IsNativeContext()) { if (!context->IsNativeContext()) {
parse_info.set_outer_scope_info(handle(context->scope_info(), isolate)); parse_info.set_outer_scope_info(handle(context->scope_info(), isolate));
} }
parse_info.set_language_mode(
stricter_language_mode(parse_info.language_mode(), language_mode)); script = NewScript(isolate, &parse_info, source, script_details,
origin_options, NOT_NATIVES_CODE);
Handle<SharedFunctionInfo> top_level; Handle<SharedFunctionInfo> top_level;
maybe_result = maybe_result =
......
...@@ -828,6 +828,10 @@ enum class REPLMode { ...@@ -828,6 +828,10 @@ enum class REPLMode {
kNo, kNo,
}; };
inline REPLMode construct_repl_mode(bool is_repl_mode) {
return is_repl_mode ? REPLMode::kYes : REPLMode::kNo;
}
// Flag indicating whether code is built into the VM (one of the natives files). // Flag indicating whether code is built into the VM (one of the natives files).
enum NativesFlag { NOT_NATIVES_CODE, EXTENSION_CODE, INSPECTOR_CODE }; enum NativesFlag { NOT_NATIVES_CODE, EXTENSION_CODE, INSPECTOR_CODE };
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "src/ast/ast-source-ranges.h" #include "src/ast/ast-source-ranges.h"
#include "src/ast/ast-value-factory.h" #include "src/ast/ast-value-factory.h"
#include "src/ast/ast.h" #include "src/ast/ast.h"
#include "src/common/globals.h"
#include "src/compiler-dispatcher/compiler-dispatcher.h" #include "src/compiler-dispatcher/compiler-dispatcher.h"
#include "src/heap/heap-inl.h" #include "src/heap/heap-inl.h"
#include "src/logging/counters.h" #include "src/logging/counters.h"
...@@ -175,7 +176,6 @@ template <typename LocalIsolate> ...@@ -175,7 +176,6 @@ template <typename LocalIsolate>
Handle<Script> ParseInfo::CreateScript(LocalIsolate* isolate, Handle<Script> ParseInfo::CreateScript(LocalIsolate* isolate,
Handle<String> source, Handle<String> source,
ScriptOriginOptions origin_options, ScriptOriginOptions origin_options,
REPLMode repl_mode,
NativesFlag natives) { NativesFlag natives) {
// Create a script object describing the script to be compiled. // Create a script object describing the script to be compiled.
Handle<Script> script; Handle<Script> script;
...@@ -198,10 +198,15 @@ Handle<Script> ParseInfo::CreateScript(LocalIsolate* isolate, ...@@ -198,10 +198,15 @@ Handle<Script> ParseInfo::CreateScript(LocalIsolate* isolate,
break; break;
} }
script->set_origin_options(origin_options); script->set_origin_options(origin_options);
script->set_is_repl_mode(repl_mode == REPLMode::kYes); script->set_is_repl_mode(is_repl_mode());
if (is_wrapped_as_function()) {
script->set_wrapped_arguments(*wrapped_arguments());
} else if (is_eval()) {
script->set_compilation_type(Script::COMPILATION_TYPE_EVAL);
}
SetFlagsForToplevelCompileFromScript(isolate, *script, CheckFlagsForToplevelCompileFromScript(*script,
isolate->is_collecting_type_profile()); isolate->is_collecting_type_profile());
return script; return script;
} }
...@@ -209,13 +214,11 @@ template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) ...@@ -209,13 +214,11 @@ template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Handle<Script> ParseInfo::CreateScript(Isolate* isolate, Handle<Script> ParseInfo::CreateScript(Isolate* isolate,
Handle<String> source, Handle<String> source,
ScriptOriginOptions origin_options, ScriptOriginOptions origin_options,
REPLMode repl_mode,
NativesFlag natives); NativesFlag natives);
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
Handle<Script> ParseInfo::CreateScript(OffThreadIsolate* isolate, Handle<Script> ParseInfo::CreateScript(OffThreadIsolate* isolate,
Handle<String> source, Handle<String> source,
ScriptOriginOptions origin_options, ScriptOriginOptions origin_options,
REPLMode repl_mode,
NativesFlag natives); NativesFlag natives);
AstValueFactory* ParseInfo::GetOrCreateAstValueFactory() { AstValueFactory* ParseInfo::GetOrCreateAstValueFactory() {
...@@ -228,6 +231,7 @@ AstValueFactory* ParseInfo::GetOrCreateAstValueFactory() { ...@@ -228,6 +231,7 @@ AstValueFactory* ParseInfo::GetOrCreateAstValueFactory() {
void ParseInfo::AllocateSourceRangeMap() { void ParseInfo::AllocateSourceRangeMap() {
DCHECK(block_coverage_enabled()); DCHECK(block_coverage_enabled());
DCHECK_NULL(source_range_map());
set_source_range_map(new (zone()) SourceRangeMap(zone())); set_source_range_map(new (zone()) SourceRangeMap(zone()));
} }
...@@ -239,15 +243,29 @@ void ParseInfo::set_character_stream( ...@@ -239,15 +243,29 @@ void ParseInfo::set_character_stream(
character_stream_.swap(character_stream); character_stream_.swap(character_stream);
} }
void ParseInfo::SetFlagsForToplevelCompile(bool is_collecting_type_profile,
bool is_user_javascript,
LanguageMode language_mode,
REPLMode repl_mode) {
set_allow_lazy_parsing();
set_toplevel();
set_collect_type_profile(is_user_javascript && is_collecting_type_profile);
set_language_mode(
stricter_language_mode(this->language_mode(), language_mode));
set_repl_mode(repl_mode == REPLMode::kYes);
if (V8_UNLIKELY(is_user_javascript && block_coverage_enabled())) {
AllocateSourceRangeMap();
}
}
template <typename LocalIsolate> template <typename LocalIsolate>
void ParseInfo::SetFlagsForToplevelCompileFromScript( void ParseInfo::SetFlagsForToplevelCompileFromScript(
LocalIsolate* isolate, Script script, bool is_collecting_type_profile) { LocalIsolate* isolate, Script script, bool is_collecting_type_profile) {
SetFlagsForFunctionFromScript(script); SetFlagsForFunctionFromScript(script);
set_allow_lazy_parsing(); SetFlagsForToplevelCompile(is_collecting_type_profile,
set_toplevel(); script.IsUserJavaScript(), language_mode(),
set_collect_type_profile(is_collecting_type_profile && construct_repl_mode(script.is_repl_mode()));
script.IsUserJavaScript());
set_repl_mode(script.is_repl_mode());
if (script.is_wrapped()) { if (script.is_wrapped()) {
set_function_syntax_kind(FunctionSyntaxKind::kWrapped); set_function_syntax_kind(FunctionSyntaxKind::kWrapped);
...@@ -255,6 +273,21 @@ void ParseInfo::SetFlagsForToplevelCompileFromScript( ...@@ -255,6 +273,21 @@ void ParseInfo::SetFlagsForToplevelCompileFromScript(
} }
} }
void ParseInfo::CheckFlagsForToplevelCompileFromScript(
Script script, bool is_collecting_type_profile) {
CheckFlagsForFunctionFromScript(script);
DCHECK(allow_lazy_parsing());
DCHECK(is_toplevel());
DCHECK_EQ(collect_type_profile(),
is_collecting_type_profile && script.IsUserJavaScript());
DCHECK_EQ(is_repl_mode(), script.is_repl_mode());
if (script.is_wrapped()) {
DCHECK_EQ(function_syntax_kind(), FunctionSyntaxKind::kWrapped);
DCHECK_EQ(*wrapped_arguments(), script.wrapped_arguments());
}
}
void ParseInfo::SetFlagsForFunctionFromScript(Script script) { void ParseInfo::SetFlagsForFunctionFromScript(Script script) {
DCHECK(script_id_ == -1 || script_id_ == script.id()); DCHECK(script_id_ == -1 || script_id_ == script.id());
script_id_ = script.id(); script_id_ = script.id();
...@@ -268,6 +301,17 @@ void ParseInfo::SetFlagsForFunctionFromScript(Script script) { ...@@ -268,6 +301,17 @@ void ParseInfo::SetFlagsForFunctionFromScript(Script script) {
} }
} }
void ParseInfo::CheckFlagsForFunctionFromScript(Script script) {
DCHECK_EQ(script_id_, script.id());
// We set "is_eval" for wrapped functions to get an outer declaration scope.
// This is a bit hacky, but ok since we can't be both eval and wrapped.
DCHECK_EQ(is_eval() && !is_wrapped_as_function(),
script.compilation_type() == Script::COMPILATION_TYPE_EVAL);
DCHECK_EQ(is_module(), script.origin_options().IsModule());
DCHECK_IMPLIES(block_coverage_enabled() && script.IsUserJavaScript(),
source_range_map() != nullptr);
}
void ParseInfo::ParallelTasks::Enqueue(ParseInfo* outer_parse_info, void ParseInfo::ParallelTasks::Enqueue(ParseInfo* outer_parse_info,
const AstRawString* function_name, const AstRawString* function_name,
FunctionLiteral* literal) { FunctionLiteral* literal) {
......
...@@ -59,7 +59,6 @@ class V8_EXPORT_PRIVATE ParseInfo { ...@@ -59,7 +59,6 @@ class V8_EXPORT_PRIVATE ParseInfo {
EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
Handle<Script> CreateScript(LocalIsolate* isolate, Handle<String> source, Handle<Script> CreateScript(LocalIsolate* isolate, Handle<String> source,
ScriptOriginOptions origin_options, ScriptOriginOptions origin_options,
REPLMode repl_mode = REPLMode::kNo,
NativesFlag natives = NOT_NATIVES_CODE); NativesFlag natives = NOT_NATIVES_CODE);
// Either returns the ast-value-factory associcated with this ParseInfo, or // Either returns the ast-value-factory associcated with this ParseInfo, or
...@@ -264,7 +263,12 @@ class V8_EXPORT_PRIVATE ParseInfo { ...@@ -264,7 +263,12 @@ class V8_EXPORT_PRIVATE ParseInfo {
ParallelTasks* parallel_tasks() { return parallel_tasks_.get(); } ParallelTasks* parallel_tasks() { return parallel_tasks_.get(); }
void SetFlagsForFunctionFromScript(Script script); void SetFlagsForToplevelCompile(bool is_collecting_type_profile,
bool is_user_javascript,
LanguageMode language_mode,
REPLMode repl_mode);
void CheckFlagsForFunctionFromScript(Script script);
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
// TODO(titzer): these should not be part of ParseInfo. // TODO(titzer): these should not be part of ParseInfo.
...@@ -293,10 +297,14 @@ class V8_EXPORT_PRIVATE ParseInfo { ...@@ -293,10 +297,14 @@ class V8_EXPORT_PRIVATE ParseInfo {
} }
private: private:
void SetFlagsForFunctionFromScript(Script script);
template <typename LocalIsolate> template <typename LocalIsolate>
void SetFlagsForToplevelCompileFromScript(LocalIsolate* isolate, void SetFlagsForToplevelCompileFromScript(LocalIsolate* isolate,
Script script, Script script,
bool is_collecting_type_profile); bool is_collecting_type_profile);
void CheckFlagsForToplevelCompileFromScript(Script script,
bool is_collecting_type_profile);
// Set function info flags based on those in either FunctionLiteral or // Set function info flags based on those in either FunctionLiteral or
// SharedFunctionInfo |function| // SharedFunctionInfo |function|
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment