Commit 11a4da99 authored by Ross McIlroy's avatar Ross McIlroy Committed by Commit Bot

[Deflake] Fix data-race relating to accessing FLAG_* on worker thread during background compile

The parser object can now be created on a worker thread, therefore we shouldn't access
global FLAGs during the constructor. Instead move them to the ParseInfo constructor
and set the parser fields based on these. Also avoid accessing always_opt flags in
bytecode-flags - instead accessing it in ParseInfo and propagating to the bytecode
generator.

Also gets rid of unused kUntrustedCodeMitigations flag in UnoptimizedCompilationInfo

BUG=v8:8582

Change-Id: I6e6fdc8cc7865803cb5f334f652abc0e3e4cb3ce
Reviewed-on: https://chromium-review.googlesource.com/c/1375918Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Commit-Queue: Ross McIlroy <rmcilroy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58316}
parent 015203e4
...@@ -30,10 +30,10 @@ uint8_t CreateObjectLiteralFlags::Encode(int runtime_flags, ...@@ -30,10 +30,10 @@ uint8_t CreateObjectLiteralFlags::Encode(int runtime_flags,
} }
// static // static
uint8_t CreateClosureFlags::Encode(bool pretenure, bool is_function_scope) { uint8_t CreateClosureFlags::Encode(bool pretenure, bool is_function_scope,
bool might_always_opt) {
uint8_t result = PretenuredBit::encode(pretenure); uint8_t result = PretenuredBit::encode(pretenure);
if (!FLAG_always_opt && !FLAG_prepare_always_opt && if (!might_always_opt && pretenure == NOT_TENURED && is_function_scope) {
pretenure == NOT_TENURED && is_function_scope) {
result |= FastNewClosureBit::encode(true); result |= FastNewClosureBit::encode(true);
} }
return result; return result;
......
...@@ -43,7 +43,8 @@ class CreateClosureFlags { ...@@ -43,7 +43,8 @@ class CreateClosureFlags {
class PretenuredBit : public BitField8<bool, 0, 1> {}; class PretenuredBit : public BitField8<bool, 0, 1> {};
class FastNewClosureBit : public BitField8<bool, PretenuredBit::kNext, 1> {}; class FastNewClosureBit : public BitField8<bool, PretenuredBit::kNext, 1> {};
static uint8_t Encode(bool pretenure, bool is_function_scope); static uint8_t Encode(bool pretenure, bool is_function_scope,
bool might_always_opt);
private: private:
DISALLOW_IMPLICIT_CONSTRUCTORS(CreateClosureFlags); DISALLOW_IMPLICIT_CONSTRUCTORS(CreateClosureFlags);
......
...@@ -1806,7 +1806,8 @@ void BytecodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) { ...@@ -1806,7 +1806,8 @@ void BytecodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
DCHECK(expr->scope()->outer_scope() == current_scope()); DCHECK(expr->scope()->outer_scope() == current_scope());
uint8_t flags = CreateClosureFlags::Encode( uint8_t flags = CreateClosureFlags::Encode(
expr->pretenure(), closure_scope()->is_function_scope()); expr->pretenure(), closure_scope()->is_function_scope(),
info()->might_always_opt());
size_t entry = builder()->AllocateDeferredConstantPoolEntry(); size_t entry = builder()->AllocateDeferredConstantPoolEntry();
FeedbackSlot slot = GetCachedCreateClosureSlot(expr); FeedbackSlot slot = GetCachedCreateClosureSlot(expr);
builder()->CreateClosure(entry, feedback_index(slot), flags); builder()->CreateClosure(entry, feedback_index(slot), flags);
......
...@@ -52,6 +52,16 @@ ParseInfo::ParseInfo(Isolate* isolate, AccountingAllocator* zone_allocator) ...@@ -52,6 +52,16 @@ ParseInfo::ParseInfo(Isolate* isolate, AccountingAllocator* zone_allocator)
if (isolate->compiler_dispatcher()->IsEnabled()) { if (isolate->compiler_dispatcher()->IsEnabled()) {
parallel_tasks_.reset(new ParallelTasks(isolate->compiler_dispatcher())); parallel_tasks_.reset(new ParallelTasks(isolate->compiler_dispatcher()));
} }
set_might_always_opt(FLAG_always_opt || FLAG_prepare_always_opt);
set_allow_lazy_compile(FLAG_lazy);
set_allow_natives_syntax(FLAG_allow_natives_syntax);
set_allow_harmony_public_fields(FLAG_harmony_public_fields);
set_allow_harmony_static_fields(FLAG_harmony_static_fields);
set_allow_harmony_dynamic_import(FLAG_harmony_dynamic_import);
set_allow_harmony_import_meta(FLAG_harmony_import_meta);
set_allow_harmony_numeric_separator(FLAG_harmony_numeric_separator);
set_allow_harmony_private_fields(FLAG_harmony_private_fields);
set_allow_harmony_private_methods(FLAG_harmony_private_methods);
} }
ParseInfo::ParseInfo(Isolate* isolate) ParseInfo::ParseInfo(Isolate* isolate)
......
...@@ -94,6 +94,26 @@ class V8_EXPORT_PRIVATE ParseInfo { ...@@ -94,6 +94,26 @@ class V8_EXPORT_PRIVATE ParseInfo {
FLAG_ACCESSOR(kRequiresInstanceMembersInitializer, FLAG_ACCESSOR(kRequiresInstanceMembersInitializer,
requires_instance_members_initializer, requires_instance_members_initializer,
set_requires_instance_members_initializer); set_requires_instance_members_initializer);
FLAG_ACCESSOR(kMightAlwaysOpt, might_always_opt, set_might_always_opt)
FLAG_ACCESSOR(kAllowNativeSyntax, allow_natives_syntax,
set_allow_natives_syntax)
FLAG_ACCESSOR(kAllowLazyCompile, allow_lazy_compile, set_allow_lazy_compile)
FLAG_ACCESSOR(kAllowNativeSyntax, allow_native_syntax,
set_allow_native_syntax);
FLAG_ACCESSOR(kAllowHarmonyPublicFields, allow_harmony_public_fields,
set_allow_harmony_public_fields);
FLAG_ACCESSOR(kAllowHarmonyStaticFields, allow_harmony_static_fields,
set_allow_harmony_static_fields);
FLAG_ACCESSOR(kAllowHarmonyDynamicImport, allow_harmony_dynamic_import,
set_allow_harmony_dynamic_import);
FLAG_ACCESSOR(kAllowHarmonyImportMeta, allow_harmony_import_meta,
set_allow_harmony_import_meta);
FLAG_ACCESSOR(kAllowHarmonyNumericSeparator, allow_harmony_numeric_separator,
set_allow_harmony_numeric_separator);
FLAG_ACCESSOR(kAllowHarmonyPrivateFields, allow_harmony_private_fields,
set_allow_harmony_private_fields);
FLAG_ACCESSOR(kAllowHarmonyPrivateMethods, allow_harmony_private_methods,
set_allow_harmony_private_methods);
#undef FLAG_ACCESSOR #undef FLAG_ACCESSOR
void set_parse_restriction(ParseRestriction restriction) { void set_parse_restriction(ParseRestriction restriction) {
...@@ -281,6 +301,16 @@ class V8_EXPORT_PRIVATE ParseInfo { ...@@ -281,6 +301,16 @@ class V8_EXPORT_PRIVATE ParseInfo {
kIsDeclaration = 1 << 16, kIsDeclaration = 1 << 16,
kRequiresInstanceMembersInitializer = 1 << 17, kRequiresInstanceMembersInitializer = 1 << 17,
kContainsAsmModule = 1 << 18, kContainsAsmModule = 1 << 18,
kMightAlwaysOpt = 1 << 19,
kAllowLazyCompile = 1 << 20,
kAllowNativeSyntax = 1 << 21,
kAllowHarmonyPublicFields = 1 << 22,
kAllowHarmonyStaticFields = 1 << 23,
kAllowHarmonyDynamicImport = 1 << 24,
kAllowHarmonyImportMeta = 1 << 25,
kAllowHarmonyNumericSeparator = 1 << 26,
kAllowHarmonyPrivateFields = 1 << 27,
kAllowHarmonyPrivateMethods = 1 << 28
}; };
//------------- Inputs to parsing and scope analysis ----------------------- //------------- Inputs to parsing and scope analysis -----------------------
......
...@@ -407,21 +407,22 @@ Parser::Parser(ParseInfo* info) ...@@ -407,21 +407,22 @@ Parser::Parser(ParseInfo* info)
// of functions without an outer context when setting a breakpoint through // of functions without an outer context when setting a breakpoint through
// Debug::FindSharedFunctionInfoInScript // Debug::FindSharedFunctionInfoInScript
// We also compile eagerly for kProduceExhaustiveCodeCache. // We also compile eagerly for kProduceExhaustiveCodeCache.
bool can_compile_lazily = FLAG_lazy && !info->is_eager(); bool can_compile_lazily = info->allow_lazy_compile() && !info->is_eager();
set_default_eager_compile_hint(can_compile_lazily set_default_eager_compile_hint(can_compile_lazily
? FunctionLiteral::kShouldLazyCompile ? FunctionLiteral::kShouldLazyCompile
: FunctionLiteral::kShouldEagerCompile); : FunctionLiteral::kShouldEagerCompile);
allow_lazy_ = FLAG_lazy && info->allow_lazy_parsing() && !info->is_native() && allow_lazy_ = info->allow_lazy_compile() && info->allow_lazy_parsing() &&
info->extension() == nullptr && can_compile_lazily; !info->is_native() && info->extension() == nullptr &&
set_allow_natives(FLAG_allow_natives_syntax || info->is_native()); can_compile_lazily;
set_allow_harmony_public_fields(FLAG_harmony_public_fields); set_allow_natives(info->allow_natives_syntax() || info->is_native());
set_allow_harmony_static_fields(FLAG_harmony_static_fields); set_allow_harmony_public_fields(info->allow_harmony_public_fields());
set_allow_harmony_dynamic_import(FLAG_harmony_dynamic_import); set_allow_harmony_static_fields(info->allow_harmony_static_fields());
set_allow_harmony_import_meta(FLAG_harmony_import_meta); set_allow_harmony_dynamic_import(info->allow_harmony_dynamic_import());
set_allow_harmony_numeric_separator(FLAG_harmony_numeric_separator); set_allow_harmony_import_meta(info->allow_harmony_import_meta());
set_allow_harmony_private_fields(FLAG_harmony_private_fields); set_allow_harmony_numeric_separator(info->allow_harmony_numeric_separator());
set_allow_harmony_private_methods(FLAG_harmony_private_methods); set_allow_harmony_private_fields(info->allow_harmony_private_fields());
set_allow_harmony_private_methods(info->allow_harmony_private_methods());
for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount; for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
++feature) { ++feature) {
use_counts_[feature] = 0; use_counts_[feature] = 0;
...@@ -2503,7 +2504,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral( ...@@ -2503,7 +2504,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
// parenthesis before the function means that it will be called // parenthesis before the function means that it will be called
// immediately). bar can be parsed lazily, but we need to parse it in a mode // immediately). bar can be parsed lazily, but we need to parse it in a mode
// that tracks unresolved variables. // that tracks unresolved variables.
DCHECK_IMPLIES(parse_lazily(), FLAG_lazy); DCHECK_IMPLIES(parse_lazily(), info()->allow_lazy_compile());
DCHECK_IMPLIES(parse_lazily(), has_error() || allow_lazy_); DCHECK_IMPLIES(parse_lazily(), has_error() || allow_lazy_);
DCHECK_IMPLIES(parse_lazily(), extension_ == nullptr); DCHECK_IMPLIES(parse_lazily(), extension_ == nullptr);
......
...@@ -18,9 +18,7 @@ namespace internal { ...@@ -18,9 +18,7 @@ namespace internal {
UnoptimizedCompilationInfo::UnoptimizedCompilationInfo(Zone* zone, UnoptimizedCompilationInfo::UnoptimizedCompilationInfo(Zone* zone,
ParseInfo* parse_info, ParseInfo* parse_info,
FunctionLiteral* literal) FunctionLiteral* literal)
: flags_(FLAG_untrusted_code_mitigations ? kUntrustedCodeMitigations : 0), : flags_(0), zone_(zone), feedback_vector_spec_(zone) {
zone_(zone),
feedback_vector_spec_(zone) {
// NOTE: The parse_info passed here represents the global information gathered // NOTE: The parse_info passed here represents the global information gathered
// during parsing, but does not represent specific details of the actual // during parsing, but does not represent specific details of the actual
// function literal being compiled for this OptimizedCompilationInfo. As such, // function literal being compiled for this OptimizedCompilationInfo. As such,
...@@ -34,6 +32,7 @@ UnoptimizedCompilationInfo::UnoptimizedCompilationInfo(Zone* zone, ...@@ -34,6 +32,7 @@ UnoptimizedCompilationInfo::UnoptimizedCompilationInfo(Zone* zone,
if (parse_info->is_eval()) MarkAsEval(); if (parse_info->is_eval()) MarkAsEval();
if (parse_info->is_native()) MarkAsNative(); if (parse_info->is_native()) MarkAsNative();
if (parse_info->collect_type_profile()) MarkAsCollectTypeProfile(); if (parse_info->collect_type_profile()) MarkAsCollectTypeProfile();
if (parse_info->might_always_opt()) MarkAsMightAlwaysOpt();
} }
DeclarationScope* UnoptimizedCompilationInfo::scope() const { DeclarationScope* UnoptimizedCompilationInfo::scope() const {
......
...@@ -46,6 +46,9 @@ class V8_EXPORT_PRIVATE UnoptimizedCompilationInfo final { ...@@ -46,6 +46,9 @@ class V8_EXPORT_PRIVATE UnoptimizedCompilationInfo final {
void MarkAsCollectTypeProfile() { SetFlag(kCollectTypeProfile); } void MarkAsCollectTypeProfile() { SetFlag(kCollectTypeProfile); }
bool collect_type_profile() const { return GetFlag(kCollectTypeProfile); } bool collect_type_profile() const { return GetFlag(kCollectTypeProfile); }
void MarkAsMightAlwaysOpt() { SetFlag(kMightAlwaysOpt); }
bool might_always_opt() const { return GetFlag(kMightAlwaysOpt); }
// Accessors for the input data of the function being compiled. // Accessors for the input data of the function being compiled.
FunctionLiteral* literal() const { return literal_; } FunctionLiteral* literal() const { return literal_; }
...@@ -98,7 +101,7 @@ class V8_EXPORT_PRIVATE UnoptimizedCompilationInfo final { ...@@ -98,7 +101,7 @@ class V8_EXPORT_PRIVATE UnoptimizedCompilationInfo final {
kIsEval = 1 << 0, kIsEval = 1 << 0,
kIsNative = 1 << 1, kIsNative = 1 << 1,
kCollectTypeProfile = 1 << 2, kCollectTypeProfile = 1 << 2,
kUntrustedCodeMitigations = 1 << 3, kMightAlwaysOpt = 1 << 3,
}; };
void SetFlag(Flag flag) { flags_ |= flag; } void SetFlag(Flag flag) { flags_ |= flag; }
......
...@@ -1613,10 +1613,10 @@ void TestParserSyncWithFlags(i::Handle<i::String> source, ...@@ -1613,10 +1613,10 @@ void TestParserSyncWithFlags(i::Handle<i::String> source,
// Parse the data // Parse the data
i::FunctionLiteral* function; i::FunctionLiteral* function;
{ {
SetGlobalFlags(flags);
i::Handle<i::Script> script = factory->NewScript(source); i::Handle<i::Script> script = factory->NewScript(source);
i::ParseInfo info(isolate, script); i::ParseInfo info(isolate, script);
info.set_allow_lazy_parsing(flags.Contains(kAllowLazy)); info.set_allow_lazy_parsing(flags.Contains(kAllowLazy));
SetGlobalFlags(flags);
if (is_module) info.set_module(); if (is_module) info.set_module();
i::parsing::ParseProgram(&info, isolate); i::parsing::ParseProgram(&info, isolate);
function = info.literal(); function = info.literal();
...@@ -11050,6 +11050,7 @@ TEST(PrivateNamesSyntaxError) { ...@@ -11050,6 +11050,7 @@ TEST(PrivateNamesSyntaxError) {
LocalContext env; LocalContext env;
auto test = [isolate](const char* program, bool is_lazy) { auto test = [isolate](const char* program, bool is_lazy) {
i::FLAG_harmony_private_fields = true;
i::Factory* const factory = isolate->factory(); i::Factory* const factory = isolate->factory();
i::Handle<i::String> source = i::Handle<i::String> source =
factory->NewStringFromUtf8(i::CStrVector(program)).ToHandleChecked(); factory->NewStringFromUtf8(i::CStrVector(program)).ToHandleChecked();
...@@ -11057,7 +11058,6 @@ TEST(PrivateNamesSyntaxError) { ...@@ -11057,7 +11058,6 @@ TEST(PrivateNamesSyntaxError) {
i::ParseInfo info(isolate, script); i::ParseInfo info(isolate, script);
info.set_allow_lazy_parsing(is_lazy); info.set_allow_lazy_parsing(is_lazy);
i::FLAG_harmony_private_fields = true;
CHECK(i::parsing::ParseProgram(&info, isolate)); CHECK(i::parsing::ParseProgram(&info, isolate));
CHECK(i::Rewriter::Rewrite(&info)); CHECK(i::Rewriter::Rewrite(&info));
CHECK(!i::DeclarationScope::Analyze(&info)); CHECK(!i::DeclarationScope::Analyze(&info));
......
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