Commit 4c7b6dec authored by sreejakshetty@chromium.org's avatar sreejakshetty@chromium.org Committed by Commit Bot

Fix Chrome Crash from TaskTypesFromFieldTrialParam

This CL fixes the crash generated from
blink::scheduler::`anonymous namespace'::TaskTypesFromFieldTrialParam.

Refactors the code for InitializeTaskTypeQueueTraitsMap, lot of the code used
for testing the feature kThrottleAndFreezeTaskTypes is not being used any more.

Bug: 1049800
Change-Id: I8237981149b7518084d480cb79da047b876b8c3d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2057265
Commit-Queue: Sreeja Kamishetty <sreejakshetty@chromium.org>
Reviewed-by: default avatarAlexander Timin <altimin@chromium.org>
Reviewed-by: default avatarScott Haseley <shaseley@chromium.org>
Cr-Commit-Position: refs/heads/master@{#742306}
parent bdbf21a5
......@@ -14,7 +14,6 @@ blink_platform_sources("scheduler") {
"common/cooperative_scheduling_manager.cc",
"common/dummy_schedulers.cc",
"common/event_loop.cc",
"common/features.cc",
"common/features.h",
"common/frame_or_worker_scheduler.cc",
"common/idle_helper.cc",
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/platform/scheduler/common/features.h"
namespace blink {
namespace scheduler {
// Field trial parameters associated with |kThrottleAndFreezeTaskTypes| feature.
// These override the throttleable and freezable QueueTraits bits for the tasks
// specified in the parameters. The parameters are comma separated lists, of the
// the form: "throttleable": "name1,name2", "freezable": "name1,name3". The
// names should be those returned by TaskTypeNames::TaskTypeToString().
const char kThrottleableTaskTypesListParam[] = "ThrottleableTasks";
const char kFreezableTaskTypesListParam[] = "FreezableTasks";
} // namespace scheduler
} // namespace blink
......@@ -194,20 +194,11 @@ const base::Feature kLowPriorityForCrossOriginOnlyWhenLoading{
"BlinkSchedulerLowPriorityForCrossOriginOnlyWhenLoading",
base::FEATURE_DISABLED_BY_DEFAULT};
// Enable setting throttleable and freezable task types from field trial
// parameters.
const base::Feature kThrottleAndFreezeTaskTypes{
"ThrottleAndFreezeTaskTypes", base::FEATURE_DISABLED_BY_DEFAULT};
// Prioritizes loading and compositing tasks while loading.
const base::Feature kPrioritizeCompositingAndLoadingDuringEarlyLoading{
"PrioritizeCompositingAndLoadingDuringEarlyLoading",
base::FEATURE_DISABLED_BY_DEFAULT};
// Parameters for |kThrottleAndFreezeTaskTypes|.
extern const char PLATFORM_EXPORT kThrottleableTaskTypesListParam[];
extern const char PLATFORM_EXPORT kFreezableTaskTypesListParam[];
// Enable setting high priority database task type from field trial parameters.
const base::Feature kHighPriorityDatabaseTaskType{
"HighPriorityDatabaseTaskType", base::FEATURE_DISABLED_BY_DEFAULT};
......
......@@ -78,45 +78,6 @@ void UpdatePriority(MainThreadTaskQueue* task_queue) {
task_queue->SetQueuePriority(frame_scheduler->ComputePriority(task_queue));
}
// Extract a substring from |source| from [start to end), trimming leading
// whitespace.
String ExtractAndTrimString(String source, size_t start, size_t end) {
DCHECK(start < source.length());
DCHECK(end <= source.length());
DCHECK(start <= end);
// Trim whitespace
while (start < end && source[start] == ' ')
++start;
if (start < end)
return source.Substring(start, end - start);
return "";
}
HashSet<String> TaskTypesFromFieldTrialParam(const char* param) {
HashSet<String> result;
String task_type_list =
String::FromUTF8(base::GetFieldTrialParamValueByFeature(
kThrottleAndFreezeTaskTypes, param));
if (!task_type_list.length())
return result;
// Extract the individual names, separated by ",".
size_t pos = 0, start = 0;
while ((pos = task_type_list.find(',', start)) != kNotFound) {
String task_type = ExtractAndTrimString(task_type_list, start, pos);
// Not valid to start with "," or have ",," in the list.
DCHECK(task_type.length());
result.insert(task_type);
start = pos + 1;
}
// Handle the last or only task type name.
String task_type =
ExtractAndTrimString(task_type_list, start, task_type_list.length());
DCHECK(task_type.length());
result.insert(task_type);
return result;
}
} // namespace
FrameSchedulerImpl::PauseSubresourceLoadingHandleImpl::
......@@ -371,42 +332,8 @@ FrameScheduler::FrameType FrameSchedulerImpl::GetFrameType() const {
return frame_type_;
}
void FrameSchedulerImpl::InitializeTaskTypeQueueTraitsMap(
FrameTaskTypeToQueueTraitsArray& frame_task_types_to_queue_traits) {
DCHECK_EQ(frame_task_types_to_queue_traits.size(),
static_cast<size_t>(TaskType::kCount));
// Using std set and strings here because field trial parameters are std
// strings, and we cannot use WTF strings as Blink is not yet initialized.
HashSet<String> throttleable_task_type_names;
HashSet<String> freezable_task_type_names;
if (base::FeatureList::IsEnabled(kThrottleAndFreezeTaskTypes)) {
throttleable_task_type_names =
TaskTypesFromFieldTrialParam(kThrottleableTaskTypesListParam);
freezable_task_type_names =
TaskTypesFromFieldTrialParam(kFreezableTaskTypesListParam);
}
for (size_t i = 0; i < static_cast<size_t>(TaskType::kCount); i++) {
TaskType type = static_cast<TaskType>(i);
base::Optional<QueueTraits> queue_traits =
CreateQueueTraitsForTaskType(type);
if (queue_traits && (!throttleable_task_type_names.IsEmpty() ||
!freezable_task_type_names.IsEmpty())) {
const char* task_type_name = TaskTypeNames::TaskTypeToString(type);
if (!throttleable_task_type_names.Take(task_type_name).IsEmpty())
queue_traits->SetCanBeThrottled(true);
if (freezable_task_type_names.Take(task_type_name).IsEmpty())
queue_traits->SetCanBeFrozen(true);
}
frame_task_types_to_queue_traits[i] = queue_traits;
}
// Protect against configuration errors.
DCHECK(throttleable_task_type_names.IsEmpty());
DCHECK(freezable_task_type_names.IsEmpty());
}
// static
base::Optional<QueueTraits> FrameSchedulerImpl::CreateQueueTraitsForTaskType(
TaskType type) {
QueueTraits FrameSchedulerImpl::CreateQueueTraitsForTaskType(TaskType type) {
// TODO(haraken): Optimize the mapping from TaskTypes to task runners.
// TODO(sreejakshetty): Clean up the PrioritisationType QueueTrait and
// QueueType for kInternalContinueScriptLoading and kInternalContentCapture.
......@@ -515,13 +442,15 @@ base::Optional<QueueTraits> FrameSchedulerImpl::CreateQueueTraitsForTaskType(
case TaskType::kExperimentalWebScheduling:
case TaskType::kCount:
// Not a valid frame-level TaskType.
return base::nullopt;
NOTREACHED();
return QueueTraits();
}
// This method is called for all values between 0 and kCount. TaskType,
// however, has numbering gaps, so even though all enumerated TaskTypes are
// handled in the switch and return a value, we fall through for some values
// of |type|.
return base::nullopt;
NOTREACHED();
return QueueTraits();
}
scoped_refptr<base::SingleThreadTaskRunner> FrameSchedulerImpl::GetTaskRunner(
......@@ -533,17 +462,8 @@ scoped_refptr<base::SingleThreadTaskRunner> FrameSchedulerImpl::GetTaskRunner(
scoped_refptr<MainThreadTaskQueue> FrameSchedulerImpl::GetTaskQueue(
TaskType type) {
DCHECK_LT(static_cast<size_t>(type),
main_thread_scheduler_->scheduling_settings()
.frame_task_types_to_queue_traits.size());
base::Optional<QueueTraits> queue_traits =
main_thread_scheduler_->scheduling_settings()
.frame_task_types_to_queue_traits[static_cast<size_t>(type)];
// We don't have a QueueTraits mapping for |task_type| if it is not a
// frame-level task type.
DCHECK(queue_traits);
return frame_task_queue_controller_->GetTaskQueue(
queue_traits.value());
QueueTraits queue_traits = CreateQueueTraitsForTaskType(type);
return frame_task_queue_controller_->GetTaskQueue(queue_traits);
}
std::unique_ptr<WebResourceLoadingTaskRunnerHandle>
......
......@@ -160,16 +160,6 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler,
MainThreadTaskQueue*,
base::sequence_manager::TaskQueue::QueueEnabledVoter*) override;
using FrameTaskTypeToQueueTraitsArray =
std::array<base::Optional<MainThreadTaskQueue::QueueTraits>,
static_cast<size_t>(TaskType::kCount)>;
// Initializes the mapping from TaskType to QueueTraits for frame-level tasks.
// We control the policy and initialize this, but the map is stored with main
// thread scheduling settings to avoid redundancy.
static void InitializeTaskTypeQueueTraitsMap(
FrameTaskTypeToQueueTraitsArray&);
// Returns the list of active features which currently tracked by the
// scheduler for back-forward cache metrics.
WTF::HashSet<SchedulingPolicy::Feature>
......@@ -269,8 +259,8 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler,
// Create the QueueTraits for a specific TaskType. This returns base::nullopt
// for loading tasks and non-frame-level tasks.
static base::Optional<MainThreadTaskQueue::QueueTraits>
CreateQueueTraitsForTaskType(TaskType);
static MainThreadTaskQueue::QueueTraits CreateQueueTraitsForTaskType(
TaskType);
// Reset the state which should not persist across navigations.
void ResetForNavigation();
......
......@@ -1787,191 +1787,6 @@ TEST_F(FrameSchedulerImplTest, TaskTypeToTaskQueueMapping) {
ForegroundOnlyTaskQueue());
}
class ThrottleAndFreezeTaskTypesExperimentTest : public FrameSchedulerImplTest {
public:
ThrottleAndFreezeTaskTypesExperimentTest(const base::FieldTrialParams& params,
const char* group_name) {
scoped_feature_list().InitAndEnableFeatureWithParameters(
kThrottleAndFreezeTaskTypes, params);
}
};
class ThrottleableAndFreezableTaskTypesTest
: public ThrottleAndFreezeTaskTypesExperimentTest {
public:
ThrottleableAndFreezableTaskTypesTest()
: ThrottleAndFreezeTaskTypesExperimentTest(
base::FieldTrialParams{
// Leading spaces are allowed.
{kThrottleableTaskTypesListParam, "PostedMessage"},
{kFreezableTaskTypesListParam,
"PostedMessage, MediaElementEvent,DOMManipulation"}},
"Group1") {}
};
TEST_F(ThrottleableAndFreezableTaskTypesTest, QueueTraitsFromFieldTrialParams) {
if (base::FeatureList::IsEnabled(blink::features::kStopNonTimersInBackground))
return;
// These tests will start to fail if the default task queues or queue traits
// change for these task types.
// Check that the overrides work.
auto task_queue = GetTaskQueue(TaskType::kPostedMessage);
EXPECT_EQ(task_queue->GetQueueTraits(),
MainThreadTaskQueue::QueueTraits()
.SetCanBeThrottled(true)
.SetCanBeFrozen(true)
.SetCanBePaused(true)
.SetCanRunWhenVirtualTimePaused(false));
task_queue = GetTaskQueue(TaskType::kMediaElementEvent);
EXPECT_EQ(task_queue->GetQueueTraits(),
MainThreadTaskQueue::QueueTraits()
.SetCanBeFrozen(true)
.SetCanBePaused(true)
.SetCanRunWhenVirtualTimePaused(false));
task_queue = GetTaskQueue(TaskType::kDatabaseAccess);
EXPECT_EQ(task_queue->GetQueueTraits(),
MainThreadTaskQueue::QueueTraits()
.SetCanBePaused(true)
.SetCanRunWhenVirtualTimePaused(false));
task_queue = GetTaskQueue(TaskType::kDOMManipulation);
EXPECT_EQ(task_queue->GetQueueTraits(),
MainThreadTaskQueue::QueueTraits()
.SetCanBeFrozen(true)
.SetCanBeDeferred(true)
.SetCanBePaused(true)
.SetCanRunWhenVirtualTimePaused(false));
// Test some task types that were not configured through field trial
// parameters.
task_queue = GetTaskQueue(TaskType::kWebLocks);
EXPECT_EQ(
task_queue->GetQueueTraits(),
MainThreadTaskQueue::QueueTraits().SetCanRunWhenVirtualTimePaused(false));
task_queue = GetTaskQueue(TaskType::kMiscPlatformAPI);
EXPECT_EQ(task_queue->GetQueueTraits(),
MainThreadTaskQueue::QueueTraits()
.SetCanBeDeferred(true)
.SetCanBePaused(true)
.SetCanRunWhenVirtualTimePaused(false));
}
class FreezableOnlyTaskTypesTest
: public ThrottleAndFreezeTaskTypesExperimentTest {
public:
FreezableOnlyTaskTypesTest()
: ThrottleAndFreezeTaskTypesExperimentTest(
base::FieldTrialParams{
{kThrottleableTaskTypesListParam, ""},
{kFreezableTaskTypesListParam,
"PostedMessage,MediaElementEvent,DOMManipulation"}},
"Group2") {}
};
TEST_F(FreezableOnlyTaskTypesTest, QueueTraitsFromFieldTrialParams) {
if (base::FeatureList::IsEnabled(blink::features::kStopNonTimersInBackground))
return;
// These tests will start to fail if the default task queues or queue traits
// change for these task types.
// Check that the overrides work.
auto task_queue = GetTaskQueue(TaskType::kPostedMessage);
EXPECT_EQ(task_queue->GetQueueTraits(), MainThreadTaskQueue::QueueTraits()
.SetCanBeFrozen(true)
.SetCanBePaused(true));
task_queue = GetTaskQueue(TaskType::kMediaElementEvent);
EXPECT_EQ(task_queue->GetQueueTraits(), MainThreadTaskQueue::QueueTraits()
.SetCanBeFrozen(true)
.SetCanBePaused(true));
task_queue = GetTaskQueue(TaskType::kDatabaseAccess);
EXPECT_EQ(task_queue->GetQueueTraits(), MainThreadTaskQueue::QueueTraits()
.SetCanBePaused(true));
task_queue = GetTaskQueue(TaskType::kDOMManipulation);
EXPECT_EQ(task_queue->GetQueueTraits(), MainThreadTaskQueue::QueueTraits()
.SetCanBeFrozen(true)
.SetCanBeDeferred(true)
.SetCanBePaused(true));
// Test some task types that were not configured through field trial
// parameters.
task_queue = GetTaskQueue(TaskType::kWebLocks);
EXPECT_EQ(task_queue->GetQueueTraits(), MainThreadTaskQueue::QueueTraits());
task_queue = GetTaskQueue(TaskType::kMiscPlatformAPI);
EXPECT_EQ(task_queue->GetQueueTraits(), MainThreadTaskQueue::QueueTraits()
.SetCanBeDeferred(true)
.SetCanBePaused(true));
}
class ThrottleableOnlyTaskTypesTest
: public ThrottleAndFreezeTaskTypesExperimentTest {
public:
ThrottleableOnlyTaskTypesTest()
: ThrottleAndFreezeTaskTypesExperimentTest(
base::FieldTrialParams{
{kFreezableTaskTypesListParam, ""},
{kThrottleableTaskTypesListParam, "PostedMessage"}},
"Group3") {}
};
TEST_F(ThrottleableOnlyTaskTypesTest, QueueTraitsFromFieldTrialParams) {
if (base::FeatureList::IsEnabled(blink::features::kStopNonTimersInBackground))
return;
// These tests will start to fail if the default task queues or queue traits
// change for these task types.
// Check that the overrides work.
auto task_queue = GetTaskQueue(TaskType::kPostedMessage);
EXPECT_EQ(task_queue->GetQueueTraits(),
MainThreadTaskQueue::QueueTraits()
.SetCanBeThrottled(true)
.SetCanBePaused(true)
.SetCanRunWhenVirtualTimePaused(false));
task_queue = GetTaskQueue(TaskType::kMediaElementEvent);
EXPECT_EQ(task_queue->GetQueueTraits(),
MainThreadTaskQueue::QueueTraits()
.SetCanBePaused(true)
.SetCanRunWhenVirtualTimePaused(false));
task_queue = GetTaskQueue(TaskType::kDatabaseAccess);
EXPECT_EQ(task_queue->GetQueueTraits(),
MainThreadTaskQueue::QueueTraits()
.SetCanBePaused(true)
.SetCanRunWhenVirtualTimePaused(false));
task_queue = GetTaskQueue(TaskType::kDOMManipulation);
EXPECT_EQ(task_queue->GetQueueTraits(),
MainThreadTaskQueue::QueueTraits()
.SetCanBeDeferred(true)
.SetCanBePaused(true)
.SetCanRunWhenVirtualTimePaused(false));
// Test some task types that were not configured through field trial
// parameters.
task_queue = GetTaskQueue(TaskType::kWebLocks);
EXPECT_EQ(
task_queue->GetQueueTraits(),
MainThreadTaskQueue::QueueTraits().SetCanRunWhenVirtualTimePaused(false));
task_queue = GetTaskQueue(TaskType::kMiscPlatformAPI);
EXPECT_EQ(task_queue->GetQueueTraits(),
MainThreadTaskQueue::QueueTraits()
.SetCanBeDeferred(true)
.SetCanBePaused(true)
.SetCanRunWhenVirtualTimePaused(false));
}
class FrameSchedulerImplDatabaseAccessWithoutHighPriority
: public FrameSchedulerImplTest {
public:
......
......@@ -590,9 +590,6 @@ MainThreadSchedulerImpl::SchedulingSettings::SchedulingSettings() {
}
}
}
FrameSchedulerImpl::InitializeTaskTypeQueueTraitsMap(
frame_task_types_to_queue_traits);
}
MainThreadSchedulerImpl::AnyThread::~AnyThread() = default;
......
......@@ -134,14 +134,6 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
std::array<base::sequence_manager::TaskQueue::QueuePriority,
net::RequestPrioritySize::NUM_PRIORITIES>
net_to_blink_priority;
using FrameTaskTypeToQueueTraitsArray =
std::array<base::Optional<MainThreadTaskQueue::QueueTraits>,
static_cast<size_t>(TaskType::kCount)>;
// Array of QueueTraits indexed by TaskType, containing TaskType::kCount
// entries. This is initialized early with all valid entries. Entries that
// aren't valid task types, i.e. non-frame level, are base::nullopt.
FrameTaskTypeToQueueTraitsArray frame_task_types_to_queue_traits;
};
static const char* UseCaseToString(UseCase use_case);
......
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