diff --git a/DEPS b/DEPS index 05306e8..6a5ec14 100644 --- a/DEPS +++ b/DEPS
@@ -80,6 +80,9 @@ # build ARC++ support libraries. 'checkout_android_native_support': 'checkout_android or checkout_chromeos', + # By default, do not check out Cast3P. + 'checkout_cast3p': False, + # By default, do not check out Chromium autofill captured sites test # dependencies. These dependencies include very large numbers of very # large web capture files. Captured sites test dependencies are also @@ -228,19 +231,19 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '71cb9725180a28eeec13aafbf17f901166b191b8', + 'skia_revision': 'ff733b3f39098600fd5461dd71778e249cd7d78c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '853a0bd84a0f6963fb38ddb566bc8a033232b1f2', + 'v8_revision': '8ce61b9d92e07ad3c63da3547bbbf0c8cbbbff3a', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': 'afe0dd9edf76dd798af7615e347725afd284924c', + 'angle_revision': '9994110baeb4741382849c8a909bed00dedd3508', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': '054ff0cd5b7ecaab630dfcf8814ec9e5c88e6a6b', + 'swiftshader_revision': 'efbbb2f07b3642b570472f01ed75b04bf1eeb4af', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. @@ -303,7 +306,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling devtools-frontend # and whatever else without interference from each other. - 'devtools_frontend_revision': 'db4c9684f0c5d9f59def0da90f80372cba6f2195', + 'devtools_frontend_revision': '10474d9f680fe879beb6bfcc21e9baade89d3845', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libprotobuf-mutator # and whatever else without interference from each other. @@ -339,11 +342,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'shaderc_revision': 'c42db5815fad0424f0f1311de1eec92cdd77203d', + 'shaderc_revision': 'f6d6dddfabfec1041c0dfb8e7ff3608a5f82227c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': '30eeac75784aac8c3a2df867ee21d8188f5f3fad', + 'dawn_revision': '4420ecc71e275f4675e981610067b426c0282f07', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -616,7 +619,7 @@ }, 'src/ios/third_party/material_components_ios/src': { - 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '95c4fb354ed585db2daeb2d1dc6c3f758b480bce', + 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'e1c88bec2a37dcc386f4484a758ccfef6615bcbf', 'condition': 'checkout_ios', }, @@ -626,7 +629,7 @@ }, 'src/ios/third_party/material_internationalization_ios/src': { - 'url': Var('chromium_git') + '/external/github.com/material-foundation/material-internationalization-ios.git' + '@' + '8e4a1eaf376e8a6d40d0f13c3c67b124dc63e0d9', + 'url': Var('chromium_git') + '/external/github.com/material-foundation/material-internationalization-ios.git' + '@' + '4f71b756289a90e7e559d1851fd1c426a183dbc8', 'condition': 'checkout_ios', }, @@ -773,7 +776,7 @@ 'packages': [ { 'package': 'chromium/third_party/androidx', - 'version': 'L-v7Lp_nVRhjXf1b1XWKe2CPp3Vd5WuJqb5nShZ7ZOoC', + 'version': '3nbPFkI2v6vg5aJKxTomy2I4gV5g7AvfZDQpjRlwSroC', }, ], 'condition': 'checkout_android', @@ -918,6 +921,17 @@ 'dep_type': 'cipd', }, + 'src/third_party/cast_core/prebuilts': { + 'packages': [ + { + 'package': 'cast3p/cast_core/package_qa_vizio_castos_armv7a.tar', + 'version': 'ZOzcgmEj32ltQEYvSSBfLbwcEo4MA_qtruinWrbbpGAC', + }, + ], + 'condition': 'checkout_cast3p', + 'dep_type': 'cipd', + }, + 'src/third_party/google_benchmark/src': { 'url': Var('chromium_git') + '/external/github.com/google/benchmark.git' + '@' + 'e991355c02b93fe17713efe04cbc2e278e00fdbd', 'condition': 'checkout_google_benchmark', @@ -1476,7 +1490,7 @@ 'packages': [ { 'package': 'fuchsia/third_party/aemu/linux-amd64', - 'version': 'y7X4kitLsRPSZc6ksrVllZRbH7mvEXlq9-4wOg7zR5cC' + 'version': 'RcTpHQNhrkxG2Y4BJhRct_IdU43YwygAOkCuplrWcKQC' }, ], 'condition': 'host_os == "linux" and checkout_fuchsia', @@ -1619,7 +1633,7 @@ Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'b0291fd966b55a5efc496772555b94842bde1085', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '889ffa4d26fa0059542c7cf5ae2ec43a687b749c', + Var('webrtc_git') + '/src.git' + '@' + '9f0b3330764eb4d373d8e2c9775d250ed10cb9f4', 'src/third_party/libgifcodec': Var('skia_git') + '/libgifcodec' + '@'+ Var('libgifcodec_revision'), @@ -1677,7 +1691,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@7066c1b6405040f6890630c0de83c2b237cd77c8', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@5d74f86711c757b493b11e623f3891828001cebf', 'condition': 'checkout_src_internal', }, @@ -1685,7 +1699,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/eche_app/app', - 'version': 'vYdpaWIxUzRyiSS-wpZmGmxnu79kgN9q_kb2w2YlFOoC', + 'version': 'yesLEVtJiCOq14OvyOrnxowJ-3QNm1AJrrX-gyZPIMAC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -4588,6 +4602,17 @@ ], }, + # Download Cast Web Runtime + { + 'name': 'cast_web_runtime', + 'pattern': '.', + 'action': [ + 'python3', + 'src/tools/cast3p/update_runtime.py', + ], + 'condition': 'checkout_cast3p', + }, + { 'name': 'Generate location tags for tests', 'pattern': '.',
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index 0071a5db..7bf739f9 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -2509,6 +2509,7 @@ "wm/overlay_layout_manager_unittest.cc", "wm/overview/cleanup_animation_observer_unittest.cc", "wm/overview/delayed_animation_observer_impl_unittest.cc", + "wm/overview/desks_templates/desks_templates_unittest.cc", "wm/overview/overview_controller_unittest.cc", "wm/overview/overview_grid_unittest.cc", "wm/overview/overview_highlight_controller_unittest.cc", @@ -2636,6 +2637,7 @@ "//components/account_id", "//components/app_restore", "//components/arc:notification_test_support", + "//components/desks_storage", "//components/media_message_center", "//components/onc", "//components/password_manager/core/browser:hash_password_manager",
diff --git a/ash/DEPS b/ash/DEPS index ba36485..3e92814 100644 --- a/ash/DEPS +++ b/ash/DEPS
@@ -6,6 +6,7 @@ "+chromeos/cryptohome", "+components/account_id", "+components/app_restore", + "+components/desks_storage", "+components/discardable_memory/public", "+components/discardable_memory/service/discardable_shared_memory_manager.h", "+components/live_caption",
diff --git a/ash/app_list/app_list_controller_impl.cc b/ash/app_list/app_list_controller_impl.cc index a541854e..0516c523 100644 --- a/ash/app_list/app_list_controller_impl.cc +++ b/ash/app_list/app_list_controller_impl.cc
@@ -69,7 +69,6 @@ #include "components/prefs/pref_service.h" #include "components/services/app_service/public/cpp/app_registry_cache_wrapper.h" #include "extensions/common/constants.h" -#include "ui/base/ui_base_features.h" #include "ui/compositor/layer.h" #include "ui/compositor/layer_animation_sequence.h" #include "ui/display/manager/display_manager.h" @@ -274,9 +273,7 @@ AppListControllerImpl::AppListControllerImpl() : model_(std::make_unique<AppListModel>()), - fullscreen_presenter_(std::make_unique<AppListPresenterImpl>(this)), - is_notification_indicator_enabled_( - ::features::IsNotificationIndicatorEnabled()) { + fullscreen_presenter_(std::make_unique<AppListPresenterImpl>(this)) { if (features::IsAppListBubbleEnabled()) bubble_presenter_ = std::make_unique<AppListBubblePresenter>(this); @@ -621,8 +618,7 @@ void AppListControllerImpl::OnAppListItemAdded(AppListItem* item) { client_->OnItemAdded(profile_id_, item->CloneMetadata()); - if (is_notification_indicator_enabled_ && cache_ && - notification_badging_pref_enabled_.value_or(false)) { + if (cache_ && notification_badging_pref_enabled_.value_or(false)) { // Update the notification badge indicator for the newly added app list // item. cache_->ForOneApp(item->id(), [item](const apps::AppUpdate& update) { @@ -634,30 +630,26 @@ void AppListControllerImpl::OnActiveUserPrefServiceChanged( PrefService* pref_service) { - if (is_notification_indicator_enabled_) { - pref_change_registrar_ = std::make_unique<PrefChangeRegistrar>(); - pref_change_registrar_->Init(pref_service); + pref_change_registrar_ = std::make_unique<PrefChangeRegistrar>(); + pref_change_registrar_->Init(pref_service); - pref_change_registrar_->Add( - prefs::kAppNotificationBadgingEnabled, - base::BindRepeating( - &AppListControllerImpl::UpdateAppNotificationBadging, - base::Unretained(this))); + pref_change_registrar_->Add( + prefs::kAppNotificationBadgingEnabled, + base::BindRepeating(&AppListControllerImpl::UpdateAppNotificationBadging, + base::Unretained(this))); - // Observe AppRegistryCache for the current active account to get - // notification updates. - AccountId account_id = - Shell::Get()->session_controller()->GetActiveAccountId(); - cache_ = - apps::AppRegistryCacheWrapper::Get().GetAppRegistryCache(account_id); - Observe(cache_); + // Observe AppRegistryCache for the current active account to get + // notification updates. + AccountId account_id = + Shell::Get()->session_controller()->GetActiveAccountId(); + cache_ = apps::AppRegistryCacheWrapper::Get().GetAppRegistryCache(account_id); + Observe(cache_); - // Resetting the recorded pref forces the next call to - // UpdateAppNotificationBadging() to update notification badging for every - // app item. - notification_badging_pref_enabled_.reset(); - UpdateAppNotificationBadging(); - } + // Resetting the recorded pref forces the next call to + // UpdateAppNotificationBadging() to update notification badging for every + // app item. + notification_badging_pref_enabled_.reset(); + UpdateAppNotificationBadging(); if (!IsTabletMode()) { DismissAppList();
diff --git a/ash/app_list/app_list_controller_impl.h b/ash/app_list/app_list_controller_impl.h index e9dc74b..c3b1bfd0 100644 --- a/ash/app_list/app_list_controller_impl.h +++ b/ash/app_list/app_list_controller_impl.h
@@ -558,9 +558,6 @@ // initial notification badge information when app list items are added. apps::AppRegistryCache* cache_ = nullptr; - // Whether the notification indicator flag is enabled. - const bool is_notification_indicator_enabled_; - // Observes user profile prefs for the app list. std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_;
diff --git a/ash/app_list/app_list_controller_impl_unittest.cc b/ash/app_list/app_list_controller_impl_unittest.cc index c1314c27..924593b5 100644 --- a/ash/app_list/app_list_controller_impl_unittest.cc +++ b/ash/app_list/app_list_controller_impl_unittest.cc
@@ -62,7 +62,6 @@ #include "base/test/scoped_feature_list.h" #include "base/test/with_feature_override.h" #include "ui/base/emoji/emoji_panel_helper.h" -#include "ui/base/ui_base_features.h" #include "ui/compositor/layer.h" #include "ui/compositor/scoped_animation_duration_scale_mode.h" #include "ui/events/test/event_generator.h" @@ -716,9 +715,7 @@ class AppListControllerImplTestWithNotificationBadging : public AppListControllerImplTest { public: - AppListControllerImplTestWithNotificationBadging() { - scoped_features_.InitWithFeatures({::features::kNotificationIndicator}, {}); - } + AppListControllerImplTestWithNotificationBadging() = default; AppListControllerImplTestWithNotificationBadging( const AppListControllerImplTestWithNotificationBadging& other) = delete; AppListControllerImplTestWithNotificationBadging& operator=( @@ -740,9 +737,6 @@ static_cast<apps::AppRegistryCache::Observer*>(controller) ->OnAppUpdate(test_update); } - - private: - base::test::ScopedFeatureList scoped_features_; }; // Tests that when an app has an update to its notification badge, the change
diff --git a/ash/app_list/views/app_list_bubble_apps_page.cc b/ash/app_list/views/app_list_bubble_apps_page.cc index 4e94930..645ee39 100644 --- a/ash/app_list/views/app_list_bubble_apps_page.cc +++ b/ash/app_list/views/app_list_bubble_apps_page.cc
@@ -38,6 +38,14 @@ // Insets for the vertical scroll bar. constexpr gfx::Insets kVerticalScrollInsets(1, 0, 1, 1); +// The padding between different sections within the apps page. Also used for +// interior apps page container margin. +constexpr int kVerticalPaddingBetweenSections = 16; + +// The horizontal interior margin for the apps page container - i.e. the margin +// between the apps page bounds and the page content. +constexpr int kHorizontalInteriorMargin = 20; + } // namespace AppListBubbleAppsPage::AppListBubbleAppsPage( @@ -71,8 +79,10 @@ scroll_view_->SetVerticalScrollBar(std::move(vertical_scroll)); auto scroll_contents = std::make_unique<views::View>(); - auto* layout = scroll_contents->SetLayoutManager( - std::make_unique<BoxLayout>(BoxLayout::Orientation::kVertical)); + auto* layout = scroll_contents->SetLayoutManager(std::make_unique<BoxLayout>( + BoxLayout::Orientation::kVertical, + gfx::Insets(kVerticalPaddingBetweenSections, kHorizontalInteriorMargin), + kVerticalPaddingBetweenSections)); layout->set_cross_axis_alignment(BoxLayout::CrossAxisAlignment::kStretch); // Continue section row.
diff --git a/ash/app_list/views/app_list_item_view.cc b/ash/app_list/views/app_list_item_view.cc index a5fc8eb..8a01940f 100644 --- a/ash/app_list/views/app_list_item_view.cc +++ b/ash/app_list/views/app_list_item_view.cc
@@ -28,7 +28,6 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/base/metadata/metadata_impl_macros.h" #include "ui/base/resource/resource_bundle.h" -#include "ui/base/ui_base_features.h" #include "ui/compositor/layer.h" #include "ui/compositor/scoped_layer_animation_settings.h" #include "ui/gfx/animation/throb_animation.h" @@ -272,9 +271,7 @@ is_folder_(item->GetItemType() == AppListFolderItem::kItemType), item_weak_(item), grid_delegate_(grid_delegate), - view_delegate_(view_delegate), - is_notification_indicator_enabled_( - features::IsNotificationIndicatorEnabled()) { + view_delegate_(view_delegate) { // TODO(crbug.com/1218186): Remove this, this is in place temporarily to be // able to submit accessibility checks. This crashes if fetching a11y node // data during paint because message_view_ is null. @@ -304,7 +301,7 @@ false /*animate*/); } - if (is_notification_indicator_enabled_ && !is_folder_) { + if (!is_folder_) { notification_indicator_ = AddChildView(std::make_unique<AppNotificationIndicatorView>( item->notification_badge_color())); @@ -760,7 +757,7 @@ title_bounds.Inset(title_shadow_margins_); title_->SetBoundsRect(title_bounds); - if (is_notification_indicator_enabled_ && notification_indicator_) + if (notification_indicator_) notification_indicator_->SetBoundsRect(icon_bounds); } @@ -1100,7 +1097,7 @@ } void AppListItemView::ItemBadgeVisibilityChanged() { - if (is_notification_indicator_enabled_ && notification_indicator_ && icon_) + if (notification_indicator_ && icon_) notification_indicator_->SetVisible(item_weak_->has_notification_badge()); }
diff --git a/ash/app_list/views/app_list_item_view.h b/ash/app_list/views/app_list_item_view.h index d7323a7..3ba7796 100644 --- a/ash/app_list/views/app_list_item_view.h +++ b/ash/app_list/views/app_list_item_view.h
@@ -406,9 +406,6 @@ // active notification. AppNotificationIndicatorView* notification_indicator_ = nullptr; - // Whether the notification indicator flag is enabled. - const bool is_notification_indicator_enabled_; - // Helper to trigger icon load. absl::optional<AppIconLoadHelper> icon_load_helper_;
diff --git a/ash/app_list/views/apps_grid_view.cc b/ash/app_list/views/apps_grid_view.cc index f45ceac..3ff1a4a4 100644 --- a/ash/app_list/views/apps_grid_view.cc +++ b/ash/app_list/views/apps_grid_view.cc
@@ -1686,7 +1686,7 @@ // GetAppListConfig() during this object's destruction. if (!contents_view_) { AppListConfig* config = AppListConfigProvider::Get().GetConfigForType( - AppListConfigType::kLarge, /*can_create=*/true); + AppListConfigType::kMedium, /*can_create=*/true); return *config; } return contents_view_->app_list_view()->GetAppListConfig();
diff --git a/ash/app_list/views/recent_apps_view.cc b/ash/app_list/views/recent_apps_view.cc index 14b7136..c7a7b02 100644 --- a/ash/app_list/views/recent_apps_view.cc +++ b/ash/app_list/views/recent_apps_view.cc
@@ -22,14 +22,14 @@ #include "base/strings/string_util.h" #include "extensions/common/constants.h" #include "ui/base/metadata/metadata_impl_macros.h" -#include "ui/views/layout/box_layout.h" +#include "ui/views/accessibility/view_accessibility.h" +#include "ui/views/layout/flex_layout.h" #include "url/gurl.h" namespace ash { namespace { -// Horizontal space between apps in dips. -constexpr int kHorizontalSpacing = 8; +constexpr size_t kMaxRecommendedApps = 5; // Sorts increasing by display index, then decreasing by position priority. struct CompareByDisplayIndexAndPositionPriority { @@ -74,7 +74,7 @@ std::vector<SearchResult*> app_suggestion_results = SearchModel::FilterSearchResultsByFunction( results, base::BindRepeating(is_app_suggestion), - /*max_results=*/5); + /*max_results=*/kMaxRecommendedApps); std::sort(app_suggestion_results.begin(), app_suggestion_results.end(), CompareByDisplayIndexAndPositionPriority()); @@ -142,7 +142,7 @@ const AppListConfig& GetAppListConfig() const override { // TODO(crbug.com/1211592): Eliminate this method and use the real config. return *AppListConfigProvider::Get().GetConfigForType( - AppListConfigType::kLarge, /*can_create=*/true); + AppListConfigType::kMedium, /*can_create=*/true); } private: @@ -154,10 +154,8 @@ : view_delegate_(view_delegate), grid_delegate_(std::make_unique<GridDelegateImpl>(view_delegate_)) { DCHECK(view_delegate_); - auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>( - views::BoxLayout::Orientation::kHorizontal, gfx::Insets(), - kHorizontalSpacing)); - layout->set_main_axis_alignment(views::BoxLayout::MainAxisAlignment::kCenter); + SetLayoutManager(std::make_unique<views::FlexLayout>()) + ->SetOrientation(views::LayoutOrientation::kHorizontal); std::vector<std::string> app_ids = GetRecentAppIdsFromSuggestionChips(view_delegate_->GetSearchModel()); @@ -167,10 +165,25 @@ std::string item_id = ItemIdFromAppId(app_id); AppListItem* item = model->FindItem(item_id); if (item) { - // NOTE: If you change the view structure, update GetItemForTest() as - // well. - AddChildView(std::make_unique<AppListItemView>(grid_delegate_.get(), item, - view_delegate_)); + auto* item_view = AddChildView(std::make_unique<AppListItemView>( + grid_delegate_.get(), item, view_delegate_)); + item_view->SetProperty( + views::kFlexBehaviorKey, + views::FlexSpecification(views::MinimumFlexSizeRule::kPreferred, + views::MaximumFlexSizeRule::kPreferred)); + + // Add a empty-space view used to evenly distribute app list item views + // within the available space. + if (app_id != app_ids.back()) { + auto* flex_view = AddChildView(std::make_unique<views::View>()); + flex_view->GetViewAccessibility().OverrideIsIgnored(true); + flex_view->SetFocusBehavior(views::View::FocusBehavior::NEVER); + flex_view->SetCanProcessEventsWithinSubtree(false); + flex_view->SetProperty( + views::kFlexBehaviorKey, + views::FlexSpecification(views::MinimumFlexSizeRule::kScaleToZero, + views::MaximumFlexSizeRule::kUnbounded)); + } } } } @@ -182,10 +195,6 @@ child->SetEnabled(!disabled); } -AppListItemView* RecentAppsView::GetItemViewForTest(int index) { - return static_cast<AppListItemView*>(children()[index]); -} - BEGIN_METADATA(RecentAppsView, views::View) END_METADATA
diff --git a/ash/app_list/views/recent_apps_view.h b/ash/app_list/views/recent_apps_view.h index 72cab88..815b989 100644 --- a/ash/app_list/views/recent_apps_view.h +++ b/ash/app_list/views/recent_apps_view.h
@@ -32,8 +32,6 @@ // See AppsGridView::DisableFocusForShowingActiveFolder(). void DisableFocusForShowingActiveFolder(bool disabled); - AppListItemView* GetItemViewForTest(int index); - private: AppListViewDelegate* const view_delegate_;
diff --git a/ash/app_list/views/recent_apps_view_unittest.cc b/ash/app_list/views/recent_apps_view_unittest.cc index b26a01b3..8f8f49b 100644 --- a/ash/app_list/views/recent_apps_view_unittest.cc +++ b/ash/app_list/views/recent_apps_view_unittest.cc
@@ -19,12 +19,26 @@ #include "ash/public/cpp/app_list/app_list_types.h" #include "ash/shell.h" #include "ash/test/ash_test_base.h" +#include "base/strings/stringprintf.h" #include "base/test/scoped_feature_list.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/gfx/geometry/point.h" +#include "ui/gfx/geometry/rect.h" +#include "ui/gfx/geometry/vector2d.h" +#include "ui/views/view_utils.h" namespace ash { namespace { +// Used to compare distances between point that allow for certain margin of +// error when comparing horizontal distance. Used to compare spacing between +// views that accounts for 1 off rounding errors. +bool AreVectorsClose(const gfx::Vector2d& v1, const gfx::Vector2d& v2) { + const int kHorizontalMarginOfError = 1; + return std::abs(v1.x() - v2.x()) <= kHorizontalMarginOfError && + std::abs(v1.y() - v2.y()) == 0; +} + // Returns the first window with type WINDOW_TYPE_MENU found via depth-first // search. Returns nullptr if no such window exists. aura::Window* FindMenuWindow(aura::Window* root) { @@ -74,6 +88,24 @@ return GetAppListTestHelper()->GetBubbleRecentAppsView(); } + // Adds `count` installed app search results. + void AddAppResults(int count) { + for (int i = 0; i < count; ++i) { + std::string id = base::StringPrintf("id%d", i); + AddAppListItem(id); + AddSearchResult(id, AppListSearchResultType::kInstalledApp); + } + } + + std::vector<AppListItemView*> GetAppListItemViews(RecentAppsView* view) { + std::vector<AppListItemView*> app_list_item_views; + for (auto* child : view->children()) { + if (views::IsViewClass<AppListItemView>(child)) + app_list_item_views.push_back(static_cast<AppListItemView*>(child)); + } + return app_list_item_views; + } + base::test::ScopedFeatureList scoped_feature_list_; }; @@ -90,7 +122,103 @@ ShowAppList(); RecentAppsView* view = GetRecentAppsView(); - EXPECT_EQ(view->children().size(), 4u); + EXPECT_EQ(GetAppListItemViews(view).size(), 4u); +} + +TEST_F(RecentAppsViewTest, ItemsEvenlySpacedInTheViewWith5Items) { + AddAppResults(5); + ShowAppList(); + + RecentAppsView* view = GetRecentAppsView(); + std::vector<AppListItemView*> items = GetAppListItemViews(view); + ASSERT_EQ(5u, items.size()); + + for (int i = 4; i > 1; --i) { + const gfx::Vector2d right_space = items[i]->bounds().left_center() - + items[i - 1]->bounds().right_center(); + const gfx::Vector2d left_space = items[i - 1]->bounds().left_center() - + items[i - 2]->bounds().right_center(); + EXPECT_TRUE(AreVectorsClose(right_space, left_space)) + << i << " " << right_space.ToString() << " " << left_space.ToString(); + } +} + +TEST_F(RecentAppsViewTest, ResultItemsCoverWholeContainerWith5Items) { + AddAppResults(5); + ShowAppList(); + + RecentAppsView* view = GetRecentAppsView(); + std::vector<AppListItemView*> items = GetAppListItemViews(view); + ASSERT_EQ(5u, items.size()); + + EXPECT_EQ(view->GetContentsBounds().left_center(), + items[0]->bounds().left_center()); + EXPECT_EQ(view->GetContentsBounds().right_center(), + items[4]->bounds().right_center()); +} + +TEST_F(RecentAppsViewTest, ItemsEvenlySpacedInTheViewWith4Items) { + AddAppResults(4); + ShowAppList(); + + RecentAppsView* view = GetRecentAppsView(); + std::vector<AppListItemView*> items = GetAppListItemViews(view); + ASSERT_EQ(4u, items.size()); + + for (int i = 3; i > 1; --i) { + const gfx::Vector2d right_space = items[i]->bounds().left_center() - + items[i - 1]->bounds().right_center(); + const gfx::Vector2d left_space = items[i - 1]->bounds().left_center() - + items[i - 2]->bounds().right_center(); + EXPECT_TRUE(AreVectorsClose(right_space, left_space)) + << i << " " << right_space.ToString() << " " << left_space.ToString(); + } +} + +TEST_F(RecentAppsViewTest, ResultItemsCoverWholeContainerWith4Items) { + AddAppResults(4); + ShowAppList(); + + RecentAppsView* view = GetRecentAppsView(); + std::vector<AppListItemView*> items = GetAppListItemViews(view); + ASSERT_EQ(4u, items.size()); + + EXPECT_EQ(view->GetContentsBounds().left_center(), + items[0]->bounds().left_center()); + EXPECT_EQ(view->GetContentsBounds().right_center(), + items[3]->bounds().right_center()); +} + +TEST_F(RecentAppsViewTest, ItemsEvenlySpacedInTheViewWith3Items) { + AddAppResults(3); + ShowAppList(); + + RecentAppsView* view = GetRecentAppsView(); + std::vector<AppListItemView*> items = GetAppListItemViews(view); + ASSERT_EQ(3u, items.size()); + + for (int i = 2; i > 1; --i) { + const gfx::Vector2d right_space = items[i]->bounds().left_center() - + items[i - 1]->bounds().right_center(); + const gfx::Vector2d left_space = items[i - 1]->bounds().left_center() - + items[i - 2]->bounds().right_center(); + EXPECT_TRUE(AreVectorsClose(right_space, left_space)) + << i << " " << right_space.ToString() << " " << left_space.ToString(); + } +} + +TEST_F(RecentAppsViewTest, ResultItemsCoverWholeContainerWith3Items) { + AddAppResults(3); + ShowAppList(); + + RecentAppsView* view = GetRecentAppsView(); + std::vector<AppListItemView*> items = GetAppListItemViews(view); + ASSERT_EQ(3u, items.size()); + + EXPECT_EQ(view->GetContentsBounds().left_center(), + items[0]->bounds().left_center()); + EXPECT_EQ(view->GetContentsBounds().right_center(), + items[2]->bounds().right_center()); } TEST_F(RecentAppsViewTest, DoesNotCreateIconsForNonApps) { @@ -101,7 +229,7 @@ ShowAppList(); RecentAppsView* view = GetRecentAppsView(); - EXPECT_EQ(view->children().size(), 0u); + EXPECT_EQ(GetAppListItemViews(view).size(), 0u); } TEST_F(RecentAppsViewTest, DoesNotCreateIconForMismatchedId) { @@ -121,9 +249,10 @@ ShowAppList(); // Click on the first icon. - RecentAppsView* view = GetRecentAppsView(); - ASSERT_FALSE(view->children().empty()); - views::View* icon = view->children()[0]; + std::vector<AppListItemView*> items = + GetAppListItemViews(GetRecentAppsView()); + ASSERT_FALSE(items.empty()); + views::View* icon = items[0]; GetEventGenerator()->MoveMouseTo(icon->GetBoundsInScreen().CenterPoint()); GetEventGenerator()->ClickLeftButton(); @@ -138,10 +267,10 @@ ShowAppList(); // Right click on the first icon. - RecentAppsView* view = GetRecentAppsView(); - ASSERT_FALSE(view->children().empty()); - views::View* icon = view->children()[0]; - GetEventGenerator()->MoveMouseTo(icon->GetBoundsInScreen().CenterPoint()); + std::vector<AppListItemView*> items = + GetAppListItemViews(GetRecentAppsView()); + ASSERT_FALSE(items.empty()); + GetEventGenerator()->MoveMouseTo(items[0]->GetBoundsInScreen().CenterPoint()); GetEventGenerator()->ClickRightButton(); // A menu opened. @@ -163,11 +292,11 @@ AddSearchResult("id2", AppListSearchResultType::kInstalledApp); ShowAppList(); - // There are 2 items. - RecentAppsView* view = GetRecentAppsView(); - ASSERT_EQ(2u, view->children().size()); - AppListItemView* item1 = view->GetItemViewForTest(0); - AppListItemView* item2 = view->GetItemViewForTest(1); + std::vector<AppListItemView*> items = + GetAppListItemViews(GetRecentAppsView()); + ASSERT_EQ(2u, items.size()); + AppListItemView* item1 = items[0]; + AppListItemView* item2 = items[1]; // The grid delegates are the same, so it doesn't matter which one we use for // expectations below.
diff --git a/ash/app_list/views/scrollable_apps_grid_view.cc b/ash/app_list/views/scrollable_apps_grid_view.cc index c9fb714..10b358a 100644 --- a/ash/app_list/views/scrollable_apps_grid_view.cc +++ b/ash/app_list/views/scrollable_apps_grid_view.cc
@@ -102,8 +102,15 @@ int content_width = GetContentsBounds().width(); int tile_width = GetAppListConfig().grid_tile_width(); int width_to_distribute = content_width - cols() * tile_width; - // Each column has padding on left and on right. - int horizontal_tile_padding = width_to_distribute / (cols() * 2); + + // While calculating tile padding, assume no padding between a tile and a + // container bounds. + DCHECK_GT(cols(), 1); + const int spaces_between_items = cols() - 1; + // Each column has padding on left and on right, so a space between two tiles + // is double the tile padding size. + const int horizontal_tile_padding = + width_to_distribute / (spaces_between_items * 2); return gfx::Insets(-kVerticalTilePadding, -horizontal_tile_padding); }
diff --git a/ash/app_list/views/scrollable_apps_grid_view_unittest.cc b/ash/app_list/views/scrollable_apps_grid_view_unittest.cc index 46d0baa..3dd0f790 100644 --- a/ash/app_list/views/scrollable_apps_grid_view_unittest.cc +++ b/ash/app_list/views/scrollable_apps_grid_view_unittest.cc
@@ -309,8 +309,11 @@ const int scroll_offset2 = scroll_view_->GetVisibleRect().y(); EXPECT_GT(scroll_offset2, scroll_offset1); - // Move the mouse back into the center of the view (not in the scroll margin). - generator->MoveMouseTo(scroll_view_->GetBoundsInScreen().CenterPoint()); + // Move the mouse back into the (vertical) center of the view (not in the + // scroll margin). Use a point close to a horizontal edge to avoid hitting an + // item bounds (which would trigger reparent instead of reorder timer). + generator->MoveMouseTo(scroll_view_->GetBoundsInScreen().left_center() + + gfx::Vector2d(5, 0)); // Scroll position didn't change, auto-scrolling is stopped, and reordering // started again.
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd index c17688e..a006c69b 100644 --- a/ash/ash_strings.grd +++ b/ash/ash_strings.grd
@@ -533,12 +533,15 @@ <message name="IDS_ASH_STATUS_TRAY_BLUETOOTH_PAIR_NEW_DEVICE" desc="The sub-header label for the button to pair a new device."> Pair new device </message> - <message name="IDS_ASH_STATUS_TRAY_BLUETOOTH_CURRENTLY_CONNECTED_DEVICES" desc="The sub-header label for currently connected devices in Bluetooth device list."> + <message name="IDS_ASH_STATUS_TRAY_BLUETOOTH_CURRENTLY_CONNECTED_DEVICES" desc="The sub-header label for currently connected devices in the Bluetooth device list."> Currently connected </message> - <message name="IDS_ASH_STATUS_TRAY_BLUETOOTH_PREVIOUSLY_CONNECTED_DEVICES" desc="The sub-header label for previously connected devices in Bluetooth device list."> + <message name="IDS_ASH_STATUS_TRAY_BLUETOOTH_PREVIOUSLY_CONNECTED_DEVICES" desc="The sub-header label for previously connected devices in the Bluetooth device list."> Previously connected </message> + <message name="IDS_ASH_STATUS_TRAY_BLUETOOTH_NO_DEVICE_CONNECTED" desc="The sub-header label for no devices connected in the Bluetooth device list."> + No device connected + </message> <message name="IDS_ASH_STATUS_TRAY_UPDATE" desc="The label used in the tray popup to notify that the user should restart to get system updates."> Restart to update @@ -3654,13 +3657,22 @@ <message name="IDS_ASH_SCREEN_CAPTURE_LABEL_MICROPHONE" desc="The capture label message for toggling microphone recording, found in the settings menu."> Record microphone </message> - <message name="IDS_ASH_SCREEN_CAPTURE_LABEL_SAVE_TO" desc="The label of the save to menu group header in capture mode settings."> + <message name="IDS_ASH_SCREEN_CAPTURE_AUDIO_INPUT" desc="The label of the audio input menu group header in capture mode settings."> + Audio input + </message> + <message name="IDS_ASH_SCREEN_CAPTURE_AUDIO_INPUT_OFF" desc="The label of the menu option button for no audio input."> + Off + </message> + <message name="IDS_ASH_SCREEN_CAPTURE_AUDIO_INPUT_MICROPHONE" desc="The label of the menu option button for microphone audio input."> + Microphone + </message> + <message name="IDS_ASH_SCREEN_CAPTURE_SAVE_TO" desc="The label of the save to menu group header in capture mode settings."> Save to </message> - <message name="IDS_ASH_SCREEN_CAPTURE_LABEL_SAVE_TO_DOWNLOADS" desc="The label of the menu option button to select the downloads folder."> + <message name="IDS_ASH_SCREEN_CAPTURE_SAVE_TO_DOWNLOADS" desc="The label of the menu option button to select the downloads folder."> Downloads </message> - <message name="IDS_ASH_SCREEN_CAPTURE_LABEL_SAVE_TO_SELECT_FOLDER" desc="The label of the menu item button for selecting a folder to store the captured images and videos."> + <message name="IDS_ASH_SCREEN_CAPTURE_SAVE_TO_SELECT_FOLDER" desc="The label of the menu item button for selecting a folder to store the captured images and videos."> Select folder... </message>
diff --git a/ash/ash_strings_grd/IDS_ASH_SCREEN_CAPTURE_AUDIO_INPUT.png.sha1 b/ash/ash_strings_grd/IDS_ASH_SCREEN_CAPTURE_AUDIO_INPUT.png.sha1 new file mode 100644 index 0000000..626479c4 --- /dev/null +++ b/ash/ash_strings_grd/IDS_ASH_SCREEN_CAPTURE_AUDIO_INPUT.png.sha1
@@ -0,0 +1 @@ +ae438034185f53e0e12d9d760885eb624bbd0935 \ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_SCREEN_CAPTURE_AUDIO_INPUT_MICROPHONE.png.sha1 b/ash/ash_strings_grd/IDS_ASH_SCREEN_CAPTURE_AUDIO_INPUT_MICROPHONE.png.sha1 new file mode 100644 index 0000000..626479c4 --- /dev/null +++ b/ash/ash_strings_grd/IDS_ASH_SCREEN_CAPTURE_AUDIO_INPUT_MICROPHONE.png.sha1
@@ -0,0 +1 @@ +ae438034185f53e0e12d9d760885eb624bbd0935 \ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_SCREEN_CAPTURE_AUDIO_INPUT_OFF.png.sha1 b/ash/ash_strings_grd/IDS_ASH_SCREEN_CAPTURE_AUDIO_INPUT_OFF.png.sha1 new file mode 100644 index 0000000..626479c4 --- /dev/null +++ b/ash/ash_strings_grd/IDS_ASH_SCREEN_CAPTURE_AUDIO_INPUT_OFF.png.sha1
@@ -0,0 +1 @@ +ae438034185f53e0e12d9d760885eb624bbd0935 \ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_SCREEN_CAPTURE_LABEL_SAVE_TO.png.sha1 b/ash/ash_strings_grd/IDS_ASH_SCREEN_CAPTURE_SAVE_TO.png.sha1 similarity index 100% rename from ash/ash_strings_grd/IDS_ASH_SCREEN_CAPTURE_LABEL_SAVE_TO.png.sha1 rename to ash/ash_strings_grd/IDS_ASH_SCREEN_CAPTURE_SAVE_TO.png.sha1
diff --git a/ash/ash_strings_grd/IDS_ASH_SCREEN_CAPTURE_LABEL_SAVE_TO_DOWNLOADS.png.sha1 b/ash/ash_strings_grd/IDS_ASH_SCREEN_CAPTURE_SAVE_TO_DOWNLOADS.png.sha1 similarity index 100% rename from ash/ash_strings_grd/IDS_ASH_SCREEN_CAPTURE_LABEL_SAVE_TO_DOWNLOADS.png.sha1 rename to ash/ash_strings_grd/IDS_ASH_SCREEN_CAPTURE_SAVE_TO_DOWNLOADS.png.sha1
diff --git a/ash/ash_strings_grd/IDS_ASH_SCREEN_CAPTURE_LABEL_SAVE_TO_SELECT_FOLDER.png.sha1 b/ash/ash_strings_grd/IDS_ASH_SCREEN_CAPTURE_SAVE_TO_SELECT_FOLDER.png.sha1 similarity index 100% rename from ash/ash_strings_grd/IDS_ASH_SCREEN_CAPTURE_LABEL_SAVE_TO_SELECT_FOLDER.png.sha1 rename to ash/ash_strings_grd/IDS_ASH_SCREEN_CAPTURE_SAVE_TO_SELECT_FOLDER.png.sha1
diff --git a/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_BLUETOOTH_NO_DEVICE_CONNECTED.png.sha1 b/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_BLUETOOTH_NO_DEVICE_CONNECTED.png.sha1 new file mode 100644 index 0000000..7f7df6d --- /dev/null +++ b/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_BLUETOOTH_NO_DEVICE_CONNECTED.png.sha1
@@ -0,0 +1 @@ +1087627139c0d0fa0010136ab561cc32462988fd \ No newline at end of file
diff --git a/ash/capture_mode/capture_mode_advanced_settings_view.cc b/ash/capture_mode/capture_mode_advanced_settings_view.cc index 581255a..ba4da87 100644 --- a/ash/capture_mode/capture_mode_advanced_settings_view.cc +++ b/ash/capture_mode/capture_mode_advanced_settings_view.cc
@@ -8,7 +8,7 @@ #include "ash/capture_mode/capture_mode_bar_view.h" #include "ash/capture_mode/capture_mode_constants.h" -#include "ash/capture_mode/capture_mode_menu_group.h" +#include "ash/capture_mode/capture_mode_controller.h" #include "ash/capture_mode/capture_mode_toggle_button.h" #include "ash/resources/vector_icons/vector_icons.h" #include "ash/strings/grit/ash_strings.h" @@ -18,37 +18,61 @@ #include "ui/compositor/layer.h" #include "ui/gfx/geometry/rect.h" #include "ui/views/background.h" +#include "ui/views/controls/separator.h" #include "ui/views/layout/box_layout.h" namespace ash { namespace { -constexpr gfx::Size kSettingsSize{256, 124}; +constexpr gfx::Size kSettingsSize{256, 248}; constexpr gfx::RoundedCornersF kBorderRadius{10.f}; +// All the options in the CaptureMode settings view. +enum CaptureSettingsOption { + kAudioOff = 0, + kAudioMicrophone, + kDownloadsFolder, + kCustomFolder, +}; + } // namespace CaptureModeAdvancedSettingsView::CaptureModeAdvancedSettingsView() - : save_to_menu_group_(AddChildView(std::make_unique<CaptureModeMenuGroup>( + : audio_input_menu_group_( + AddChildView(std::make_unique<CaptureModeMenuGroup>( + this, + kCaptureModeMicIcon, + l10n_util::GetStringUTF16(IDS_ASH_SCREEN_CAPTURE_AUDIO_INPUT)))), + separator_(AddChildView(std::make_unique<views::Separator>())), + save_to_menu_group_(AddChildView(std::make_unique<CaptureModeMenuGroup>( + this, kCaptureModeFolderIcon, - l10n_util::GetStringUTF16(IDS_ASH_SCREEN_CAPTURE_LABEL_SAVE_TO)))) { + l10n_util::GetStringUTF16(IDS_ASH_SCREEN_CAPTURE_SAVE_TO)))) { + audio_input_menu_group_->AddOption( + l10n_util::GetStringUTF16(IDS_ASH_SCREEN_CAPTURE_AUDIO_INPUT_OFF), + kAudioOff); + audio_input_menu_group_->AddOption( + l10n_util::GetStringUTF16(IDS_ASH_SCREEN_CAPTURE_AUDIO_INPUT_MICROPHONE), + kAudioMicrophone); save_to_menu_group_->AddOption( - base::BindRepeating(&CaptureModeAdvancedSettingsView::HandleOptionClick, - base::Unretained(this)), - l10n_util::GetStringUTF16(IDS_ASH_SCREEN_CAPTURE_LABEL_SAVE_TO_DOWNLOADS), - /*checked=*/true); + l10n_util::GetStringUTF16(IDS_ASH_SCREEN_CAPTURE_SAVE_TO_DOWNLOADS), + kDownloadsFolder); save_to_menu_group_->AddMenuItem( base::BindRepeating(&CaptureModeAdvancedSettingsView::HandleMenuClick, base::Unretained(this)), - l10n_util::GetStringUTF16( - IDS_ASH_SCREEN_CAPTURE_LABEL_SAVE_TO_SELECT_FOLDER)); + l10n_util::GetStringUTF16(IDS_ASH_SCREEN_CAPTURE_SAVE_TO_SELECT_FOLDER)); + + auto* color_provider = AshColorProvider::Get(); + + const SkColor separator_color = color_provider->GetContentLayerColor( + AshColorProvider::ContentLayerType::kSeparatorColor); + separator_->SetColor(separator_color); SetPaintToLayer(); - SetBackground( - views::CreateSolidBackground(AshColorProvider::Get()->GetBaseLayerColor( - AshColorProvider::BaseLayerType::kTransparent80))); + SetBackground(views::CreateSolidBackground(color_provider->GetBaseLayerColor( + AshColorProvider::BaseLayerType::kTransparent80))); layer()->SetFillsBoundsOpaquely(false); layer()->SetRoundedCornerRadius(kBorderRadius); layer()->SetBackgroundBlur(ColorProvider::kBackgroundBlurSigma); @@ -73,7 +97,52 @@ kSettingsSize.width(), kSettingsSize.height()); } -void CaptureModeAdvancedSettingsView::HandleOptionClick() {} +void CaptureModeAdvancedSettingsView::OnOptionSelected(int option_id) const { + switch (option_id) { + case kAudioOff: + CaptureModeController::Get()->EnableAudioRecording(false); + break; + case kAudioMicrophone: + CaptureModeController::Get()->EnableAudioRecording(true); + break; + case kDownloadsFolder: + case kCustomFolder: + // TODO(conniekxu|afakhry): Handle |kDownloadsFolder| and |kCustomFolder| + // options in the following up CLs. For now we only support + // |kDownloadsFolder| for |save_to_menu_group_|, that's why we don't need + // to handle it explicitly here. + break; + default: + return; + } +} + +bool CaptureModeAdvancedSettingsView::IsOptionChecked(int option_id) const { + switch (option_id) { + case kAudioOff: + return !CaptureModeController::Get()->enable_audio_recording(); + case kAudioMicrophone: + return CaptureModeController::Get()->enable_audio_recording(); + // TODO(conniekxu|afakhry): Handle |kDownloadsFolder| and |kCustomFolder| + // options in the following up CLs. For now we only support + // |kDownloadsFolder|, hence we return true/false directly here. + case kDownloadsFolder: + return true; + case kCustomFolder: + return false; + default: + return false; + } +} + +views::View* CaptureModeAdvancedSettingsView::GetMicrophoneOptionForTesting() { + return audio_input_menu_group_->GetOptionForTesting( // IN-TEST + kAudioMicrophone); // IN-TEST +} + +views::View* CaptureModeAdvancedSettingsView::GetOffOptionForTesting() { + return audio_input_menu_group_->GetOptionForTesting(kAudioOff); // IN-TEST +} void CaptureModeAdvancedSettingsView::HandleMenuClick() {}
diff --git a/ash/capture_mode/capture_mode_advanced_settings_view.h b/ash/capture_mode/capture_mode_advanced_settings_view.h index cf50d3b..6b62511 100644 --- a/ash/capture_mode/capture_mode_advanced_settings_view.h +++ b/ash/capture_mode/capture_mode_advanced_settings_view.h
@@ -6,20 +6,26 @@ #define ASH_CAPTURE_MODE_CAPTURE_MODE_ADVANCED_SETTINGS_VIEW_H_ #include "ash/ash_export.h" +#include "ash/capture_mode/capture_mode_menu_group.h" #include "ui/base/metadata/metadata_header_macros.h" #include "ui/views/view.h" +namespace views { +class Separator; +} // namespace views + namespace ash { class CaptureModeBarView; -class CaptureModeMenuGroup; // TODO(conniekxu): This will replace CaptureModeSettingsView once // feature 'ImprovedScreenCaptureSettings' is fully launched. // A view that acts as the content view of the capture mode settings menu // widget. It is the content view of settings widget and it contains // `CaptureModeMenuGroup` for each setting, save to, audio input etc. -class ASH_EXPORT CaptureModeAdvancedSettingsView : public views::View { +class ASH_EXPORT CaptureModeAdvancedSettingsView + : public views::View, + public CaptureModeMenuGroup::Delegate { public: METADATA_HEADER(CaptureModeAdvancedSettingsView); @@ -34,22 +40,31 @@ // the given 'capture_mode_bar_view'. static gfx::Rect GetBounds(CaptureModeBarView* capture_mode_bar_view); - CaptureModeMenuGroup* save_to_menu_group() const { - return save_to_menu_group_; + // CaptureModeMenuGroup::Delegate: + void OnOptionSelected(int option_id) const override; + bool IsOptionChecked(int option_id) const override; + + // For tests only: + CaptureModeMenuGroup* GetAudioInputMenuGroupForTesting() { + return audio_input_menu_group_; } + views::View* GetMicrophoneOptionForTesting(); + views::View* GetOffOptionForTesting(); private: - // TODO(conniekxu): This is the callback function on option click. It will - // select the clicked/pressed button, and unselect any previously selected - // button. - void HandleOptionClick(); - // TODO(afakhry|conniekxu): This is the callback function on menu item click. - // It will be only used by the menu item in `save_to_menu_` for now. It should - // open the folder window for user to select to folder to save the captured - // files from. + // It will be only used by the menu item in |save_to_menu_| for now. It should + // open the folder window for user to select a folder to save the captured + // files to. void HandleMenuClick(); + // "Audio input" menu group that users can select an audio input from for + // screen capture recording. It has "Off" and "Microphone" options for now. + // "Off" is the default one which means no audio input selected. + CaptureModeMenuGroup* audio_input_menu_group_; + + views::Separator* separator_; + // "Save to" menu group that users can select a folder to save the captured // files to. It will include the "Downloads" folder as the default one and // one more folder selected by users.
diff --git a/ash/capture_mode/capture_mode_controller.cc b/ash/capture_mode/capture_mode_controller.cc index 4a51ab4..45e7ead 100644 --- a/ash/capture_mode/capture_mode_controller.cc +++ b/ash/capture_mode/capture_mode_controller.cc
@@ -426,6 +426,13 @@ return; enable_audio_recording_ = enable_audio_recording; + + // TODO(conniekxu): remove all code below for this function once feature + // 'ImprovedScreenCaptureSettings' is fully launched. + // Return directly if |kImprovedScreenCaptureSettings| is enabled because for + // the new CaptureMode settings we don't have microphone toggle button. + if (features::AreImprovedScreenCaptureSettingsEnabled()) + return; DCHECK(capture_mode_session_); capture_mode_session_->OnMicrophoneChanged(enable_audio_recording_); }
diff --git a/ash/capture_mode/capture_mode_menu_group.cc b/ash/capture_mode/capture_mode_menu_group.cc index a0cc50c8..a2cae0e 100644 --- a/ash/capture_mode/capture_mode_menu_group.cc +++ b/ash/capture_mode/capture_mode_menu_group.cc
@@ -5,6 +5,8 @@ #include "ash/capture_mode/capture_mode_menu_group.h" #include <memory> +#include <string> +#include <utility> #include <vector> #include "ash/capture_mode/capture_mode_constants.h" @@ -13,6 +15,10 @@ #include "ash/style/ash_color_provider.h" #include "ui/base/metadata/metadata_impl_macros.h" #include "ui/gfx/paint_vector_icon.h" +#include "ui/views/animation/ink_drop.h" +#include "ui/views/animation/ink_drop_highlight.h" +#include "ui/views/controls/button/button.h" +#include "ui/views/controls/highlight_path_generator.h" #include "ui/views/controls/image_view.h" #include "ui/views/controls/label.h" #include "ui/views/layout/box_layout.h" @@ -21,13 +27,13 @@ namespace { -constexpr gfx::Insets kMenuGroupPadding{8, 16}; +constexpr gfx::Insets kMenuGroupPadding{8, 0}; -constexpr gfx::Insets kMenuHeaderPadding{8, 0}; +constexpr gfx::Insets kMenuHeaderPadding{8, 16}; -constexpr gfx::Insets kOptionPadding{8, 36, 8, 0}; +constexpr gfx::Insets kOptionPadding{8, 52, 8, 16}; -constexpr gfx::Insets kMenuItemPadding{10, 36, 10, 0}; +constexpr gfx::Insets kMenuItemPadding{10, 52, 10, 16}; constexpr int kSpaceBetweenMenuItem = 0; @@ -50,6 +56,28 @@ return box_layout; } +void SetInkDropForButton(views::Button* button) { + auto* ink_drop = views::InkDrop::Get(button); + ink_drop->SetMode(views::InkDropHost::InkDropMode::ON); + button->SetHasInkDropActionOnClick(true); + ink_drop->SetVisibleOpacity(capture_mode::kInkDropVisibleOpacity); + views::InkDrop::UseInkDropForFloodFillRipple(ink_drop, + /*highlight_on_hover=*/false, + /*highlight_on_focus=*/false); + ink_drop->SetCreateHighlightCallback(base::BindRepeating( + [](views::Button* host) { + const AshColorProvider::RippleAttributes ripple_attributes = + AshColorProvider::Get()->GetRippleAttributes(); + auto highlight = std::make_unique<views::InkDropHighlight>( + gfx::SizeF(host->size()), ripple_attributes.base_color); + highlight->set_visible_opacity(ripple_attributes.highlight_opacity); + return highlight; + }, + button)); + ink_drop->SetBaseColor(capture_mode::kInkDropBaseColor); + views::InstallRectHighlightPathGenerator(button); +} + // The header of the menu group, which has an icon and a text label. Not user // interactable. class CaptureModeMenuHeader : public views::View { @@ -84,47 +112,6 @@ BEGIN_METADATA(CaptureModeMenuHeader, views::View) END_METADATA -// A button which represents an option of the menu group. It has a text label -// and a checked icon. The checked icon will be shown on button click and any -// other option's checked icon will be set to invisible in the meanwhile. One -// and only one checked icon is visible in the menu group. -class CaptureModeOption : public views::Button { - public: - METADATA_HEADER(CaptureModeOption); - - CaptureModeOption(views::Button::PressedCallback callback, - std::u16string option_label, - bool checked) - : views::Button(callback), - label_view_(AddChildView( - std::make_unique<views::Label>(std::move(option_label)))), - checked_icon_view_(AddChildView(std::make_unique<views::ImageView>())) { - checked_icon_view_->SetImageSize(kIconSize); - checked_icon_view_->SetPreferredSize(kIconSize); - checked_icon_view_->SetImage(gfx::CreateVectorIcon( - kHollowCheckCircleIcon, - AshColorProvider::Get()->GetContentLayerColor( - AshColorProvider::ContentLayerType::kButtonLabelColorBlue))); - checked_icon_view_->SetVisible(checked); - - SetBorder(views::CreateEmptyBorder(kOptionPadding)); - ConfigLabelView(label_view_); - auto* box_layout = CreateAndInitBoxLayoutForView(this); - box_layout->SetFlexForView(label_view_, 1); - } - - CaptureModeOption(const CaptureModeOption&) = delete; - CaptureModeOption& operator=(const CaptureModeOption&) = delete; - ~CaptureModeOption() override = default; - - private: - views::Label* label_view_; - views::ImageView* checked_icon_view_; -}; - -BEGIN_METADATA(CaptureModeOption, views::Button) -END_METADATA - // A button which has a text label. Its behavior on click can be customized. // For selecting folder, a folder window will be opened on click. class CaptureModeMenuItem : public views::Button { @@ -139,6 +126,7 @@ SetBorder(views::CreateEmptyBorder(kMenuItemPadding)); ConfigLabelView(label_view_); CreateAndInitBoxLayoutForView(this); + SetInkDropForButton(this); } CaptureModeMenuItem(const CaptureModeMenuItem&) = delete; @@ -154,8 +142,63 @@ } // namespace -CaptureModeMenuGroup::CaptureModeMenuGroup(const gfx::VectorIcon& header_icon, - std::u16string header_label) { +// A button which represents an option of the menu group. It has a text label +// and a checked icon. The checked icon will be shown on button click and any +// other option's checked icon will be set to invisible in the meanwhile. One +// and only one checked icon is visible in the menu group. +class CaptureModeOption : public views::Button { + public: + METADATA_HEADER(CaptureModeOption); + + CaptureModeOption(views::Button::PressedCallback callback, + std::u16string option_label, + int option_id, + bool checked) + : views::Button(callback), + label_view_(AddChildView( + std::make_unique<views::Label>(std::move(option_label)))), + checked_icon_view_(AddChildView(std::make_unique<views::ImageView>())), + id_(option_id) { + checked_icon_view_->SetImageSize(kIconSize); + checked_icon_view_->SetPreferredSize(kIconSize); + checked_icon_view_->SetImage(gfx::CreateVectorIcon( + kHollowCheckCircleIcon, + AshColorProvider::Get()->GetContentLayerColor( + AshColorProvider::ContentLayerType::kButtonLabelColorBlue))); + checked_icon_view_->SetVisible(checked); + + SetBorder(views::CreateEmptyBorder(kOptionPadding)); + ConfigLabelView(label_view_); + auto* box_layout = CreateAndInitBoxLayoutForView(this); + box_layout->SetFlexForView(label_view_, 1); + SetInkDropForButton(this); + } + + CaptureModeOption(const CaptureModeOption&) = delete; + CaptureModeOption& operator=(const CaptureModeOption&) = delete; + ~CaptureModeOption() override = default; + + int id() const { return id_; } + + void SetOptionChecked(bool checked) { + checked_icon_view_->SetVisible(checked); + } + + bool IsOptionChecked() { return checked_icon_view_->GetVisible(); } + + private: + views::Label* label_view_; + views::ImageView* checked_icon_view_; + const int id_; +}; + +BEGIN_METADATA(CaptureModeOption, views::Button) +END_METADATA + +CaptureModeMenuGroup::CaptureModeMenuGroup(Delegate* delegate, + const gfx::VectorIcon& header_icon, + std::u16string header_label) + : delegate_(delegate) { AddChildView(std::make_unique<CaptureModeMenuHeader>( header_icon, std::move(header_label))); options_container_ = AddChildView(std::make_unique<views::View>()); @@ -168,11 +211,14 @@ CaptureModeMenuGroup::~CaptureModeMenuGroup() = default; -void CaptureModeMenuGroup::AddOption(views::Button::PressedCallback callback, - std::u16string option_label, - bool checked) { - options_container_->AddChildView(std::make_unique<CaptureModeOption>( - callback, std::move(option_label), checked)); +void CaptureModeMenuGroup::AddOption(std::u16string option_label, + int option_id) { + options_.push_back( + options_container_->AddChildView(std::make_unique<CaptureModeOption>( + base::BindRepeating(&CaptureModeMenuGroup::HandleOptionClick, + base::Unretained(this), option_id), + std::move(option_label), option_id, + /*checked=*/delegate_->IsOptionChecked(option_id)))); } void CaptureModeMenuGroup::AddMenuItem(views::Button::PressedCallback callback, @@ -181,6 +227,24 @@ std::make_unique<CaptureModeMenuItem>(callback, std::move(item_label))); } +views::View* CaptureModeMenuGroup::GetOptionForTesting(int option_id) { + for (auto* option : options_) { + if (option->id() == option_id) + return option; + } + return nullptr; +} + +bool CaptureModeMenuGroup::IsOptionCheckedForTesting(views::View* option) { + return static_cast<CaptureModeOption*>(option)->IsOptionChecked(); +} + +void CaptureModeMenuGroup::HandleOptionClick(int option_id) { + for (auto* option : options_) + option->SetOptionChecked(option_id == option->id()); + delegate_->OnOptionSelected(option_id); +} + BEGIN_METADATA(CaptureModeMenuGroup, views::View) END_METADATA } // namespace ash
diff --git a/ash/capture_mode/capture_mode_menu_group.h b/ash/capture_mode/capture_mode_menu_group.h index 0f27f4b..6c47388 100644 --- a/ash/capture_mode/capture_mode_menu_group.h +++ b/ash/capture_mode/capture_mode_menu_group.h
@@ -5,6 +5,8 @@ #ifndef ASH_CAPTURE_MODE_CAPTURE_MODE_MENU_GROUP_H_ #define ASH_CAPTURE_MODE_CAPTURE_MODE_MENU_GROUP_H_ +#include <vector> + #include "ash/ash_export.h" #include "ui/base/metadata/metadata_header_macros.h" #include "ui/views/controls/button/button.h" @@ -15,6 +17,8 @@ namespace ash { +class CaptureModeOption; + // Defines a view that groups together related capture mode settings in an // independent section in the settings menu. Each group has a header icon and a // header label. @@ -22,7 +26,20 @@ public: METADATA_HEADER(CaptureModeMenuGroup); - CaptureModeMenuGroup(const gfx::VectorIcon& header_icon, + class Delegate { + public: + // Called when user selects an option. + virtual void OnOptionSelected(int option_id) const = 0; + + // Called to determine if an option with the given |option_id| is selected. + virtual bool IsOptionChecked(int option_id) const = 0; + + protected: + virtual ~Delegate() = default; + }; + + CaptureModeMenuGroup(Delegate* delegate, + const gfx::VectorIcon& header_icon, std::u16string header_label); CaptureModeMenuGroup(const CaptureModeMenuGroup&) = delete; CaptureModeMenuGroup& operator=(const CaptureModeMenuGroup&) = delete; @@ -32,9 +49,7 @@ // group. When the option is selected, its checked icon is visible. Otherwise // its checked icon is invisible. One and only one option's checked icon is // visible all the time. - void AddOption(views::Button::PressedCallback callback, - std::u16string option_label, - bool checked); + void AddOption(std::u16string option_label, int option_id); // Adds a menu item which has text to the menu group. Each menu item can have // its own customized behavior. For example, file save menu group's menu item @@ -43,11 +58,27 @@ void AddMenuItem(views::Button::PressedCallback callback, std::u16string item_label); + // For tests only: + views::View* GetOptionForTesting(int option_id); + bool IsOptionCheckedForTesting(views::View* option); + private: - // It's a container view for the option added via calls "AddOption()" and - // owned by its views hierarchy. We need it for grouping up options. For - // example, when user selects a custom folder, we need to add it to the end of - // the options instead of adding it after the menu item. + // This is the callback function on option click. It will select the + // clicked/pressed button, and unselect any previously selected button. + void HandleOptionClick(int option_id); + + // CaptureModeAdvancedSettingsView is the |delegate_| here. It's owned by + // its views hierarchy. + const Delegate* const delegate_; + + // Options added via calls "AddOption()". Options are owned by theirs views + // hierarchy. + std::vector<CaptureModeOption*> options_; + + // It's a container view for |options_|. It's owned by its views hierarchy. + // We need it for grouping up options. For example, when user selects a custom + // folder, we need to add it to the end of the options instead of adding it + // after the menu item. views::View* options_container_; };
diff --git a/ash/capture_mode/capture_mode_unittests.cc b/ash/capture_mode/capture_mode_unittests.cc index a27a71c..e7aa8500 100644 --- a/ash/capture_mode/capture_mode_unittests.cc +++ b/ash/capture_mode/capture_mode_unittests.cc
@@ -8,10 +8,12 @@ #include "ash/accessibility/magnifier/docked_magnifier_controller.h" #include "ash/accessibility/magnifier/magnifier_glass.h" #include "ash/app_list/app_list_controller_impl.h" +#include "ash/capture_mode/capture_mode_advanced_settings_view.h" #include "ash/capture_mode/capture_mode_bar_view.h" #include "ash/capture_mode/capture_mode_button.h" #include "ash/capture_mode/capture_mode_constants.h" #include "ash/capture_mode/capture_mode_controller.h" +#include "ash/capture_mode/capture_mode_menu_group.h" #include "ash/capture_mode/capture_mode_metrics.h" #include "ash/capture_mode/capture_mode_session.h" #include "ash/capture_mode/capture_mode_settings_entry_view.h" @@ -245,6 +247,11 @@ return session_->capture_mode_settings_view_; } + CaptureModeAdvancedSettingsView* capture_mode_advanced_settings_view() const { + EXPECT_TRUE(features::AreImprovedScreenCaptureSettingsEnabled()); + return session_->capture_mode_advanced_settings_view_; + } + views::Widget* capture_mode_settings_widget() const { return session_->capture_mode_settings_widget_.get(); } @@ -4616,4 +4623,67 @@ testing::Values(CaptureModeSource::kFullscreen, CaptureModeSource::kRegion, CaptureModeSource::kWindow)); + +// ----------------------------------------------------------------------------- +// CaptureModeAdvancedSettingsTest: + +// Test fixture for CaptureMode advanced settings view. +class CaptureModeAdvancedSettingsTest : public CaptureModeTest { + public: + CaptureModeAdvancedSettingsTest() = default; + ~CaptureModeAdvancedSettingsTest() override = default; + + // CaptureModeTest: + void SetUp() override { + scoped_feature_list_.InitAndEnableFeature( + features::kImprovedScreenCaptureSettings); + CaptureModeTest::SetUp(); + } + + CaptureModeAdvancedSettingsView* GetCaptureModeAdvancedSettingsView() const { + auto* session = CaptureModeController::Get()->capture_mode_session(); + DCHECK(session); + return CaptureModeSessionTestApi(session) + .capture_mode_advanced_settings_view(); + } + + protected: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +// Tests that clicking on audio input buttons updates the state in the +// controller, and persists between sessions. +TEST_F(CaptureModeAdvancedSettingsTest, AudioInputSettingsMenu) { + auto* controller = StartImageRegionCapture(); + auto* event_generator = GetEventGenerator(); + + // Test that the audio recording preference is defaulted to off. + ClickOnView(GetSettingsButton(), event_generator); + EXPECT_FALSE(controller->enable_audio_recording()); + + CaptureModeAdvancedSettingsView* settings_view = + GetCaptureModeAdvancedSettingsView(); + CaptureModeMenuGroup* audio_input_menu_group = + settings_view->GetAudioInputMenuGroupForTesting(); + views::View* microphone_option = + settings_view->GetMicrophoneOptionForTesting(); + views::View* off_option = settings_view->GetOffOptionForTesting(); + EXPECT_TRUE(audio_input_menu_group->IsOptionCheckedForTesting(off_option)); + EXPECT_FALSE( + audio_input_menu_group->IsOptionCheckedForTesting(microphone_option)); + + // Click on the |microphone| option. It should be checked after click along + // with |off| is unchecked. Recording preference is set to microphone. + ClickOnView(microphone_option, event_generator); + EXPECT_TRUE( + audio_input_menu_group->IsOptionCheckedForTesting(microphone_option)); + EXPECT_FALSE(audio_input_menu_group->IsOptionCheckedForTesting(off_option)); + EXPECT_TRUE(controller->enable_audio_recording()); + + // Test that the user selected audio preference for audio recording is + // remembered between sessions. + SendKey(ui::VKEY_ESCAPE, event_generator); + StartImageRegionCapture(); + EXPECT_TRUE(controller->enable_audio_recording()); +} } // namespace ash
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc index 1b0ee51b..d06066bf 100644 --- a/ash/constants/ash_features.cc +++ b/ash/constants/ash_features.cc
@@ -535,6 +535,10 @@ const base::Feature kFiltersInRecents{"FiltersInRecents", base::FEATURE_DISABLED_BY_DEFAULT}; +// Enables the firmware updater app. +const base::Feature kFirmwareUpdaterApp = {"FirmwareUpdaterApp", + base::FEATURE_DISABLED_BY_DEFAULT}; + // When enabled, there will be an alert bubble showing up when the device // returns from low brightness (e.g., sleep, closed cover) without a lock screen // and the active window is in fullscreen. @@ -1373,6 +1377,10 @@ return base::FeatureList::IsEnabled(kFilesSWA); } +bool IsFirmwareUpdaterAppEnabled() { + return base::FeatureList::IsEnabled(kFirmwareUpdaterApp); +} + bool IsFullscreenAlertBubbleEnabled() { return base::FeatureList::IsEnabled(kFullscreenAlertBubble); }
diff --git a/ash/constants/ash_features.h b/ash/constants/ash_features.h index 1a82b71d..e23066f 100644 --- a/ash/constants/ash_features.h +++ b/ash/constants/ash_features.h
@@ -207,6 +207,7 @@ COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kFilesTrash; COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kFilesZipUnpack; COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kFiltersInRecents; +COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kFirmwareUpdaterApp; COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kFullscreenAlertBubble; COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kFuseBox; @@ -493,6 +494,7 @@ COMPONENT_EXPORT(ASH_CONSTANTS) bool IsFamilyLinkOnSchoolDeviceEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsFastPairEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsFileManagerSwaEnabled(); +COMPONENT_EXPORT(ASH_CONSTANTS) bool IsFirmwareUpdaterAppEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsFullscreenAlertBubbleEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsGaiaCloseViewMessageEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsGaiaReauthEndpointEnabled();
diff --git a/ash/projector/projector_controller_impl.cc b/ash/projector/projector_controller_impl.cc index 96d000bd..9bb65f78 100644 --- a/ash/projector/projector_controller_impl.cc +++ b/ash/projector/projector_controller_impl.cc
@@ -107,6 +107,9 @@ } void ProjectorControllerImpl::OnSpeechRecognitionAvailable(bool available) { + if (ProjectorController::AreExtendedProjectorFeaturesDisabled()) + return; + if (available == is_speech_recognition_available_) return; @@ -132,7 +135,8 @@ } bool ProjectorControllerImpl::IsEligible() const { - return is_speech_recognition_available_; + return is_speech_recognition_available_ || + ProjectorController::AreExtendedProjectorFeaturesDisabled(); } bool ProjectorControllerImpl::CanStartNewSession() const { @@ -232,6 +236,9 @@ } void ProjectorControllerImpl::StartSpeechRecognition() { + if (ProjectorController::AreExtendedProjectorFeaturesDisabled()) + return; + DCHECK(is_speech_recognition_available_); DCHECK(!is_speech_recognition_on_); DCHECK_NE(client_, nullptr); @@ -240,6 +247,9 @@ } void ProjectorControllerImpl::StopSpeechRecognition() { + if (ProjectorController::AreExtendedProjectorFeaturesDisabled()) + return; + DCHECK(is_speech_recognition_available_); DCHECK(is_speech_recognition_on_); DCHECK_NE(client_, nullptr);
diff --git a/ash/public/cpp/projector/projector_controller.cc b/ash/public/cpp/projector/projector_controller.cc index e8eead1..f1fcabf05 100644 --- a/ash/public/cpp/projector/projector_controller.cc +++ b/ash/public/cpp/projector/projector_controller.cc
@@ -5,12 +5,19 @@ #include "ash/public/cpp/projector/projector_controller.h" #include "base/check_op.h" +#include "base/command_line.h" namespace ash { namespace { ProjectorController* g_instance = nullptr; -} + +// Controls whether to enable the extended features of Projector. These include +// speech recognition and drivefs integration. Only used during development to +// disable extended features in X11 simulator. +constexpr char kExtendedProjectorFeaturesDisabled[] = + "projector-extended-features-disabled"; +} // namespace ProjectorController::ProjectorController() { DCHECK_EQ(nullptr, g_instance); @@ -27,6 +34,12 @@ return g_instance; } +// static +bool ProjectorController::AreExtendedProjectorFeaturesDisabled() { + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + return command_line->HasSwitch(kExtendedProjectorFeaturesDisabled); +} + ProjectorController::ScopedInstanceResetterForTest:: ScopedInstanceResetterForTest() : controller_(g_instance) {
diff --git a/ash/public/cpp/projector/projector_controller.h b/ash/public/cpp/projector/projector_controller.h index 808fd0db..2cd526a 100644 --- a/ash/public/cpp/projector/projector_controller.h +++ b/ash/public/cpp/projector/projector_controller.h
@@ -36,6 +36,10 @@ static ProjectorController* Get(); + // Returns whether the extended features for projector are enabled. This is + // decided based on a command line switch. + static bool AreExtendedProjectorFeaturesDisabled(); + // Starts a capture mode session for the projector workflow if no video // recording is currently in progress. `storage_dir` is the container // directory name for screencasts and will be used to create the storage path.
diff --git a/ash/shelf/shelf_app_button.cc b/ash/shelf/shelf_app_button.cc index 0affda1..614d890 100644 --- a/ash/shelf/shelf_app_button.cc +++ b/ash/shelf/shelf_app_button.cc
@@ -25,7 +25,6 @@ #include "ui/accessibility/ax_action_data.h" #include "ui/accessibility/ax_node_data.h" #include "ui/base/resource/resource_bundle.h" -#include "ui/base/ui_base_features.h" #include "ui/compositor/layer.h" #include "ui/compositor/scoped_layer_animation_settings.h" #include "ui/gfx/animation/animation_delegate.h" @@ -280,9 +279,7 @@ shelf_view_(shelf_view), indicator_(new AppStatusIndicatorView()), notification_indicator_(nullptr), - state_(STATE_NORMAL), - is_notification_indicator_enabled_( - features::IsNotificationIndicatorEnabled()) { + state_(STATE_NORMAL) { const gfx::ShadowValue kShadows[] = { gfx::ShadowValue(gfx::Vector2d(0, 2), 0, SkColorSetARGB(0x1A, 0, 0, 0)), gfx::ShadowValue(gfx::Vector2d(0, 3), 1, SkColorSetARGB(0x1A, 0, 0, 0)), @@ -326,10 +323,9 @@ AddChildView(indicator_); AddChildView(icon_view_); - if (is_notification_indicator_enabled_) { - notification_indicator_ = views::DotIndicator::Install(this); - SetNotificationBadgeColor(kDefaultIndicatorColor); - } + notification_indicator_ = views::DotIndicator::Install(this); + SetNotificationBadgeColor(kDefaultIndicatorColor); + views::InkDrop::Get(this)->GetInkDrop()->AddObserver(this); // Do not set a clip, allow the ink drop to burst out. @@ -400,7 +396,7 @@ if (state & STATE_ACTIVE) indicator_->ShowActiveStatus(true); - if (is_notification_indicator_enabled_ && (state & STATE_NOTIFICATION)) + if (state & STATE_NOTIFICATION) notification_indicator_->Show(); if (state & STATE_DRAGGING) @@ -417,7 +413,7 @@ if (state & STATE_ACTIVE) indicator_->ShowActiveStatus(false); - if (is_notification_indicator_enabled_ && (state & STATE_NOTIFICATION)) + if (state & STATE_NOTIFICATION) notification_indicator_->Hide(); if (state & STATE_DRAGGING) @@ -506,12 +502,10 @@ } void ShelfAppButton::ReflectItemStatus(const ShelfItem& item) { - if (features::IsNotificationIndicatorEnabled()) { - if (item.has_notification) - AddState(ShelfAppButton::STATE_NOTIFICATION); - else - ClearState(ShelfAppButton::STATE_NOTIFICATION); - } + if (item.has_notification) + AddState(ShelfAppButton::STATE_NOTIFICATION); + else + ClearState(ShelfAppButton::STATE_NOTIFICATION); app_status_ = item.app_status; @@ -705,10 +699,8 @@ icon_view_->SetBoundsRect(icon_view_bounds); - if (is_notification_indicator_enabled_) { - notification_indicator_->SetBoundsRect( - GetNotificationIndicatorBounds(icon_scale_)); - } + notification_indicator_->SetBoundsRect( + GetNotificationIndicatorBounds(icon_scale_)); // The indicators should be aligned with the icon, not the icon + shadow. // Use 1.0 as icon scale for |indicator_midpoint|, otherwise integer rounding
diff --git a/ash/shelf/shelf_app_button.h b/ash/shelf/shelf_app_button.h index 3425a7a..577bdb97 100644 --- a/ash/shelf/shelf_app_button.h +++ b/ash/shelf/shelf_app_button.h
@@ -200,9 +200,6 @@ gfx::ShadowValues icon_shadows_; - // Whether the notification indicator is enabled. - const bool is_notification_indicator_enabled_; - // The bitmap image for this app button. gfx::ImageSkia icon_image_;
diff --git a/ash/shelf/shelf_controller.cc b/ash/shelf/shelf_controller.cc index d238dda..631d10b 100644 --- a/ash/shelf/shelf_controller.cc +++ b/ash/shelf/shelf_controller.cc
@@ -23,7 +23,6 @@ #include "components/prefs/pref_service.h" #include "components/services/app_service/public/cpp/app_registry_cache_wrapper.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/base/ui_base_features.h" #include "ui/display/display.h" #include "ui/display/screen.h" @@ -99,9 +98,7 @@ } // namespace -ShelfController::ShelfController() - : is_notification_indicator_enabled_( - features::IsNotificationIndicatorEnabled()) { +ShelfController::ShelfController() { ShelfModel::SetInstance(&model_); Shell::Get()->session_controller()->AddObserver(this); @@ -150,30 +147,27 @@ pref_change_registrar_->Add(prefs::kShelfPreferences, base::BindRepeating(&SetShelfBehaviorsFromPrefs)); - if (is_notification_indicator_enabled_) { - pref_change_registrar_->Add( - prefs::kAppNotificationBadgingEnabled, - base::BindRepeating(&ShelfController::UpdateAppNotificationBadging, - base::Unretained(this))); + pref_change_registrar_->Add( + prefs::kAppNotificationBadgingEnabled, + base::BindRepeating(&ShelfController::UpdateAppNotificationBadging, + base::Unretained(this))); - // Observe AppRegistryCache for the current active account to get - // notification updates. - AccountId account_id = - Shell::Get()->session_controller()->GetActiveAccountId(); - cache_ = - apps::AppRegistryCacheWrapper::Get().GetAppRegistryCache(account_id); - Observe(cache_); + // Observe AppRegistryCache for the current active account to get + // notification updates. + AccountId account_id = + Shell::Get()->session_controller()->GetActiveAccountId(); + cache_ = apps::AppRegistryCacheWrapper::Get().GetAppRegistryCache(account_id); + Observe(cache_); - // Resetting the recorded pref forces the next call to - // UpdateAppNotificationBadging() to update notification badging for every - // app item. - notification_badging_pref_enabled_.reset(); + // Resetting the recorded pref forces the next call to + // UpdateAppNotificationBadging() to update notification badging for every + // app item. + notification_badging_pref_enabled_.reset(); - // Update the notification badge indicator for all apps. This will also - // ensure that apps have the correct notification badge value for the - // multiprofile case when switching between users. - UpdateAppNotificationBadging(); - } + // Update the notification badge indicator for all apps. This will also + // ensure that apps have the correct notification badge value for the + // multiprofile case when switching between users. + UpdateAppNotificationBadging(); } void ShelfController::OnTabletModeStarted() { @@ -235,8 +229,7 @@ } void ShelfController::ShelfItemAdded(int index) { - if (!cache_ || !is_notification_indicator_enabled_ || - !notification_badging_pref_enabled_.value_or(false)) + if (!cache_ || !notification_badging_pref_enabled_.value_or(false)) return; auto app_id = model_.items()[index].id.app_id;
diff --git a/ash/shelf/shelf_controller.h b/ash/shelf/shelf_controller.h index b260ad33..0f67c53 100644 --- a/ash/shelf/shelf_controller.h +++ b/ash/shelf/shelf_controller.h
@@ -70,9 +70,6 @@ // The shelf model shared by all shelf instances. ShelfModel model_; - // Whether notification indicators are enabled for app icons in the shelf. - const bool is_notification_indicator_enabled_; - // Whether the pref for notification badging is enabled. absl::optional<bool> notification_badging_pref_enabled_;
diff --git a/ash/shelf/shelf_controller_unittest.cc b/ash/shelf/shelf_controller_unittest.cc index b55c80d..070c94ec 100644 --- a/ash/shelf/shelf_controller_unittest.cc +++ b/ash/shelf/shelf_controller_unittest.cc
@@ -24,10 +24,8 @@ #include "ash/wm/window_util.h" #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" -#include "base/test/scoped_feature_list.h" #include "components/prefs/pref_service.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/ui_base_features.h" #include "ui/gfx/image/image_unittest_util.h" #include "ui/message_center/message_center.h" #include "ui/message_center/public/cpp/notifier_id.h" @@ -82,8 +80,6 @@ ~ShelfControllerNotificationIndicatorTest() override = default; void SetUp() override { - scoped_feature_list_.InitWithFeatures({features::kNotificationIndicator}, - {}); AshTestBase::SetUp(); account_id_ = AccountId::FromUserEmail("test@gmail.com"); @@ -106,7 +102,6 @@ private: AccountId account_id_; - base::test::ScopedFeatureList scoped_feature_list_; }; // Tests that the ShelfController keeps the ShelfModel updated on calls to
diff --git a/ash/shelf/shelf_view_unittest.cc b/ash/shelf/shelf_view_unittest.cc index 77d4d298..1bfcb867 100644 --- a/ash/shelf/shelf_view_unittest.cc +++ b/ash/shelf/shelf_view_unittest.cc
@@ -69,7 +69,6 @@ #include "ui/aura/window_event_dispatcher.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/test/ui_controls.h" -#include "ui/base/ui_base_features.h" #include "ui/compositor/layer.h" #include "ui/compositor/scoped_animation_duration_scale_mode.h" #include "ui/display/display.h" @@ -2311,27 +2310,9 @@ .x()); } -// Test class that enables notification indicators. -class NotificationIndicatorTest : public ShelfViewTest { - public: - NotificationIndicatorTest() { - scoped_feature_list_.InitAndEnableFeature( - ::features::kNotificationIndicator); - } - - NotificationIndicatorTest(const NotificationIndicatorTest&) = delete; - NotificationIndicatorTest& operator=(const NotificationIndicatorTest&) = - delete; - - ~NotificationIndicatorTest() override = default; - - private: - base::test::ScopedFeatureList scoped_feature_list_; -}; - // Tests that an item has a notification badge indicator when the notification // is added and removed. -TEST_F(NotificationIndicatorTest, ItemHasCorrectNotificationBadgeIndicator) { +TEST_F(ShelfViewTest, ItemHasCorrectNotificationBadgeIndicator) { const ShelfID item_id = AddApp(); const ShelfAppButton* shelf_app_button = GetButtonByID(item_id);
diff --git a/ash/system/bluetooth/bluetooth_detailed_view_controller.cc b/ash/system/bluetooth/bluetooth_detailed_view_controller.cc index 9782dd99..c86f4f9 100644 --- a/ash/system/bluetooth/bluetooth_detailed_view_controller.cc +++ b/ash/system/bluetooth/bluetooth_detailed_view_controller.cc
@@ -12,6 +12,7 @@ #include "ash/system/model/system_tray_model.h" #include "base/check.h" #include "chromeos/services/bluetooth_config/public/cpp/cros_bluetooth_config_util.h" +#include "mojo/public/cpp/bindings/clone_traits.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "ui/base/l10n/l10n_util.h" #include "ui/views/view.h" @@ -19,6 +20,7 @@ namespace ash { namespace { using chromeos::bluetooth_config::IsBluetoothEnabledOrEnabling; +using chromeos::bluetooth_config::mojom::DeviceConnectionState; } // namespace BluetoothDetailedViewController::BluetoothDetailedViewController( @@ -45,6 +47,11 @@ bluetooth_detailed_view.get()); BluetoothEnabledStateChanged(); + if (IsBluetoothEnabledOrEnabling(system_state_)) { + device_list_controller_->UpdateDeviceList(connected_devices_, + previously_connected_devices_); + } + // We are expected to return an unowned pointer that the caller is responsible // for deleting. return bluetooth_detailed_view.release()->GetAsView(); @@ -64,6 +71,22 @@ if (has_bluetooth_enabled_state_changed) BluetoothEnabledStateChanged(); + + connected_devices_.clear(); + previously_connected_devices_.clear(); + + for (auto& paired_device : properties->paired_devices) { + if (paired_device->device_properties->connection_state == + DeviceConnectionState::kConnected) { + connected_devices_.push_back(std::move(paired_device)); + } else { + previously_connected_devices_.push_back(std::move(paired_device)); + } + } + if (device_list_controller_ && IsBluetoothEnabledOrEnabling(system_state_)) { + device_list_controller_->UpdateDeviceList(connected_devices_, + previously_connected_devices_); + } } void BluetoothDetailedViewController::OnToggleClicked(bool new_state) {
diff --git a/ash/system/bluetooth/bluetooth_detailed_view_controller.h b/ash/system/bluetooth/bluetooth_detailed_view_controller.h index 412d961d..b4ee723 100644 --- a/ash/system/bluetooth/bluetooth_detailed_view_controller.h +++ b/ash/system/bluetooth/bluetooth_detailed_view_controller.h
@@ -7,6 +7,7 @@ #include <memory> #include <string> +#include <vector> #include "ash/ash_export.h" #include "ash/system/bluetooth/bluetooth_detailed_view.h" @@ -41,6 +42,10 @@ const BluetoothDetailedViewController&) = delete; ~BluetoothDetailedViewController() override; + protected: + using PairedBluetoothDevicePropertiesPtrs = std::vector< + chromeos::bluetooth_config::mojom::PairedBluetoothDevicePropertiesPtr>; + private: // DetailedViewControllerBase: views::View* CreateView() override; @@ -73,6 +78,8 @@ chromeos::bluetooth_config::mojom::BluetoothSystemState::kUnavailable; tray::BluetoothDetailedView* view_ = nullptr; std::unique_ptr<BluetoothDeviceListController> device_list_controller_; + PairedBluetoothDevicePropertiesPtrs connected_devices_; + PairedBluetoothDevicePropertiesPtrs previously_connected_devices_; }; } // namespace ash
diff --git a/ash/system/bluetooth/bluetooth_detailed_view_controller_unittest.cc b/ash/system/bluetooth/bluetooth_detailed_view_controller_unittest.cc index 5fa4c51..dc06172c 100644 --- a/ash/system/bluetooth/bluetooth_detailed_view_controller_unittest.cc +++ b/ash/system/bluetooth/bluetooth_detailed_view_controller_unittest.cc
@@ -5,6 +5,7 @@ #include "ash/system/bluetooth/bluetooth_detailed_view_controller.h" #include <memory> +#include <vector> #include "ash/constants/ash_features.h" #include "ash/public/cpp/test/test_system_tray_client.h" @@ -17,15 +18,21 @@ #include "base/run_loop.h" #include "base/test/scoped_feature_list.h" #include "chromeos/services/bluetooth_config/fake_adapter_state_controller.h" +#include "chromeos/services/bluetooth_config/fake_device_cache.h" #include "chromeos/services/bluetooth_config/public/mojom/cros_bluetooth_config.mojom.h" #include "chromeos/services/bluetooth_config/scoped_bluetooth_config_test_helper.h" +#include "mojo/public/cpp/bindings/clone_traits.h" namespace ash { namespace tray { namespace { using chromeos::bluetooth_config::AdapterStateController; +using chromeos::bluetooth_config::mojom::BluetoothDeviceProperties; using chromeos::bluetooth_config::mojom::BluetoothSystemState; +using chromeos::bluetooth_config::mojom::DeviceConnectionState; +using chromeos::bluetooth_config::mojom::PairedBluetoothDeviceProperties; +using chromeos::bluetooth_config::mojom::PairedBluetoothDevicePropertiesPtr; class FakeBluetoothDetailedViewFactory : public BluetoothDetailedView::Factory { public: @@ -121,6 +128,22 @@ ->GetAdapterState(); } + PairedBluetoothDevicePropertiesPtr CreatePairedDevice( + DeviceConnectionState connection_state) { + PairedBluetoothDevicePropertiesPtr paired_properties = + PairedBluetoothDeviceProperties::New(); + paired_properties->device_properties = BluetoothDeviceProperties::New(); + paired_properties->device_properties->connection_state = connection_state; + return paired_properties; + } + + void SetPairedDevices( + std::vector<PairedBluetoothDevicePropertiesPtr> paired_devices) { + scoped_bluetooth_config_test_helper_.fake_device_cache()->SetPairedDevices( + std::move(paired_devices)); + base::RunLoop().RunUntilIdle(); + } + void SetBluetoothAdapterState(BluetoothSystemState system_state) { scoped_bluetooth_config_test_helper_.fake_adapter_state_controller() ->SetSystemState(system_state); @@ -200,5 +223,28 @@ EXPECT_EQ(1, GetSystemTrayClient()->show_bluetooth_pairing_dialog_count()); } +TEST_F(BluetoothDetailedViewControllerTest, + CorrectlySplitsDevicesByConnectionState) { + std::vector<PairedBluetoothDevicePropertiesPtr> paired_devices; + paired_devices.push_back( + CreatePairedDevice(DeviceConnectionState::kNotConnected)); + paired_devices.push_back( + CreatePairedDevice(DeviceConnectionState::kConnecting)); + paired_devices.push_back( + CreatePairedDevice(DeviceConnectionState::kConnected)); + + EXPECT_EQ(0u, bluetooth_device_list_controller()->connected_devices_count()); + EXPECT_EQ( + 0u, + bluetooth_device_list_controller()->previously_connected_devices_count()); + + SetPairedDevices(std::move(paired_devices)); + + EXPECT_EQ(1u, bluetooth_device_list_controller()->connected_devices_count()); + EXPECT_EQ( + 2u, + bluetooth_device_list_controller()->previously_connected_devices_count()); +} + } // namespace tray } // namespace ash
diff --git a/ash/system/bluetooth/bluetooth_detailed_view_impl.cc b/ash/system/bluetooth/bluetooth_detailed_view_impl.cc index 9a4f6c1..5529751 100644 --- a/ash/system/bluetooth/bluetooth_detailed_view_impl.cc +++ b/ash/system/bluetooth/bluetooth_detailed_view_impl.cc
@@ -97,6 +97,11 @@ return scroll_content(); } +void BluetoothDetailedViewImpl::HandleViewClicked(views::View* view) { + delegate()->OnDeviceListItemSelected( + static_cast<BluetoothDeviceListItemView*>(view)->device_properties()); +} + const char* BluetoothDetailedViewImpl::GetClassName() const { return "BluetoothDetailedViewImpl"; }
diff --git a/ash/system/bluetooth/bluetooth_detailed_view_impl.h b/ash/system/bluetooth/bluetooth_detailed_view_impl.h index ebd4e1bb..b12f8b7 100644 --- a/ash/system/bluetooth/bluetooth_detailed_view_impl.h +++ b/ash/system/bluetooth/bluetooth_detailed_view_impl.h
@@ -58,6 +58,9 @@ void NotifyDeviceListChanged() override; views::View* device_list() override; + // TrayDetailedView: + void HandleViewClicked(views::View* view) override; + // views::View: const char* GetClassName() const override;
diff --git a/ash/system/bluetooth/bluetooth_detailed_view_unittest.cc b/ash/system/bluetooth/bluetooth_detailed_view_unittest.cc index 6271baf50..40f3640 100644 --- a/ash/system/bluetooth/bluetooth_detailed_view_unittest.cc +++ b/ash/system/bluetooth/bluetooth_detailed_view_unittest.cc
@@ -10,6 +10,7 @@ #include "ash/public/cpp/test/test_system_tray_client.h" #include "ash/strings/grit/ash_strings.h" #include "ash/system/bluetooth/bluetooth_detailed_view_impl.h" +#include "ash/system/bluetooth/bluetooth_device_list_item_view.h" #include "ash/system/bluetooth/bluetooth_disabled_detailed_view.h" #include "ash/system/tray/detailed_view_delegate.h" #include "ash/system/unified/top_shortcut_button.h" @@ -35,6 +36,9 @@ namespace tray { namespace { +const std::string kDeviceNickname = "mau5"; + +using chromeos::bluetooth_config::mojom::PairedBluetoothDeviceProperties; using chromeos::bluetooth_config::mojom::PairedBluetoothDevicePropertiesPtr; class FakeBluetoothDetailedViewDelegate @@ -294,5 +298,28 @@ EXPECT_EQ(view_center, button_center.y()); } +TEST_F(BluetoothDetailedViewTest, SelectingDeviceListItemNotifiesDelegate) { + bluetooth_detailed_view()->UpdateBluetoothEnabledState(true); + + PairedBluetoothDevicePropertiesPtr paired_properties = + PairedBluetoothDeviceProperties::New(); + paired_properties->nickname = kDeviceNickname; + + BluetoothDeviceListItemView* device_list_item = + bluetooth_detailed_view()->AddDeviceListItem(); + device_list_item->UpdateDeviceProperties(paired_properties); + + bluetooth_detailed_view()->NotifyDeviceListChanged(); + + EXPECT_FALSE( + bluetooth_detailed_view_delegate()->last_device_list_item_selected()); + ClickOnAndWait(device_list_item); + EXPECT_TRUE( + bluetooth_detailed_view_delegate()->last_device_list_item_selected()); + EXPECT_EQ(kDeviceNickname, bluetooth_detailed_view_delegate() + ->last_device_list_item_selected() + ->nickname); +} + } // namespace tray } // namespace ash
diff --git a/ash/system/bluetooth/bluetooth_device_list_controller_impl.cc b/ash/system/bluetooth/bluetooth_device_list_controller_impl.cc index 695fef46..c332887 100644 --- a/ash/system/bluetooth/bluetooth_device_list_controller_impl.cc +++ b/ash/system/bluetooth/bluetooth_device_list_controller_impl.cc
@@ -7,12 +7,32 @@ #include "ash/constants/ash_features.h" #include "ash/strings/grit/ash_strings.h" #include "ash/system/bluetooth/bluetooth_detailed_view.h" +#include "ash/system/bluetooth/bluetooth_device_list_item_view.h" +#include "ash/system/tray/tray_popup_utils.h" #include "ash/system/tray/tri_view.h" #include "base/check.h" #include "ui/gfx/paint_vector_icon.h" +#include "ui/views/controls/separator.h" #include "ui/views/view.h" namespace ash { +namespace { + +// Helper function to remove |*view| from its view hierarchy, delete the view, +// and reset the value of |*view| to be |nullptr|. +template <class T> +void RemoveAndResetViewIfExists(T** view) { + DCHECK(view); + + views::View* parent = (*view)->parent(); + + if (*view && parent) { + parent->RemoveChildViewT(*view); + *view = nullptr; + } +} + +} // namespace BluetoothDeviceListControllerImpl::BluetoothDeviceListControllerImpl( tray::BluetoothDetailedView* bluetooth_detailed_view) @@ -20,10 +40,19 @@ DCHECK(ash::features::IsBluetoothRevampEnabled()); } +BluetoothDeviceListControllerImpl::~BluetoothDeviceListControllerImpl() = + default; + void BluetoothDeviceListControllerImpl::UpdateBluetoothEnabledState( bool enabled) { - if (is_bluetooth_enabled_ && !enabled) + if (is_bluetooth_enabled_ && !enabled) { + device_id_to_view_map_.clear(); + device_list_separator_ = nullptr; + connected_sub_header_ = nullptr; + no_device_connected_sub_header_ = nullptr; + previously_connected_sub_header_ = nullptr; bluetooth_detailed_view_->device_list()->RemoveAllChildViews(); + } is_bluetooth_enabled_ = enabled; } @@ -31,16 +60,89 @@ const PairedBluetoothDevicePropertiesPtrs& connected, const PairedBluetoothDevicePropertiesPtrs& previously_connected) { DCHECK(is_bluetooth_enabled_); - currently_connected_devices_sub_header_ = AddOrReorderSubHeader( - currently_connected_devices_sub_header_, - IDS_ASH_STATUS_TRAY_BLUETOOTH_CURRENTLY_CONNECTED_DEVICES, 1); - previously_connected_devices_sub_header_ = AddOrReorderSubHeader( - previously_connected_devices_sub_header_, - IDS_ASH_STATUS_TRAY_BLUETOOTH_PREVIOUSLY_CONNECTED_DEVICES, 2); + + // This function will create views for new devices, re-use views for existing + // devices, and remove views for devices that no longer exist. To do this, we + // keep track of all the preexisting views in |previous_views|, removing a + // view from this map when the corresponding device is found in |connected| or + // |previously_connected|. Before returning, any view remaining in + // |previous_views| is no longer needed and is deleted. + base::flat_map<std::string, BluetoothDeviceListItemView*> previous_views = + std::move(device_id_to_view_map_); + device_id_to_view_map_.clear(); + + // Since we re-use views when possible, we need to re-order them to match the + // order of the devices we are provided with. We use |index| to keep track of + // the next index within the device list where a view should be placed, i.e. + // all views before |index| are in their final position. + int index = 0; + + // The list of connected devices. + if (!connected.empty()) { + connected_sub_header_ = CreateSubHeaderIfMissingAndReorder( + connected_sub_header_, + IDS_ASH_STATUS_TRAY_BLUETOOTH_CURRENTLY_CONNECTED_DEVICES, index); + + // Increment |index| since this position was taken by + // |connected_sub_header_|. + index++; + + index = CreateViewsIfMissingAndReorder(connected, &previous_views, index); + } else { + RemoveAndResetViewIfExists(&connected_sub_header_); + } + + // The separator between the connected and previously connected devices. + if (!connected.empty() && !previously_connected.empty()) { + if (!device_list_separator_) { + device_list_separator_ = + bluetooth_detailed_view_->device_list()->AddChildView( + TrayPopupUtils::CreateListSubHeaderSeparator()); + } + bluetooth_detailed_view_->device_list()->ReorderChildView( + device_list_separator_, index); + + // Increment |index| since this position was taken by + // |device_list_separator_|. + index++; + } else { + RemoveAndResetViewIfExists(&device_list_separator_); + } + + // The previously connected devices. + if (!previously_connected.empty()) { + previously_connected_sub_header_ = CreateSubHeaderIfMissingAndReorder( + previously_connected_sub_header_, + IDS_ASH_STATUS_TRAY_BLUETOOTH_PREVIOUSLY_CONNECTED_DEVICES, index); + + // Increment |index| since this position was taken by + // |previously_connected_sub_header_|. + index++; + + // Ignore the returned index since we are now done re-ordering the list. + CreateViewsIfMissingAndReorder(previously_connected, &previous_views, + index); + } else { + RemoveAndResetViewIfExists(&previously_connected_sub_header_); + } + + // The header when there are no connected or previously connected devices. + if (device_id_to_view_map_.empty()) { + no_device_connected_sub_header_ = CreateSubHeaderIfMissingAndReorder( + no_device_connected_sub_header_, + IDS_ASH_STATUS_TRAY_BLUETOOTH_NO_DEVICE_CONNECTED, index); + } else { + RemoveAndResetViewIfExists(&no_device_connected_sub_header_); + } + + for (const auto& id_and_view : previous_views) { + bluetooth_detailed_view_->device_list()->RemoveChildViewT( + id_and_view.second); + } bluetooth_detailed_view_->NotifyDeviceListChanged(); } -TriView* BluetoothDeviceListControllerImpl::AddOrReorderSubHeader( +TriView* BluetoothDeviceListControllerImpl::CreateSubHeaderIfMissingAndReorder( TriView* sub_header, int text_id, int index) { @@ -52,4 +154,34 @@ return sub_header; } +int BluetoothDeviceListControllerImpl::CreateViewsIfMissingAndReorder( + const PairedBluetoothDevicePropertiesPtrs& device_property_list, + base::flat_map<std::string, BluetoothDeviceListItemView*>* previous_views, + int index) { + DCHECK(previous_views); + + BluetoothDeviceListItemView* device_view = nullptr; + + for (const auto& device_properties : device_property_list) { + const std::string& device_id = device_properties->device_properties->id; + auto it = previous_views->find(device_id); + + if (it == previous_views->end()) { + device_view = bluetooth_detailed_view_->AddDeviceListItem(); + } else { + device_view = it->second; + previous_views->erase(it); + } + device_id_to_view_map_.emplace(device_id, device_view); + + device_view->UpdateDeviceProperties(device_properties); + bluetooth_detailed_view_->device_list()->ReorderChildView(device_view, + index); + + // Increment |index| since this position was taken by |device_view|. + index++; + } + return index; +} + } // namespace ash
diff --git a/ash/system/bluetooth/bluetooth_device_list_controller_impl.h b/ash/system/bluetooth/bluetooth_device_list_controller_impl.h index 687a047..787747a 100644 --- a/ash/system/bluetooth/bluetooth_device_list_controller_impl.h +++ b/ash/system/bluetooth/bluetooth_device_list_controller_impl.h
@@ -5,15 +5,24 @@ #ifndef ASH_SYSTEM_BLUETOOTH_BLUETOOTH_DEVICE_LIST_CONTROLLER_IMPL_H_ #define ASH_SYSTEM_BLUETOOTH_BLUETOOTH_DEVICE_LIST_CONTROLLER_IMPL_H_ +#include <string> +#include <vector> + #include "ash/ash_export.h" #include "ash/system/bluetooth/bluetooth_device_list_controller.h" +#include "base/containers/flat_map.h" #include "chromeos/services/bluetooth_config/public/mojom/cros_bluetooth_config.mojom.h" +namespace views { +class Separator; +} // namespace views + namespace ash { namespace tray { class BluetoothDetailedView; } // namespace tray +class BluetoothDeviceListItemView; class TriView; // BluetoothDeviceListController implementation. @@ -26,25 +35,44 @@ delete; BluetoothDeviceListControllerImpl& operator=( const BluetoothDeviceListControllerImpl&) = delete; - ~BluetoothDeviceListControllerImpl() override = default; + ~BluetoothDeviceListControllerImpl() override; private: + friend class BluetoothDeviceListControllerTest; + // BluetoothDeviceListController: void UpdateBluetoothEnabledState(bool enabled) override; void UpdateDeviceList( const PairedBluetoothDevicePropertiesPtrs& connected, const PairedBluetoothDevicePropertiesPtrs& previously_connected) override; - // Adds a new sub-header with |text_id| if |sub_header| is |nullptr|, - // otherwise reuses |sub_header|. Whichever sub-header used is then reordered - // to |index| and returned. - TriView* AddOrReorderSubHeader(TriView* sub_header, int text_id, int index); + // Creates a sub-header with text represented by the |text_id| message ID when + // |sub_header| is |nullptr|, otherwise uses the provided |sub_header|. The + // used sub-header is then moved to index |index| within the device list and + // returned. + TriView* CreateSubHeaderIfMissingAndReorder(TriView* sub_header, + int text_id, + int index); + + // Creates and initializes a view for each of the device properties within + // |device_property_list| if a view does not already exist, otherwise re-using + // the existing view to avoid disrupting a11y. Each view will be reordered to + // start at |index| and will be removed from |previous_views|. The index of + // the position after the final view that was added is returned. + int CreateViewsIfMissingAndReorder( + const PairedBluetoothDevicePropertiesPtrs& device_property_list, + base::flat_map<std::string, BluetoothDeviceListItemView*>* previous_views, + int index); tray::BluetoothDetailedView* bluetooth_detailed_view_; bool is_bluetooth_enabled_ = false; - TriView* currently_connected_devices_sub_header_ = nullptr; - TriView* previously_connected_devices_sub_header_ = nullptr; + base::flat_map<std::string, BluetoothDeviceListItemView*> + device_id_to_view_map_; + views::Separator* device_list_separator_ = nullptr; + TriView* connected_sub_header_ = nullptr; + TriView* no_device_connected_sub_header_ = nullptr; + TriView* previously_connected_sub_header_ = nullptr; }; } // namespace ash
diff --git a/ash/system/bluetooth/bluetooth_device_list_controller_unittest.cc b/ash/system/bluetooth/bluetooth_device_list_controller_unittest.cc index 43af681d..f619098 100644 --- a/ash/system/bluetooth/bluetooth_device_list_controller_unittest.cc +++ b/ash/system/bluetooth/bluetooth_device_list_controller_unittest.cc
@@ -5,14 +5,35 @@ #include "ash/system/bluetooth/bluetooth_device_list_controller_impl.h" #include <memory> +#include <string> +#include <vector> #include "ash/constants/ash_features.h" +#include "ash/strings/grit/ash_strings.h" #include "ash/system/bluetooth/bluetooth_detailed_view.h" +#include "ash/system/bluetooth/bluetooth_device_list_item_view.h" #include "ash/system/bluetooth/fake_bluetooth_detailed_view.h" +#include "ash/system/tray/tri_view.h" #include "ash/test/ash_test_base.h" #include "base/test/scoped_feature_list.h" +#include "chromeos/services/bluetooth_config/public/mojom/cros_bluetooth_config.mojom.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/views/controls/label.h" +#include "ui/views/controls/separator.h" namespace ash { +namespace { + +using chromeos::bluetooth_config::mojom::BluetoothDeviceProperties; +using chromeos::bluetooth_config::mojom::DeviceConnectionState; +using chromeos::bluetooth_config::mojom::PairedBluetoothDeviceProperties; +using chromeos::bluetooth_config::mojom::PairedBluetoothDevicePropertiesPtr; + +const char kDeviceId1[] = "/device/id/1"; +const char kDeviceId2[] = "/device/id/2"; +const char kDeviceNickname[] = "mau5"; + +} // namespace class BluetoothDeviceListControllerTest : public AshTestBase { public: @@ -30,15 +51,140 @@ void TearDown() override { AshTestBase::TearDown(); } - tray::BluetoothDetailedView* bluetooth_detailed_view() { - return fake_bluetooth_detailed_view_.get(); + const TriView* FindConnectedSubHeader() { + return FindSubHeaderWithText(l10n_util::GetStringUTF16( + IDS_ASH_STATUS_TRAY_BLUETOOTH_CURRENTLY_CONNECTED_DEVICES)); + } + + const TriView* FindPreviouslyConnectedSubHeader() { + return FindSubHeaderWithText(l10n_util::GetStringUTF16( + IDS_ASH_STATUS_TRAY_BLUETOOTH_PREVIOUSLY_CONNECTED_DEVICES)); + } + + const TriView* FindNoDeviceConnectedSubHeader() { + return FindSubHeaderWithText(l10n_util::GetStringUTF16( + IDS_ASH_STATUS_TRAY_BLUETOOTH_NO_DEVICE_CONNECTED)); + } + + const views::Separator* FindSeparator() { + for (const auto* view : device_list()->children()) { + if (!std::strcmp("Separator", view->GetClassName())) + return static_cast<const views::Separator*>(view); + } + return nullptr; + } + + PairedBluetoothDevicePropertiesPtr BuildDeviceProperties( + const std::string& id) { + PairedBluetoothDevicePropertiesPtr device_properties = + PairedBluetoothDeviceProperties::New(); + device_properties->device_properties = BluetoothDeviceProperties::New(); + device_properties->device_properties->id = id; + return device_properties; + } + + const std::u16string& GetSubHeaderText(const TriView* sub_header) { + EXPECT_TRUE(sub_header); + EXPECT_EQ(1u, sub_header->children().at(1)->children().size()); + return static_cast<views::Label*>( + sub_header->children().at(1)->children().at(0)) + ->GetText(); + } + + const char* GetDeviceId(const BluetoothDeviceListItemView* device_item_view) { + return device_item_view->device_properties()->device_properties->id.c_str(); + } + + const BluetoothDeviceListItemView* GetFirstDeviceView() { + EXPECT_LT(1u, device_list()->children().size()); + return static_cast<BluetoothDeviceListItemView*>( + device_list()->children().at(1)); + } + + void CheckDeviceListOrdering(size_t connected_device_count, + size_t previously_connected_device_count) { + if (connected_device_count && previously_connected_device_count) { + const TriView* connected_sub_header = FindConnectedSubHeader(); + const TriView* previously_connected_sub_header = + FindPreviouslyConnectedSubHeader(); + const views::Separator* device_list_separator = FindSeparator(); + + EXPECT_TRUE(connected_sub_header); + EXPECT_TRUE(previously_connected_sub_header); + EXPECT_TRUE(device_list_separator); + + const unsigned int connected_index = + device_list()->GetIndexOf(connected_sub_header); + const unsigned int previously_connected_index = + device_list()->GetIndexOf(previously_connected_sub_header); + const unsigned int separator_index = + device_list()->GetIndexOf(device_list_separator); + + EXPECT_EQ(0u, connected_index); + EXPECT_EQ(connected_device_count + 1, separator_index); + EXPECT_EQ(separator_index + 1, previously_connected_index); + return; + } + + if (connected_device_count) { + const TriView* connected_sub_header = FindConnectedSubHeader(); + EXPECT_TRUE(connected_sub_header); + EXPECT_EQ(0, device_list()->GetIndexOf(connected_sub_header)); + EXPECT_EQ(connected_device_count + 1, device_list()->children().size()); + return; + } + + if (previously_connected_device_count) { + const TriView* previously_connected_sub_header = + FindPreviouslyConnectedSubHeader(); + EXPECT_TRUE(previously_connected_sub_header); + EXPECT_EQ(0, device_list()->GetIndexOf(previously_connected_sub_header)); + EXPECT_EQ(previously_connected_device_count + 1, + device_list()->children().size()); + return; + } + + const TriView* no_device_connected_sub_header = + FindNoDeviceConnectedSubHeader(); + EXPECT_TRUE(no_device_connected_sub_header); + EXPECT_EQ(0, device_list()->GetIndexOf(no_device_connected_sub_header)); + EXPECT_EQ(1u, device_list()->children().size()); + } + + void CheckNotifyDeviceListChangedCount(size_t call_count) { + EXPECT_EQ(call_count, fake_bluetooth_detailed_view() + ->notify_device_list_changed_call_count()); + } + + views::View* device_list() { + return static_cast<tray::BluetoothDetailedView*>( + fake_bluetooth_detailed_view_.get()) + ->device_list(); } BluetoothDeviceListController* bluetooth_device_list_controller() { return bluetooth_device_list_controller_impl_.get(); } + tray::FakeBluetoothDetailedView* fake_bluetooth_detailed_view() { + return fake_bluetooth_detailed_view_.get(); + } + + protected: + const std::vector<PairedBluetoothDevicePropertiesPtr> empty_list_; + private: + const TriView* FindSubHeaderWithText(const std::u16string text) { + for (const auto* view : device_list()->children()) { + if (std::strcmp("TriView", view->GetClassName())) + continue; + const TriView* sub_header = static_cast<const TriView*>(view); + if (GetSubHeaderText(sub_header) == text) + return sub_header; + } + return nullptr; + } + base::test::ScopedFeatureList feature_list_; std::unique_ptr<tray::FakeBluetoothDetailedView> fake_bluetooth_detailed_view_; @@ -46,8 +192,135 @@ bluetooth_device_list_controller_impl_; }; -TEST_F(BluetoothDeviceListControllerTest, CanConstruct) { - EXPECT_TRUE(true); +TEST_F(BluetoothDeviceListControllerTest, + HasCorrectSubHeaderWithNoPairedDevices) { + CheckNotifyDeviceListChangedCount(/*call_count=*/0u); + + bluetooth_device_list_controller()->UpdateBluetoothEnabledState(true); + bluetooth_device_list_controller()->UpdateDeviceList( + /*connected=*/empty_list_, + /*previously_connected=*/empty_list_); + CheckNotifyDeviceListChangedCount(/*call_count=*/1u); + + EXPECT_EQ(1u, device_list()->children().size()); + + const TriView* no_device_connected_sub_header = + FindNoDeviceConnectedSubHeader(); + EXPECT_TRUE(no_device_connected_sub_header); +} + +TEST_F(BluetoothDeviceListControllerTest, + HasCorrectDeviceListOrderWithPairedDevices) { + CheckNotifyDeviceListChangedCount(/*call_count=*/0u); + + bluetooth_device_list_controller()->UpdateBluetoothEnabledState(true); + + std::vector<PairedBluetoothDevicePropertiesPtr> connected_list; + connected_list.push_back(BuildDeviceProperties(kDeviceId1)); + + bluetooth_device_list_controller()->UpdateDeviceList( + /*connected=*/connected_list, + /*previously_connected=*/empty_list_); + CheckNotifyDeviceListChangedCount(/*call_count=*/1u); + + const TriView* connected_devices_sub_header = FindConnectedSubHeader(); + + EXPECT_EQ(2u, device_list()->children().size()); + EXPECT_STREQ(kDeviceId1, GetDeviceId(GetFirstDeviceView())); + EXPECT_TRUE(connected_devices_sub_header); + + CheckDeviceListOrdering( + /*connected_device_count=*/connected_list.size(), + /*previously_connected_device_count=*/empty_list_.size()); + + std::vector<PairedBluetoothDevicePropertiesPtr> previously_connected_list; + previously_connected_list.push_back(BuildDeviceProperties(kDeviceId2)); + + bluetooth_device_list_controller()->UpdateDeviceList( + /*connected=*/empty_list_, + /*previously_connected=*/previously_connected_list); + CheckNotifyDeviceListChangedCount(/*call_count=*/2u); + + const TriView* previously_connected_devices_sub_header = + FindPreviouslyConnectedSubHeader(); + + EXPECT_EQ(2u, device_list()->children().size()); + EXPECT_STREQ(kDeviceId2, GetDeviceId(GetFirstDeviceView())); + EXPECT_TRUE(previously_connected_devices_sub_header); + + CheckDeviceListOrdering( + /*connected_device_count=*/0, + /*previously_connected_device_count=*/previously_connected_list.size()); + + // "Update" the device list multiple times to be sure that no children are + // duplicated and every child is re-ordered correctly. + for (int i = 0; i < 2; i++) { + bluetooth_device_list_controller()->UpdateDeviceList( + /*connected=*/connected_list, + /*previously_connected=*/previously_connected_list); + } + + CheckNotifyDeviceListChangedCount(/*call_count=*/4u); + + EXPECT_EQ(5u, device_list()->children().size()); + + CheckDeviceListOrdering( + /*connected_device_count=*/connected_list.size(), + /*previously_connected_device_count=*/previously_connected_list.size()); +} + +TEST_F(BluetoothDeviceListControllerTest, ExistingDeviceViewsAreUpdated) { + CheckNotifyDeviceListChangedCount(/*call_count=*/0u); + + bluetooth_device_list_controller()->UpdateBluetoothEnabledState(true); + + std::vector<PairedBluetoothDevicePropertiesPtr> connected_list; + connected_list.push_back(BuildDeviceProperties(kDeviceId1)); + + bluetooth_device_list_controller()->UpdateDeviceList( + /*connected=*/connected_list, + /*previously_connected=*/empty_list_); + CheckNotifyDeviceListChangedCount(/*call_count=*/1u); + + EXPECT_EQ(2u, device_list()->children().size()); + + const BluetoothDeviceListItemView* first_item = GetFirstDeviceView(); + + EXPECT_FALSE(first_item->device_properties()->nickname.has_value()); + + connected_list.at(0)->nickname = kDeviceNickname; + + bluetooth_device_list_controller()->UpdateDeviceList( + /*connected=*/connected_list, + /*previously_connected=*/empty_list_); + CheckNotifyDeviceListChangedCount(/*call_count=*/2u); + + EXPECT_EQ(2u, device_list()->children().size()); + EXPECT_EQ(1, device_list()->GetIndexOf(first_item)); + EXPECT_TRUE(first_item->device_properties()->nickname.has_value()); + EXPECT_STREQ(kDeviceNickname, + first_item->device_properties()->nickname.value().c_str()); +} + +TEST_F(BluetoothDeviceListControllerTest, + DeviceListIsClearedWhenBluetoothBecomesDisabled) { + CheckNotifyDeviceListChangedCount(/*call_count=*/0u); + + bluetooth_device_list_controller()->UpdateBluetoothEnabledState(true); + + std::vector<PairedBluetoothDevicePropertiesPtr> connected_list; + connected_list.push_back(BuildDeviceProperties(kDeviceId1)); + + bluetooth_device_list_controller()->UpdateDeviceList( + /*connected=*/connected_list, + /*previously_connected=*/empty_list_); + CheckNotifyDeviceListChangedCount(/*call_count=*/1u); + + EXPECT_EQ(2u, device_list()->children().size()); + + bluetooth_device_list_controller()->UpdateBluetoothEnabledState(false); + + EXPECT_EQ(0u, device_list()->children().size()); } } // namespace ash
diff --git a/ash/system/bluetooth/bluetooth_device_list_item_view.cc b/ash/system/bluetooth/bluetooth_device_list_item_view.cc index b4abc9bd..f950a9d 100644 --- a/ash/system/bluetooth/bluetooth_device_list_item_view.cc +++ b/ash/system/bluetooth/bluetooth_device_list_item_view.cc
@@ -26,4 +26,8 @@ device_properties_ = mojo::Clone(device_properties); } +const char* BluetoothDeviceListItemView::GetClassName() const { + return "BluetoothDeviceListItemView"; +} + } // namespace ash
diff --git a/ash/system/bluetooth/bluetooth_device_list_item_view.h b/ash/system/bluetooth/bluetooth_device_list_item_view.h index e70b57c..f08d7739 100644 --- a/ash/system/bluetooth/bluetooth_device_list_item_view.h +++ b/ash/system/bluetooth/bluetooth_device_list_item_view.h
@@ -34,6 +34,9 @@ } private: + // views::View: + const char* GetClassName() const override; + chromeos::bluetooth_config::mojom::PairedBluetoothDevicePropertiesPtr device_properties_; };
diff --git a/ash/system/bluetooth/fake_bluetooth_detailed_view.cc b/ash/system/bluetooth/fake_bluetooth_detailed_view.cc index 9f978157..059f2a3c 100644 --- a/ash/system/bluetooth/fake_bluetooth_detailed_view.cc +++ b/ash/system/bluetooth/fake_bluetooth_detailed_view.cc
@@ -6,13 +6,15 @@ #include "ash/system/bluetooth/bluetooth_device_list_item_view.h" #include "ash/system/tray/tri_view.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/views/controls/label.h" namespace ash { namespace tray { FakeBluetoothDetailedView::FakeBluetoothDetailedView(Delegate* delegate) : BluetoothDetailedView(delegate), - device_list_(std::make_unique<views::ScrollView>()) {} + device_list_(std::make_unique<views::View>()) {} FakeBluetoothDetailedView::~FakeBluetoothDetailedView() = default; @@ -30,9 +32,13 @@ } ash::TriView* FakeBluetoothDetailedView::AddDeviceListSubHeader( - const gfx::VectorIcon&, - int) { - return device_list_->AddChildView(new ash::TriView()); + const gfx::VectorIcon& /*icon*/, + int text_id) { + std::unique_ptr<TriView> sub_header = std::make_unique<TriView>(); + sub_header->AddView(TriView::Container::CENTER, + new views::Label(l10n_util::GetStringUTF16(text_id))); + device_list_->AddChildView(sub_header.get()); + return sub_header.release(); } void FakeBluetoothDetailedView::NotifyDeviceListChanged() { @@ -40,7 +46,7 @@ } views::View* FakeBluetoothDetailedView::device_list() { - return device_list_->contents(); + return device_list_.get(); } } // namespace tray
diff --git a/ash/system/bluetooth/fake_bluetooth_detailed_view.h b/ash/system/bluetooth/fake_bluetooth_detailed_view.h index 197bf4d..59745f4 100644 --- a/ash/system/bluetooth/fake_bluetooth_detailed_view.h +++ b/ash/system/bluetooth/fake_bluetooth_detailed_view.h
@@ -11,7 +11,6 @@ #include "ash/system/bluetooth/bluetooth_detailed_view.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "ui/gfx/vector_icon_types.h" -#include "ui/views/controls/scroll_view.h" namespace views { class View; @@ -47,13 +46,13 @@ void UpdateBluetoothEnabledState(bool enabled) override; BluetoothDeviceListItemView* AddDeviceListItem() override; ash::TriView* AddDeviceListSubHeader(const gfx::VectorIcon& /*icon*/, - int /*text_id*/) override; + int text_id) override; void NotifyDeviceListChanged() override; views::View* device_list() override; size_t notify_device_list_changed_call_count_ = 0; absl::optional<bool> last_bluetooth_enabled_state_; - std::unique_ptr<views::ScrollView> device_list_; + std::unique_ptr<views::View> device_list_; }; } // namespace tray
diff --git a/ash/system/message_center/notifier_settings_view.cc b/ash/system/message_center/notifier_settings_view.cc index 76ad2bd..0cb811f 100644 --- a/ash/system/message_center/notifier_settings_view.cc +++ b/ash/system/message_center/notifier_settings_view.cc
@@ -35,7 +35,6 @@ #include "ui/accessibility/ax_enums.mojom.h" #include "ui/accessibility/ax_node_data.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/base/ui_base_features.h" #include "ui/compositor/layer.h" #include "ui/compositor/paint_recorder.h" #include "ui/events/event_utils.h" @@ -554,42 +553,40 @@ const SkColor separator_color = AshColorProvider::Get()->GetContentLayerColor( ContentLayerType::kSeparatorColor); - if (::features::IsNotificationIndicatorEnabled()) { - // Row for the app badging toggle button. - auto app_badging_icon = std::make_unique<AdaptiveBadgingIcon>(); - app_badging_icon->SetImage(gfx::CreateVectorIcon( - kSystemTrayAppBadgingIcon, kMenuIconSize, icon_color)); - auto app_badging_label = - std::make_unique<views::Label>(l10n_util::GetStringUTF16( - IDS_ASH_MESSAGE_CENTER_APP_BADGING_BUTTON_TOOLTIP)); - auto app_badging_toggle = - base::WrapUnique<views::ToggleButton>(new TrayToggleButton( - base::BindRepeating(&NotifierSettingsView::AppBadgingTogglePressed, - base::Unretained(this)), - IDS_ASH_MESSAGE_CENTER_APP_BADGING_BUTTON_TOOLTIP)); - app_badging_toggle_ = app_badging_toggle.get(); + // Row for the app badging toggle button. + auto app_badging_icon = std::make_unique<AdaptiveBadgingIcon>(); + app_badging_icon->SetImage(gfx::CreateVectorIcon(kSystemTrayAppBadgingIcon, + kMenuIconSize, icon_color)); + auto app_badging_label = + std::make_unique<views::Label>(l10n_util::GetStringUTF16( + IDS_ASH_MESSAGE_CENTER_APP_BADGING_BUTTON_TOOLTIP)); + auto app_badging_toggle = + base::WrapUnique<views::ToggleButton>(new TrayToggleButton( + base::BindRepeating(&NotifierSettingsView::AppBadgingTogglePressed, + base::Unretained(this)), + IDS_ASH_MESSAGE_CENTER_APP_BADGING_BUTTON_TOOLTIP)); + app_badging_toggle_ = app_badging_toggle.get(); - SessionControllerImpl* session_controller = - Shell::Get()->session_controller(); - PrefService* prefs = session_controller->GetLastActiveUserPrefService(); - if (prefs) { - app_badging_toggle_->SetIsOn( - prefs->GetBoolean(prefs::kAppNotificationBadgingEnabled)); - } - - auto app_badging_view = CreateToggleButtonRow( - std::move(app_badging_icon), std::move(app_badging_label), - std::move(app_badging_toggle)); - app_badging_view->SetBorder( - views::CreateSolidSidedBorder(0, 0, 0, 1, kTopBorderColor)); - header_view->AddChildView(std::move(app_badging_view)); - - // Separator between toggle button rows. - auto separator = std::make_unique<AdaptiveSeparator>(); - separator->SetColor(separator_color); - header_view->AddChildView(std::move(separator)); + SessionControllerImpl* session_controller = + Shell::Get()->session_controller(); + PrefService* prefs = session_controller->GetLastActiveUserPrefService(); + if (prefs) { + app_badging_toggle_->SetIsOn( + prefs->GetBoolean(prefs::kAppNotificationBadgingEnabled)); } + auto app_badging_view = CreateToggleButtonRow(std::move(app_badging_icon), + std::move(app_badging_label), + std::move(app_badging_toggle)); + app_badging_view->SetBorder( + views::CreateSolidSidedBorder(0, 0, 0, 1, kTopBorderColor)); + header_view->AddChildView(std::move(app_badging_view)); + + // Separator between toggle button rows. + auto separator = std::make_unique<AdaptiveSeparator>(); + separator->SetColor(separator_color); + header_view->AddChildView(std::move(separator)); + // Row for the quiet mode toggle button. auto quiet_mode_icon = std::make_unique<views::ImageView>(); quiet_mode_icon_ = quiet_mode_icon.get();
diff --git a/ash/system/message_center/stacked_notification_bar.cc b/ash/system/message_center/stacked_notification_bar.cc index 659f0562..3f17e2c1 100644 --- a/ash/system/message_center/stacked_notification_bar.cc +++ b/ash/system/message_center/stacked_notification_bar.cc
@@ -120,9 +120,8 @@ : public views::ImageView, public ui::LayerAnimationObserver { public: - StackedNotificationBarIcon(StackedNotificationBar* notification_bar, - const std::string& id) - : views::ImageView(), notification_bar_(notification_bar), id_(id) { + explicit StackedNotificationBarIcon(const std::string& id) + : views::ImageView(), id_(id) { SetPaintToLayer(); layer()->SetFillsBoundsOpaquely(false); } @@ -140,6 +139,11 @@ auto* notification = message_center::MessageCenter::Get()->FindVisibleNotificationById(id_); + // The notification icon could be waiting to be cleaned up after the + // notification removal animation completes. + if (!notification) + return; + SkColor accent_color = GetNativeTheme()->GetSystemColor( ui::NativeTheme::kColorId_NotificationDefaultAccentColor); gfx::Image masked_small_icon = notification->GenerateMaskedSmallIcon( @@ -198,7 +202,13 @@ layer()->GetAnimator()->StartAnimation(sequence.release()); } - void AnimateOut() { + using AnimationCompleteCallback = base::OnceCallback<void(views::View*)>; + + void AnimateOut(AnimationCompleteCallback animation_complete_callback) { + DCHECK(animation_complete_callback_.is_null()); + + animation_complete_callback_ = std::move(animation_complete_callback); + layer()->GetAnimator()->StopAnimating(); std::unique_ptr<ui::InterpolatedTransform> scale = @@ -235,7 +245,7 @@ // ui::LayerAnimationObserver: void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override { set_animating_out(false); - notification_bar_->OnIconAnimatedOut(this); + std::move(animation_complete_callback_).Run(this); // Note |this| is deleted after this point. } @@ -249,57 +259,58 @@ void set_animating_out(bool animating_out) { animating_out_ = animating_out; } private: - StackedNotificationBar* notification_bar_; std::string id_; bool animating_out_ = false; + + // Used to notify the parent of animation completion. This is deleted after + // the callback is run. + // Registered in `AnimateOut()`. + AnimationCompleteCallback animation_complete_callback_; }; StackedNotificationBar::StackedNotificationBar( UnifiedMessageCenterView* message_center_view) : message_center_view_(message_center_view), - count_label_(new views::Label), - clear_all_button_(new StackingBarLabelButton( + notification_icons_container_( + AddChildView(std::make_unique<views::View>())), + count_label_(AddChildView(std::make_unique<views::Label>())), + clear_all_button_(AddChildView(std::make_unique<StackingBarLabelButton>( base::BindRepeating(&UnifiedMessageCenterView::ClearAllNotifications, base::Unretained(message_center_view_)), l10n_util::GetStringUTF16( IDS_ASH_MESSAGE_CENTER_CLEAR_ALL_BUTTON_LABEL), - message_center_view)), - expand_all_button_(new StackingBarLabelButton( + message_center_view))), + expand_all_button_(AddChildView(std::make_unique<StackingBarLabelButton>( base::BindRepeating(&UnifiedMessageCenterView::ExpandMessageCenter, base::Unretained(message_center_view_)), l10n_util::GetStringUTF16( IDS_ASH_MESSAGE_CENTER_EXPAND_ALL_NOTIFICATIONS_BUTTON_LABEL), - message_center_view)) { + message_center_view))) { SetVisible(false); auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::Orientation::kHorizontal)); layout->set_cross_axis_alignment( views::BoxLayout::CrossAxisAlignment::kStretch); - notification_icons_container_ = new views::View(); notification_icons_container_->SetLayoutManager( std::make_unique<views::BoxLayout>( views::BoxLayout::Orientation::kHorizontal, kStackedNotificationIconsContainerPadding, kStackedNotificationBarIconSpacing)); - AddChildView(notification_icons_container_); + message_center::MessageCenter::Get()->AddObserver(this); count_label_->SetEnabledColor(message_center_style::kCountLabelColor); count_label_->SetFontList(views::Label::GetDefaultFontList().Derive( 1, gfx::Font::NORMAL, gfx::Font::Weight::MEDIUM)); - AddChildView(count_label_); - views::View* spacer = new views::View; - AddChildView(spacer); + views::View* spacer = AddChildView(std::make_unique<views::View>()); layout->SetFlexForView(spacer, 1); clear_all_button_->SetTooltipText(l10n_util::GetStringUTF16( IDS_ASH_MESSAGE_CENTER_CLEAR_ALL_BUTTON_TOOLTIP)); - AddChildView(clear_all_button_); expand_all_button_->SetVisible(false); - AddChildView(expand_all_button_); if (!features::IsNotificationsRefreshEnabled()) SetPaintToLayer(); @@ -360,32 +371,42 @@ void StackedNotificationBar::AddNotificationIcon( message_center::Notification* notification, bool at_front) { - views::ImageView* icon_view = - new StackedNotificationBarIcon(this, notification->id()); if (at_front) - notification_icons_container_->AddChildViewAt(icon_view, 0); + notification_icons_container_->AddChildViewAt( + std::make_unique<StackedNotificationBarIcon>(notification->id()), 0); else - notification_icons_container_->AddChildView(icon_view); + notification_icons_container_->AddChildView( + std::make_unique<StackedNotificationBarIcon>(notification->id())); } -void StackedNotificationBar::OnIconAnimatedOut(views::View* icon) { +void StackedNotificationBar::OnIconAnimatedOut( + message_center::Notification* notification, + views::View* icon) { delete icon; + + // This is only called when icons animate out, so never add icons to the + // front. + if (notification) + AddNotificationIcon(notification, /*at_front=*/false); + Layout(); } StackedNotificationBar::StackedNotificationBarIcon* -StackedNotificationBar::GetFrontIcon() { +StackedNotificationBar::GetFrontIcon(bool animating_out) { const auto i = std::find_if( notification_icons_container_->children().cbegin(), - notification_icons_container_->children().cend(), [](const auto* v) { - return !static_cast<const StackedNotificationBarIcon*>(v) - ->is_animating_out(); + notification_icons_container_->children().cend(), [&](const auto* v) { + return animating_out == + static_cast<const StackedNotificationBarIcon*>(v) + ->is_animating_out(); }); return (i == notification_icons_container_->children().cend() ? nullptr : static_cast<StackedNotificationBarIcon*>(*i)); } + const StackedNotificationBar::StackedNotificationBarIcon* StackedNotificationBar::GetIconFromId(const std::string& id) const { for (auto* v : notification_icons_container_->children()) { @@ -399,35 +420,57 @@ void StackedNotificationBar::ShiftIconsLeft( std::vector<message_center::Notification*> stacked_notifications) { + auto* front_animating_out_icon = GetFrontIcon(/*animating_out=*/true); + bool is_already_animating_a_left_shift = front_animating_out_icon != nullptr; + // If we need to animate a second icon, the scroll is faster than the icon can + // animate out (this is possible with a very fast scroll), so immediately + // finish that animation before starting a new one. + if (is_already_animating_a_left_shift) { + front_animating_out_icon->layer()->GetAnimator()->StopAnimating(); + // `front_animating_out_icon` is now deleted, and StackedNotificationBar has + // been reloaded with another icon in the back. + } + int stacked_notification_count = stacked_notifications.size(); int removed_icons_count = std::min(stacked_notification_count_ - stacked_notification_count, kStackedNotificationBarMaxIcons); + stacked_notification_count_ = stacked_notification_count; + // Remove required number of icons from the front. // Only animate if we're removing one icon. - if (removed_icons_count == 1) { - StackedNotificationBarIcon* icon = GetFrontIcon(); - if (icon) { - icon->AnimateOut(); - } - } else { - for (int i = 0; i < removed_icons_count; i++) { - StackedNotificationBarIcon* icon = GetFrontIcon(); - if (icon) { - delete icon; - } - } - } - // Add icons to the back if there was a backfill. int backfill_start = kStackedNotificationBarMaxIcons - removed_icons_count; int backfill_end = std::min(kStackedNotificationBarMaxIcons, stacked_notification_count); - for (int i = backfill_start; i < backfill_end; i++) { - AddNotificationIcon(stacked_notifications[i], false /*at_front*/); + const bool will_animate = removed_icons_count == 1; + if (will_animate) { + auto* icon = GetFrontIcon(/*animating_out=*/false); + if (icon) { + // If there are notifications to backfill, do not add the + // icon until the animation completes, this avoids a jumping overflow + // label/icons and having more than 3 icons in the stack. + message_center::Notification* notification_icon_to_show_on_completion = + backfill_start < backfill_end ? stacked_notifications[backfill_start] + : nullptr; + icon->AnimateOut( + base::BindOnce(&StackedNotificationBar::OnIconAnimatedOut, + weak_ptr_factory_.GetWeakPtr(), + notification_icon_to_show_on_completion)); + } + return; } - stacked_notification_count_ = stacked_notification_count; + // No animation. + for (int i = 0; i < removed_icons_count; i++) { + auto* icon = GetFrontIcon(/*animating_out=*/false); + if (icon) { + delete icon; + } + } + + for (int i = backfill_start; i < backfill_end; i++) + AddNotificationIcon(stacked_notifications[i], false /*at_front*/); } void StackedNotificationBar::ShiftIconsRight( @@ -446,9 +489,9 @@ ++stacked_notification_count_; } // Animate in the first stacked notification icon. - StackedNotificationBarIcon* icon = GetFrontIcon(); + auto* icon = GetFrontIcon(/*animating_out=*/false); if (icon) - GetFrontIcon()->AnimateIn(); + icon->AnimateIn(); } void StackedNotificationBar::UpdateStackedNotifications(
diff --git a/ash/system/message_center/stacked_notification_bar.h b/ash/system/message_center/stacked_notification_bar.h index fa35077b..def490a1 100644 --- a/ash/system/message_center/stacked_notification_bar.h +++ b/ash/system/message_center/stacked_notification_bar.h
@@ -9,6 +9,7 @@ #include "ash/system/message_center/message_center_scroll_bar.h" #include "ash/system/message_center/unified_message_center_view.h" #include "ash/system/message_center/unified_message_list_view.h" +#include "base/memory/weak_ptr.h" #include "ui/compositor/layer_animation_observer.h" #include "ui/gfx/animation/animation_delegate.h" #include "ui/message_center/message_center_observer.h" @@ -25,8 +26,8 @@ namespace ash { // The header shown above the notification list displaying the number of hidden -// notifications. There are currently two UI implementations toggled by the -// NotificationStackedBarRedesign feature flag. +// notifications. Has a dynamic list of icons which hide/show as notifications +// are scrolled. class StackedNotificationBar : public views::View, public message_center::MessageCenterObserver { public: @@ -54,9 +55,6 @@ // Set notification bar state to expanded. void SetExpanded(); - // Clean up icon view after it's removal animation is complete. - void OnIconAnimatedOut(views::View* icon); - // views::View: void OnPaint(gfx::Canvas* canvas) override; const char* GetClassName() const override; @@ -70,8 +68,14 @@ class StackedNotificationBarIcon; friend class UnifiedMessageCenterViewTest; - // Get the first icon which is not animating out. - StackedNotificationBarIcon* GetFrontIcon(); + // Clean up icon view after it's removal animation is complete, adds an icon + // for `notification` if needed. Called from a callback registered in + // `ShiftIconsLeft()`. + void OnIconAnimatedOut(message_center::Notification* notification, + views::View* icon); + + // Get the first icon which is `animating_out`. + StackedNotificationBarIcon* GetFrontIcon(bool animating_out); // Search for a icon view in the stacked notification bar based on a provided // notification id. @@ -109,6 +113,8 @@ views::Label* const count_label_; views::Button* const clear_all_button_; views::Button* const expand_all_button_; + + base::WeakPtrFactory<StackedNotificationBar> weak_ptr_factory_{this}; }; } // namespace ash
diff --git a/ash/system/message_center/unified_message_center_view_unittest.cc b/ash/system/message_center/unified_message_center_view_unittest.cc index 791d4d4f..2421a0a 100644 --- a/ash/system/message_center/unified_message_center_view_unittest.cc +++ b/ash/system/message_center/unified_message_center_view_unittest.cc
@@ -20,6 +20,8 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "components/prefs/pref_service.h" +#include "ui/compositor/layer.h" +#include "ui/compositor/scoped_animation_duration_scale_mode.h" #include "ui/message_center/message_center.h" #include "ui/message_center/views/message_view.h" #include "ui/views/controls/scroll_view.h" @@ -180,6 +182,11 @@ return message_center_view()->notification_bar_; } + views::View* GetNotificationBarIconsContainer() { + return message_center_view() + ->notification_bar_->notification_icons_container_; + } + views::View* GetNotificationBarLabel() { return message_center_view()->notification_bar_->count_label_; } @@ -481,12 +488,12 @@ GetScroller()->GetVisibleRect().bottom()); } -TEST_F(UnifiedMessageCenterViewTest, StackingCounterLayout) { +// Tests basic layout of the StackingNotificationBar. +TEST_F(UnifiedMessageCenterViewTest, StackingCounterLabelLayout) { AddManyNotifications(); // MessageCenterView is maxed out. CreateMessageCenterView(); - EXPECT_TRUE(message_center_view()->GetVisible()); EXPECT_GT(GetMessageListView()->bounds().height(), message_center_view()->bounds().height()); @@ -497,32 +504,26 @@ GetScroller()->bounds().y()); EXPECT_TRUE(GetNotificationBarLabel()->GetVisible()); EXPECT_TRUE(GetNotificationBarClearAllButton()->GetVisible()); +} - // Scroll to the top, making the counter label invisible. +// Tests that the NotificationBarLabel is invisible when scrolled to the top. +TEST_F(UnifiedMessageCenterViewTest, StackingCounterLabelInvisible) { + AddManyNotifications(); + CreateMessageCenterView(); + + // Scroll to the top, the counter label should be invisible. GetScroller()->ScrollToPosition(GetScrollBar(), 0); message_center_view()->OnMessageCenterScrolled(); - EXPECT_TRUE(GetNotificationBar()->GetVisible()); + EXPECT_FALSE(GetNotificationBarLabel()->GetVisible()); + // ClearAll label should always be visible. EXPECT_TRUE(GetNotificationBarClearAllButton()->GetVisible()); } -TEST_F(UnifiedMessageCenterViewTest, StackingCounterMessageListScrolled) { +// Tests that the NotificationBarLabel is visible when scrolling down. +TEST_F(UnifiedMessageCenterViewTest, StackingCounterLabelVisible) { AddManyNotifications(); CreateMessageCenterView(); - EXPECT_TRUE(message_center_view()->GetVisible()); - EXPECT_TRUE(GetNotificationBarLabel()->GetVisible()); - EXPECT_TRUE(GetNotificationBarClearAllButton()->GetVisible()); - - // MessageCenterView is maxed out. - EXPECT_GT(GetMessageListView()->bounds().height(), - message_center_view()->bounds().height()); - - // Scroll to the top, making the counter label invisible. - GetScroller()->ScrollToPosition(GetScrollBar(), 0); - message_center_view()->OnMessageCenterScrolled(); - EXPECT_TRUE(GetNotificationBar()->GetVisible()); - EXPECT_FALSE(GetNotificationBarLabel()->GetVisible()); - EXPECT_TRUE(GetNotificationBarClearAllButton()->GetVisible()); // Scrolling past 5 notifications should make the counter label visible. const int scroll_amount = (GetMessageViewVisibleBounds(0).height() * 5) + 1; @@ -530,16 +531,72 @@ message_center_view()->OnMessageCenterScrolled(); EXPECT_TRUE(GetNotificationBarLabel()->GetVisible()); + // ClearAll label should always be visible. + EXPECT_TRUE(GetNotificationBarClearAllButton()->GetVisible()); +} + +// Tests that the +n notifications label hides after being shown. +TEST_F(UnifiedMessageCenterViewTest, StackingCounterLabelHidesAfterShown) { + AddManyNotifications(); + CreateMessageCenterView(); + + // Scroll to the top, making the counter label invisible. + GetScroller()->ScrollToPosition(GetScrollBar(), 0); + message_center_view()->OnMessageCenterScrolled(); + + // Scrolling past 5 notifications should make the counter label visible. + const int scroll_amount = (GetMessageViewVisibleBounds(0).height() * 5) + 1; + GetScroller()->ScrollToPosition(GetScrollBar(), scroll_amount); + message_center_view()->OnMessageCenterScrolled(); + + ASSERT_TRUE(GetNotificationBarLabel()->GetVisible()); // Scrolling back to the top should make the // counter label invisible again. GetScroller()->ScrollToPosition(GetScrollBar(), 0); message_center_view()->OnMessageCenterScrolled(); - EXPECT_TRUE(GetNotificationBar()->GetVisible()); + EXPECT_FALSE(GetNotificationBarLabel()->GetVisible()); + // ClearAll label should always be visible. EXPECT_TRUE(GetNotificationBarClearAllButton()->GetVisible()); } +// Tests that there are never more than 3 stacked icons in the +// StackedNotificationBar. Also verifies that only one animation happens at a +// time (this prevents the user from over-scrolling and showing multiple +// animations when they scroll very quickly). Before, users could scroll fast +// and have a large amount of icons, instead of keeping it to 3. +TEST_F(UnifiedMessageCenterViewTest, StackingIconsNeverMoreThanThree) { + for (int i = 0; i < 20; ++i) + AddNotification(false); + CreateMessageCenterView(); + + // Force animations to happen, so we can see if multiple animations trigger. + ui::ScopedAnimationDurationScaleMode scoped_duration_modifier( + ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION); + // Scroll past 20 notifications, so we can scroll back up quickly. + for (int i = 20; i >= 0; --i) { + const int scroll_amount = (GetMessageViewVisibleBounds(0).height() * i) + 1; + GetScroller()->ScrollToPosition(GetScrollBar(), scroll_amount); + message_center_view()->OnMessageCenterScrolled(); + + auto icons_container_children = + GetNotificationBarIconsContainer()->children(); + int animating_count = 0; + for (auto* child : icons_container_children) { + // Verify that no more than one icon is animating at any one time. + if (child->layer()->GetAnimator()->is_animating()) + animating_count++; + } + EXPECT_GE(1, animating_count); + // Verify that no more than 3 icons are added to the bar at any one time, + // regardless of how fast the user scrolls. This test scrolls faster than + // the icons can animate away, and animating icons should be removed prior + // to starting a new animation. + EXPECT_GE(3u, icons_container_children.size()); + } +} + // Flaky: crbug.com/1163575 TEST_F(UnifiedMessageCenterViewTest, DISABLED_StackingCounterNotificationRemoval) {
diff --git a/ash/webui/diagnostics_ui/resources/routine_group.js b/ash/webui/diagnostics_ui/resources/routine_group.js index 01e6f17..89016620 100644 --- a/ash/webui/diagnostics_ui/resources/routine_group.js +++ b/ash/webui/diagnostics_ui/resources/routine_group.js
@@ -78,16 +78,19 @@ // Prevent 1st failed test from being overwritten. this.failedTest = this.failedTest || status.routine; - const blocking = !this.nonBlockingRoutines_.has(status.routine); - this.inWarningState = this.inWarningState || !blocking; - this.progress = isLastRoutine ? ExecutionProgress.kCompleted : - ExecutionProgress.kWarning; - return; + const isBlocking = !this.nonBlockingRoutines_.has(status.routine); + this.inWarningState = this.inWarningState || !isBlocking; + + // We've encountered a blocking failure. + if (this.failedTest && isBlocking) { + this.progress = ExecutionProgress.kCompleted; + return; + } } - // Set status to "completed" only when all routines in this group - // are finished running. Otherwise, check if we're in the warning - // state before setting the progress to running. + // Set status to "completed" only when all routines in this group are + // finished running. Otherwise, check if we're in the warning state + // before setting the progress to running. this.progress = isLastRoutine ? ExecutionProgress.kCompleted : this.inWarningState ? ExecutionProgress.kWarning :
diff --git a/ash/wm/overview/desks_templates/desks_templates_unittest.cc b/ash/wm/overview/desks_templates/desks_templates_unittest.cc new file mode 100644 index 0000000..938c2bd4 --- /dev/null +++ b/ash/wm/overview/desks_templates/desks_templates_unittest.cc
@@ -0,0 +1,117 @@ +// Copyright 2021 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 <string> + +#include "ash/constants/ash_features.h" +#include "ash/public/cpp/desk_template.h" +#include "ash/shell.h" +#include "ash/wm/desks/desks_bar_view.h" +#include "ash/wm/overview/overview_grid.h" +#include "ash/wm/overview/overview_session.h" +#include "ash/wm/overview/overview_test_base.h" +#include "ash/wm/overview/overview_test_util.h" +#include "base/files/scoped_temp_dir.h" +#include "base/guid.h" +#include "base/strings/utf_string_conversions.h" +#include "base/test/bind.h" +#include "base/test/scoped_feature_list.h" +#include "base/time/time.h" +#include "components/desks_storage/core/local_desk_data_manager.h" +#include "ui/aura/window.h" + +namespace ash { + +class DesksTemplatesTest : public OverviewTestBase { + public: + DesksTemplatesTest() = default; + DesksTemplatesTest(const DesksTemplatesTest&) = delete; + DesksTemplatesTest& operator=(const DesksTemplatesTest&) = delete; + ~DesksTemplatesTest() override = default; + + desks_storage::LocalDeskDataManager* desk_model() { + return desk_model_.get(); + } + + // Adds an entry to the desks model directly without capturing a desk. Allows + // for testing the names and times of the UI directly. + void AddEntry(const base::GUID& uuid, + const std::string& name, + base::Time created_time) { + auto desk_template = std::make_unique<DeskTemplate>( + uuid.AsLowercaseString(), name, created_time); + desk_template->set_desk_restore_data( + std::make_unique<app_restore::RestoreData>()); + + base::RunLoop loop; + desk_model()->AddOrUpdateEntry( + std::move(desk_template), + base::BindLambdaForTesting( + [&](desks_storage::DeskModel::AddOrUpdateEntryStatus status) { + EXPECT_EQ(desks_storage::DeskModel::AddOrUpdateEntryStatus::kOk, + status); + loop.Quit(); + })); + loop.Run(); + } + + // OverviewTestBase: + void SetUp() override { + scoped_feature_list_.InitAndEnableFeature(features::kDesksTemplates); + + EXPECT_TRUE(temp_dir_.CreateUniqueTempDir()); + desk_model_ = std::make_unique<desks_storage::LocalDeskDataManager>( + temp_dir_.GetPath()); + + OverviewTestBase::SetUp(); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; + + // The desks model for tests. + std::unique_ptr<desks_storage::LocalDeskDataManager> desk_model_; + + // Temporary directory for the local desk model to store data. + base::ScopedTempDir temp_dir_; +}; + +// Tests that the desks templates button is created when the feature is turned +// on. +// TODO(sammiequon): Update this test once more logic is added to the desks +// templates button. +TEST_F(DesksTemplatesTest, DesksTemplatesButtonVisibility) { + ToggleOverview(); + auto* overview_session = GetOverviewSession(); + ASSERT_TRUE(overview_session); + + const auto* overview_grid = + overview_session->GetGridWithRootWindow(Shell::GetPrimaryRootWindow()); + const auto* desks_bar_view = overview_grid->desks_bar_view(); + EXPECT_TRUE(desks_bar_view->desks_templates_button()); +} + +// Tests the helper `AddEntry()`, which will be used in different tests. +TEST_F(DesksTemplatesTest, AddEntry) { + const base::GUID expected_uuid = base::GUID::GenerateRandomV4(); + const std::string expected_name = "desk name"; + base::Time expected_time = base::Time::Now(); + AddEntry(expected_uuid, expected_name, expected_time); + + base::RunLoop loop; + desk_model()->GetAllEntries(base::BindLambdaForTesting( + [&](desks_storage::DeskModel::GetAllEntriesStatus status, + std::vector<ash::DeskTemplate*> entries) { + EXPECT_EQ(desks_storage::DeskModel::GetAllEntriesStatus::kOk, status); + ASSERT_EQ(1ul, entries.size()); + EXPECT_EQ(expected_uuid, entries[0]->uuid()); + EXPECT_EQ(base::UTF8ToUTF16(expected_name), + entries[0]->template_name()); + EXPECT_EQ(expected_time, entries[0]->created_time()); + loop.Quit(); + })); + loop.Run(); +} + +} // namespace ash
diff --git a/ash/wm/overview/overview_test_base.cc b/ash/wm/overview/overview_test_base.cc index 6260e16..c5905bc3 100644 --- a/ash/wm/overview/overview_test_base.cc +++ b/ash/wm/overview/overview_test_base.cc
@@ -6,7 +6,6 @@ #include "ash/public/cpp/presentation_time_recorder.h" #include "ash/shelf/shelf.h" -#include "ash/shelf/shelf_view_test_api.h" #include "ash/shell.h" #include "ash/wm/overview/overview_controller.h" #include "ash/wm/overview/overview_grid.h"
diff --git a/ash/wm/overview/overview_test_base.h b/ash/wm/overview/overview_test_base.h index 95469c05..7ab463ec 100644 --- a/ash/wm/overview/overview_test_base.h +++ b/ash/wm/overview/overview_test_base.h
@@ -5,9 +5,11 @@ #ifndef ASH_WM_OVERVIEW_OVERVIEW_TEST_BASE_H_ #define ASH_WM_OVERVIEW_OVERVIEW_TEST_BASE_H_ +#include <memory> #include <string> #include <vector> +#include "ash/shelf/shelf_view_test_api.h" #include "ash/test/ash_test_base.h" namespace views { @@ -22,7 +24,6 @@ class OverviewItem; class OverviewSession; class ScopedOverviewTransformWindow; -class ShelfViewTestAPI; class SplitViewController; class WindowPreviewView; @@ -32,6 +33,8 @@ template <typename... TaskEnvironmentTraits> explicit OverviewTestBase(TaskEnvironmentTraits&&... traits) : AshTestBase(std::forward<TaskEnvironmentTraits>(traits)...) {} + OverviewTestBase(const OverviewTestBase&) = delete; + OverviewTestBase& operator=(const OverviewTestBase&) = delete; ~OverviewTestBase() override; // Enters tablet mode. Needed by tests that test dragging and or splitview,
diff --git a/ash/wm/overview/overview_test_util.h b/ash/wm/overview/overview_test_util.h index 89ce2b7..a29e6e0 100644 --- a/ash/wm/overview/overview_test_util.h +++ b/ash/wm/overview/overview_test_util.h
@@ -25,8 +25,8 @@ void ToggleOverview( OverviewEnterExitType type = OverviewEnterExitType::kNormal); -// Waits for the overview enter/exit anmations to finish. No-op and immediately -// return if animations are disabled. +// Waits for the overview enter/exit animations to finish. No-op and immediately +// returns if animations are disabled. void WaitForOverviewEnterAnimation(); void WaitForOverviewExitAnimation();
diff --git a/build/fuchsia/common_args.py b/build/fuchsia/common_args.py index 3098f6a2..a357e1d 100644 --- a/build/fuchsia/common_args.py +++ b/build/fuchsia/common_args.py
@@ -28,7 +28,7 @@ device_args.add_argument('--device', default=None, choices=BUILTIN_TARGET_NAMES + ['custom'], - help='Choose to run on aemu|qemu|device. ' + help='Choose to run on fvdl|aemu|qemu|device. ' 'By default, Fuchsia will run on AEMU on x64 ' 'hosts and QEMU on arm64 hosts. Alternatively, ' 'setting to custom will require specifying the ' @@ -160,6 +160,6 @@ if args.device: device = args.device else: - device = 'aemu' if args.target_cpu == 'x64' else 'qemu' + device = 'fvdl' if args.target_cpu == 'x64' else 'qemu' return _LoadTargetClass(_GetPathToBuiltinTarget(device)).CreateFromArgs(args)
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index 9778107..0a3283f 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -6.20210924.1.1 +6.20210925.0.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index 9778107..35260c5 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -6.20210924.1.1 +6.20210924.3.1
diff --git a/chrome/VERSION b/chrome/VERSION index 7ecd409..5ef82d45 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=96 MINOR=0 -BUILD=4653 +BUILD=4654 PATCH=0
diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_java_resources.gni index 2733d3e4..0222e90 100644 --- a/chrome/android/chrome_java_resources.gni +++ b/chrome/android/chrome_java_resources.gni
@@ -454,6 +454,8 @@ "java/res/drawable/arrow_down.xml", "java/res/drawable/arrow_up.xml", "java/res/drawable/bg_white_dialog.xml", + "java/res/drawable/bookmark_save_flow_background.xml", + "java/res/drawable/bookmark_save_flow_ripple.xml", "java/res/drawable/bookmark_title_bar_shadow.xml", "java/res/drawable/bookmark_widget_list_selector.xml", "java/res/drawable/btn_back.xml", @@ -579,6 +581,7 @@ "java/res/layout/bookmark_folder_select_activity.xml", "java/res/layout/bookmark_item_row.xml", "java/res/layout/bookmark_main.xml", + "java/res/layout/bookmark_save_flow.xml", "java/res/layout/bookmark_section_header.xml", "java/res/layout/bookmark_widget.xml", "java/res/layout/bookmark_widget_icons_only.xml",
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni index 793c97c..535e48b0 100644 --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni
@@ -170,6 +170,10 @@ "java/src/org/chromium/chrome/browser/bookmarks/BookmarkPage.java", "java/src/org/chromium/chrome/browser/bookmarks/BookmarkPromoHeader.java", "java/src/org/chromium/chrome/browser/bookmarks/BookmarkRow.java", + "java/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowCoordinator.java", + "java/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowMediator.java", + "java/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowProperties.java", + "java/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowViewBinder.java", "java/src/org/chromium/chrome/browser/bookmarks/BookmarkTextInputLayout.java", "java/src/org/chromium/chrome/browser/bookmarks/BookmarkUIObserver.java", "java/src/org/chromium/chrome/browser/bookmarks/BookmarkUIState.java",
diff --git a/chrome/android/chrome_test_java_sources.gni b/chrome/android/chrome_test_java_sources.gni index f8687820..964ebcdc 100644 --- a/chrome/android/chrome_test_java_sources.gni +++ b/chrome/android/chrome_test_java_sources.gni
@@ -79,6 +79,7 @@ "javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkPersonalizedPromoRenderTest.java", "javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkPersonalizedSigninPromoDismissTest.java", "javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkPersonalizedSigninPromoTest.java", + "javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowTest.java", "javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java", "javatests/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkTagChipListTest.java", "javatests/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkTest.java",
diff --git a/chrome/android/expectations/lint-baseline.xml b/chrome/android/expectations/lint-baseline.xml index 072cffc5..b20bba2 100644 --- a/chrome/android/expectations/lint-baseline.xml +++ b/chrome/android/expectations/lint-baseline.xml
@@ -91,86 +91,6 @@ <issue id="WrongConstant" - message="Must be one of: BookmarkType.NORMAL, BookmarkType.PARTNER, BookmarkType.READING_LIST, BookmarkType.LAST"> - <location - file="../../chrome/android/java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetCoordinator.java" - line="121"/> - </issue> - - <issue - id="WrongConstant" - message="Must be one of: BookmarkType.NORMAL, BookmarkType.PARTNER, BookmarkType.READING_LIST, BookmarkType.LAST"> - <location - file="../../chrome/android/java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetCoordinator.java" - line="127"/> - </issue> - - <issue - id="WrongConstant" - message="Must be one of: BookmarkType.NORMAL, BookmarkType.PARTNER, BookmarkType.READING_LIST, BookmarkType.LAST"> - <location - file="../../chrome/android/java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetCoordinator.java" - line="127"/> - </issue> - - <issue - id="WrongConstant" - message="Must be one of: BookmarkType.NORMAL, BookmarkType.PARTNER, BookmarkType.READING_LIST, BookmarkType.LAST"> - <location - file="../../chrome/android/java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetCoordinator.java" - line="128"/> - </issue> - - <issue - id="WrongConstant" - message="Must be one of: BookmarkType.NORMAL, BookmarkType.PARTNER, BookmarkType.READING_LIST, BookmarkType.LAST"> - <location - file="../../chrome/android/java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetCoordinator.java" - line="128"/> - </issue> - - <issue - id="WrongConstant" - message="Must be one of: BookmarkType.NORMAL, BookmarkType.PARTNER, BookmarkType.READING_LIST, BookmarkType.LAST"> - <location - file="../../chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderRow.java" - line="64"/> - </issue> - - <issue - id="WrongConstant" - message="Must be one of: BookmarkType.NORMAL, BookmarkType.PARTNER, BookmarkType.READING_LIST, BookmarkType.LAST"> - <location - file="../../chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderRow.java" - line="71"/> - </issue> - - <issue - id="WrongConstant" - message="Must be one of: BookmarkType.NORMAL, BookmarkType.PARTNER, BookmarkType.READING_LIST, BookmarkType.LAST"> - <location - file="../../chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderRow.java" - line="73"/> - </issue> - - <issue - id="WrongConstant" - message="Must be one of: BookmarkType.NORMAL, BookmarkType.PARTNER, BookmarkType.READING_LIST, BookmarkType.LAST"> - <location - file="../../chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderRow.java" - line="73"/> - </issue> - - <issue - id="WrongConstant" - message="Must be one of: BookmarkType.NORMAL, BookmarkType.PARTNER, BookmarkType.READING_LIST, BookmarkType.LAST"> - <location - file="../../chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUtils.java" - line="406"/> - </issue> - - <issue - id="WrongConstant" message="Must be one of: PageTransition.FIRST, PageTransition.LINK, PageTransition.TYPED, PageTransition.AUTO_BOOKMARK, PageTransition.AUTO_SUBFRAME, PageTransition.MANUAL_SUBFRAME, PageTransition.GENERATED, PageTransition.AUTO_TOPLEVEL, PageTransition.FORM_SUBMIT, PageTransition.RELOAD, PageTransition.KEYWORD, PageTransition.KEYWORD_GENERATED, PageTransition.LAST_CORE, PageTransition.CORE_MASK, PageTransition.BLOCKED, PageTransition.FORWARD_BACK, PageTransition.FROM_ADDRESS_BAR, PageTransition.HOME_PAGE, PageTransition.FROM_API, PageTransition.CHAIN_START, PageTransition.CHAIN_END, PageTransition.CLIENT_REDIRECT, PageTransition.SERVER_REDIRECT, PageTransition.IS_REDIRECT_MASK, PageTransition.QUALIFIER_MASK"> <location file="../../chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java"
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/TasksSurfaceViewBinder.java b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/TasksSurfaceViewBinder.java index e7ed85b9..007032e 100644 --- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/TasksSurfaceViewBinder.java +++ b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/TasksSurfaceViewBinder.java
@@ -76,7 +76,10 @@ private static void setBottomBarHeight(ViewHolder viewHolder, int height) { MarginLayoutParams layoutParams = (MarginLayoutParams) viewHolder.tasksSurfaceView.getLayoutParams(); - if (layoutParams != null) layoutParams.bottomMargin = height; + if (layoutParams != null) { + layoutParams.bottomMargin = height; + viewHolder.tasksSurfaceView.setLayoutParams(layoutParams); + } } private static void setTopBarHeight(ViewHolder viewHolder, int height) {
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUi.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUi.java index 6b3cfe13..fa38099 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUi.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUi.java
@@ -4,7 +4,6 @@ package org.chromium.chrome.browser.tasks.tab_management; -import org.chromium.base.supplier.Supplier; import org.chromium.chrome.browser.toolbar.bottom.BottomControlsContentDelegate; /** @@ -12,7 +11,7 @@ */ public interface TabGroupUi extends BottomControlsContentDelegate { /** - * @return {@link Supplier} that provides dialog visibility. + * @return Whether the TabGridDialog is visible. */ - Supplier<Boolean> getTabGridDialogVisibilitySupplier(); + boolean isTabGridDialogVisible(); }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java index d1be8d2..e44c6e00 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java
@@ -186,8 +186,8 @@ * @return {@link Supplier} that provides dialog visibility. */ @Override - public Supplier<Boolean> getTabGridDialogVisibilitySupplier() { - return () -> mTabGridDialogCoordinator != null && mTabGridDialogCoordinator.isVisible(); + public boolean isTabGridDialogVisible() { + return mTabGridDialogCoordinator != null && mTabGridDialogCoordinator.isVisible(); } /**
diff --git a/chrome/android/java/res/drawable/bookmark_save_flow_background.xml b/chrome/android/java/res/drawable/bookmark_save_flow_background.xml new file mode 100644 index 0000000..b54fcea --- /dev/null +++ b/chrome/android/java/res/drawable/bookmark_save_flow_background.xml
@@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2021 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. --> + +<shape + xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle"> + <solid android:color="@color/default_bg_color" /> + <stroke android:width="1dp" android:color="@color/hairline_stroke_color"/> + <corners android:radius="@dimen/default_rounded_corner_radius" /> +</shape>
diff --git a/chrome/android/java/res/drawable/bookmark_save_flow_ripple.xml b/chrome/android/java/res/drawable/bookmark_save_flow_ripple.xml new file mode 100644 index 0000000..b990134 --- /dev/null +++ b/chrome/android/java/res/drawable/bookmark_save_flow_ripple.xml
@@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2021 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. --> + +<ripple xmlns:android="http://schemas.android.com/apk/res/android" + android:color="?android:attr/colorControlHighlight"> + <item android:id="@android:id/mask" + android:drawable="@drawable/bookmark_save_flow_background" /> +</ripple>
diff --git a/chrome/android/java/res/layout/bookmark_save_flow.xml b/chrome/android/java/res/layout/bookmark_save_flow.xml new file mode 100644 index 0000000..afe4c8ab --- /dev/null +++ b/chrome/android/java/res/layout/bookmark_save_flow.xml
@@ -0,0 +1,97 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2021 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. --> + +<org.chromium.ui.widget.ViewLookupCachingFrameLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:layout_height="match_parent" + android:layout_width="match_parent"> + + <LinearLayout + android:layout_height="match_parent" + android:layout_width="match_parent" + android:padding="24dp" + android:orientation="vertical"> + + <LinearLayout + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:orientation="horizontal"> + + <org.chromium.ui.widget.ChromeImageView + android:id="@+id/title_start_icon" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical|end" /> + + <TextView + android:id="@+id/title_text" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:ellipsize="end" + android:layout_gravity="center_vertical" + android:textAppearance="@style/TextAppearance.HeadlineThick" + android:layout_weight="1" /> + + <TextView + android:id="@+id/bookmark_edit" + android:text="@string/edit_bookmark" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical|end" + android:textAppearance="@style/TextAppearance.TextMedium.Blue" /> + + </LinearLayout> + + <FrameLayout + android:background="@drawable/bookmark_save_flow_background" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:layout_marginTop="16dp"> + + <LinearLayout + android:id="@+id/bookmark_select_folder" + android:background="@drawable/bookmark_save_flow_ripple" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:padding="16dp" + android:orientation="horizontal"> + + <org.chromium.ui.widget.ChromeImageView + android:id="@+id/bookmark_folder_icon" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" /> + + <TextView + android:id="@+id/bookmark_folder_text" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:ellipsize="end" + android:layout_gravity="center_vertical" + android:layout_marginStart="16dp" + android:textAppearance="@style/TextAppearance.TextLarge" + android:layout_weight="1" /> + + <org.chromium.ui.widget.ChromeImageView + android:id="@+id/bookmark_folder_edit_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:src="@drawable/ic_edit_24dp" + android:tint="@color/default_icon_color_tint_list" /> + </LinearLayout> + </FrameLayout> + + <TextView + android:id="@+id/subtitle_text" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:ellipsize="end" + android:layout_gravity="center_vertical" + android:textAppearance="@style/TextAppearance.TextMedium.Secondary" + android:visibility="gone" /> + </LinearLayout> +</org.chromium.ui.widget.ViewLookupCachingFrameLayout>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java index 1939304..9ddfc68 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -1677,16 +1677,14 @@ assert mStartSurfaceSupplier.get() != null; assert getToolbarManager().getTabGroupUi() != null; // Return true if dialog from either tab switcher or tab strip is visible. + ToolbarManager toolbarManager = getToolbarManager(); TabGroupUi tabGroupUi = toolbarManager.getTabGroupUi(); - Supplier<Boolean> tabGroupUiDialogVisibilitySupplier = - tabGroupUi.getTabGridDialogVisibilitySupplier(); + boolean isDialogVisible = tabGroupUi.isTabGridDialogVisible(); + Supplier<Boolean> tabSwitcherDialogVisibilitySupplier = mStartSurfaceSupplier.get().getTabGridDialogVisibilitySupplier(); - boolean isDialogVisible = false; - if (tabGroupUiDialogVisibilitySupplier != null) { - isDialogVisible = tabGroupUiDialogVisibilitySupplier.get(); - } + if (tabSwitcherDialogVisibilitySupplier != null) { isDialogVisible = isDialogVisible || tabSwitcherDialogVisibilitySupplier.get(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java index d21ea1c..640137f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java
@@ -24,6 +24,8 @@ import org.chromium.chrome.browser.bookmarks.BookmarkListEntry.ViewType; import org.chromium.chrome.browser.bookmarks.BookmarkRow.Location; import org.chromium.chrome.browser.feature_engagement.TrackerFactory; +import org.chromium.chrome.browser.power_bookmarks.PowerBookmarkMeta; +import org.chromium.chrome.browser.power_bookmarks.PowerBookmarkType; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.signin.ui.PersonalizedSigninPromoView; import org.chromium.chrome.browser.sync.SyncService; @@ -144,7 +146,8 @@ // Show the tag chiplist only for the shopping folder. // TODO(crbug.com/1247825): Clarify how the tag list should interact with promo headers. - if (mCurrentFolder.getType() == ViewType.SHOPPING_POWER_BOOKMARK) { + PowerBookmarkMeta meta = mDelegate.getModel().getPowerBookmarkMeta(mCurrentFolder); + if (meta != null && meta.getType() == PowerBookmarkType.SHOPPING) { mElements.add(BookmarkListEntry.createChipList()); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowCoordinator.java new file mode 100644 index 0000000..cf9a5bf --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowCoordinator.java
@@ -0,0 +1,165 @@ +// Copyright 2021 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. + +package org.chromium.chrome.browser.bookmarks; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; + +import org.chromium.base.lifetime.DestroyChecker; +import org.chromium.chrome.R; +import org.chromium.components.bookmarks.BookmarkId; +import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent; +import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; +import org.chromium.ui.modelutil.PropertyKey; +import org.chromium.ui.modelutil.PropertyModel; +import org.chromium.ui.modelutil.PropertyModelChangeProcessor; +import org.chromium.ui.widget.ViewLookupCachingFrameLayout; + +/** Coordinates the bottom-sheet saveflow. */ +public class BookmarkSaveFlowCoordinator { + private final Context mContext; + private final PropertyModel mPropertyModel = + new PropertyModel(BookmarkSaveFlowProperties.ALL_PROPERTIES); + private final PropertyModelChangeProcessor<PropertyModel, ViewLookupCachingFrameLayout, + PropertyKey> mChangeProcessor; + private final DestroyChecker mDestroyChecker; + + private BottomSheetController mBottomSheetController; + private BookmarkSaveFlowBottomSheetContent mBottomSheetContent; + private BookmarkSaveFlowMediator mMediator; + private View mBookmarkSaveFlowView; + + private BookmarkModel mBookmarkModel; + + /** + * @param context The {@link Context} associated with this cooridnator. + * @param bottomSheetController Allows displaying content in the bottom sheet. + */ + public BookmarkSaveFlowCoordinator( + @NonNull Context context, @NonNull BottomSheetController bottomSheetController) { + mContext = context; + mBottomSheetController = bottomSheetController; + mBookmarkModel = new BookmarkModel(); + mDestroyChecker = new DestroyChecker(); + + mBookmarkSaveFlowView = LayoutInflater.from(mContext).inflate( + org.chromium.chrome.R.layout.bookmark_save_flow, /*root=*/null); + mMediator = + new BookmarkSaveFlowMediator(mBookmarkModel, mPropertyModel, mContext, this::close); + mChangeProcessor = PropertyModelChangeProcessor.create(mPropertyModel, + (ViewLookupCachingFrameLayout) mBookmarkSaveFlowView, + new BookmarkSaveFlowViewBinder()); + } + + /** + * Shows the bookmark save flow sheet. + */ + public void show(BookmarkId bookmarkId) { + mDestroyChecker.checkNotDestroyed(); + assert mBookmarkModel.isBookmarkModelLoaded(); + mBottomSheetContent = new BookmarkSaveFlowBottomSheetContent(mBookmarkSaveFlowView); + mBottomSheetController.requestShowContent(mBottomSheetContent, /* animate= */ true); + mMediator.show(bookmarkId); + } + + private void close() { + mDestroyChecker.checkNotDestroyed(); + mBottomSheetController.hideContent(mBottomSheetContent, true); + } + + private void destroy() { + mDestroyChecker.checkNotDestroyed(); + mDestroyChecker.destroy(); + + mMediator.destroy(); + mMediator = null; + + mBookmarkSaveFlowView = null; + + mBookmarkModel.destroy(); + mBookmarkModel = null; + + mChangeProcessor.destroy(); + } + + private class BookmarkSaveFlowBottomSheetContent implements BottomSheetContent { + private final View mContentView; + + BookmarkSaveFlowBottomSheetContent(View contentView) { + mContentView = contentView; + } + + @Override + public View getContentView() { + return mContentView; + } + + @Nullable + @Override + public View getToolbarView() { + return null; + } + + @Override + public int getVerticalScrollOffset() { + return 0; + } + + @Override + public void destroy() { + BookmarkSaveFlowCoordinator.this.destroy(); + } + + @Override + public int getPriority() { + return BottomSheetContent.ContentPriority.HIGH; + } + + @Override + public int getPeekHeight() { + return BottomSheetContent.HeightMode.DISABLED; + } + + @Override + public float getFullHeightRatio() { + return BottomSheetContent.HeightMode.WRAP_CONTENT; + } + + @Override + public boolean swipeToDismissEnabled() { + return true; + } + + @Override + public int getSheetContentDescriptionStringId() { + return R.string.bookmarks_bottom_sheet_content_description; + } + + @Override + public int getSheetHalfHeightAccessibilityStringId() { + return R.string.bookmarks_bottom_sheet_opened_half; + } + + @Override + public int getSheetFullHeightAccessibilityStringId() { + return R.string.bookmarks_bottom_sheet_opened_full; + } + + @Override + public int getSheetClosedAccessibilityStringId() { + return R.string.bookmarks_bottom_sheet_closed; + } + } + + @VisibleForTesting + View getViewForTesting() { + return mBookmarkSaveFlowView; + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowMediator.java new file mode 100644 index 0000000..31d4cfd --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowMediator.java
@@ -0,0 +1,85 @@ +// Copyright 2021 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. + +package org.chromium.chrome.browser.bookmarks; + +import android.content.Context; + +import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; +import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkModelObserver; +import org.chromium.components.bookmarks.BookmarkId; +import org.chromium.ui.modelutil.PropertyModel; + +/** Controls the bookmarks save-flow. */ +public class BookmarkSaveFlowMediator extends BookmarkModelObserver { + private final Context mContext; + private final Runnable mCloseRunnable; + private PropertyModel mPropertyModel; + private BookmarkModel mBookmarkModel; + private BookmarkId mBookmarkId; + + /** + * @param bookmarkModel The {@link BookmarkModel} which supplies the data. + * @param propertyModel The {@link PropertyModel} which allows the mediator to push data to the + * model. + * @param context The {@link Context} associated with this mediator. + * @param closeRunnable A {@link Runnable} which closes the bookmark save flow. + */ + public BookmarkSaveFlowMediator(BookmarkModel bookmarkModel, PropertyModel propertyModel, + Context context, Runnable closeRunnable) { + mBookmarkModel = bookmarkModel; + mPropertyModel = propertyModel; + mContext = context; + mCloseRunnable = closeRunnable; + mBookmarkModel.addObserver(this); + } + + /** + * Shows bottom sheet save-flow for the given {@link BookmarkId}. + * + * @param bookmarkId The {@link BookmarkId} to show. + */ + public void show(BookmarkId bookmarkId) { + mBookmarkId = bookmarkId; + + bindBookmarkProperties(mBookmarkId); + mPropertyModel.set(BookmarkSaveFlowProperties.EDIT_ONCLICK_LISTENER, (v) -> { + BookmarkUtils.startEditActivity(mContext, mBookmarkId); + mCloseRunnable.run(); + }); + mPropertyModel.set(BookmarkSaveFlowProperties.FOLDER_SELECT_ONCLICK_LISTENER, (v) -> { + BookmarkUtils.startFolderSelectActivity(mContext, mBookmarkId); + mCloseRunnable.run(); + }); + } + + private void bindBookmarkProperties(BookmarkId bookmarkId) { + BookmarkItem item = mBookmarkModel.getBookmarkById(bookmarkId); + mPropertyModel.set(BookmarkSaveFlowProperties.TITLE_START_ICON, + BookmarkUtils.getSaveFlowStartIconForBookmark(bookmarkId)); + mPropertyModel.set(BookmarkSaveFlowProperties.TITLE_TEXT, + BookmarkUtils.getSaveFlowTitleForBookmark(mContext, bookmarkId)); + mPropertyModel.set(BookmarkSaveFlowProperties.FOLDER_SELECT_START_ICON, + BookmarkUtils.getFolderIcon(mContext, bookmarkId.getType())); + mPropertyModel.set(BookmarkSaveFlowProperties.FOLDER_SELECT_TEXT, + mBookmarkModel.getBookmarkTitle(item.getParentId())); + mPropertyModel.set(BookmarkSaveFlowProperties.SUBTITLE_TEXT, + BookmarkUtils.getSaveFlowSubtitleForBookmark(bookmarkId)); + } + + void destroy() { + mBookmarkModel.removeObserver(this); + mBookmarkModel = null; + mPropertyModel = null; + mBookmarkId = null; + } + + // BookmarkModelObserver implementation + + @Override + public void bookmarkModelChanged() { + if (mBookmarkId == null) return; + bindBookmarkProperties(mBookmarkId); + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowProperties.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowProperties.java new file mode 100644 index 0000000..d154ed91 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowProperties.java
@@ -0,0 +1,36 @@ +// Copyright 2021 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. + +package org.chromium.chrome.browser.bookmarks; + +import android.graphics.drawable.Drawable; +import android.view.View; + +import org.chromium.ui.modelutil.PropertyKey; +import org.chromium.ui.modelutil.PropertyModel.WritableObjectPropertyKey; + +/** Hosts the properties for the bookmarks save flow. */ +public class BookmarkSaveFlowProperties { + public static final WritableObjectPropertyKey<View.OnClickListener> EDIT_ONCLICK_LISTENER = + new WritableObjectPropertyKey<>(); + public static final WritableObjectPropertyKey<View.OnClickListener> + FOLDER_SELECT_ONCLICK_LISTENER = new WritableObjectPropertyKey<>(); + + public static final WritableObjectPropertyKey<Drawable> TITLE_START_ICON = + new WritableObjectPropertyKey<>(); + public static final WritableObjectPropertyKey<CharSequence> TITLE_TEXT = + new WritableObjectPropertyKey<>(); + + public static final WritableObjectPropertyKey<Drawable> FOLDER_SELECT_START_ICON = + new WritableObjectPropertyKey<>(); + public static final WritableObjectPropertyKey<CharSequence> FOLDER_SELECT_TEXT = + new WritableObjectPropertyKey<>(); + + public static final WritableObjectPropertyKey<CharSequence> SUBTITLE_TEXT = + new WritableObjectPropertyKey<>(); + + public static final PropertyKey[] ALL_PROPERTIES = {EDIT_ONCLICK_LISTENER, + FOLDER_SELECT_ONCLICK_LISTENER, TITLE_START_ICON, TITLE_TEXT, FOLDER_SELECT_START_ICON, + FOLDER_SELECT_TEXT, SUBTITLE_TEXT}; +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowViewBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowViewBinder.java new file mode 100644 index 0000000..3ee0095 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowViewBinder.java
@@ -0,0 +1,48 @@ +// Copyright 2021 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. + +package org.chromium.chrome.browser.bookmarks; + +import android.widget.ImageView; +import android.widget.TextView; + +import org.chromium.chrome.R; +import org.chromium.ui.modelutil.PropertyKey; +import org.chromium.ui.modelutil.PropertyModel; +import org.chromium.ui.modelutil.PropertyModelChangeProcessor.ViewBinder; +import org.chromium.ui.widget.ViewLookupCachingFrameLayout; + +/** ViewBinder for the bookmarks save flow. */ +public class BookmarkSaveFlowViewBinder + implements ViewBinder<PropertyModel, ViewLookupCachingFrameLayout, PropertyKey> { + @Override + public void bind( + PropertyModel model, ViewLookupCachingFrameLayout view, PropertyKey propertyKey) { + if (propertyKey == BookmarkSaveFlowProperties.EDIT_ONCLICK_LISTENER) { + view.findViewById(R.id.bookmark_edit) + .setOnClickListener( + model.get(BookmarkSaveFlowProperties.EDIT_ONCLICK_LISTENER)); + } else if (propertyKey == BookmarkSaveFlowProperties.FOLDER_SELECT_ONCLICK_LISTENER) { + view.findViewById(R.id.bookmark_select_folder) + .setOnClickListener( + model.get(BookmarkSaveFlowProperties.FOLDER_SELECT_ONCLICK_LISTENER)); + } else if (propertyKey == BookmarkSaveFlowProperties.TITLE_START_ICON) { + ((ImageView) view.findViewById(R.id.title_start_icon)) + .setImageDrawable(model.get(BookmarkSaveFlowProperties.TITLE_START_ICON)); + } else if (propertyKey == BookmarkSaveFlowProperties.TITLE_TEXT) { + ((TextView) view.findViewById(R.id.title_text)) + .setText(model.get(BookmarkSaveFlowProperties.TITLE_TEXT)); + } else if (propertyKey == BookmarkSaveFlowProperties.FOLDER_SELECT_START_ICON) { + ((ImageView) view.findViewById(R.id.bookmark_folder_icon)) + .setImageDrawable( + model.get(BookmarkSaveFlowProperties.FOLDER_SELECT_START_ICON)); + } else if (propertyKey == BookmarkSaveFlowProperties.FOLDER_SELECT_TEXT) { + ((TextView) view.findViewById(R.id.bookmark_folder_text)) + .setText(model.get(BookmarkSaveFlowProperties.FOLDER_SELECT_TEXT)); + } else if (propertyKey == BookmarkSaveFlowProperties.SUBTITLE_TEXT) { + ((TextView) view.findViewById(R.id.subtitle_text)) + .setText(model.get(BookmarkSaveFlowProperties.SUBTITLE_TEXT)); + } + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUtils.java index 1504d6dc..cda1735 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUtils.java
@@ -93,6 +93,15 @@ return; } + if (isImprovedSaveFlowEnabled()) { + BookmarkId newBookmarkId = + addBookmarkAndShowSaveFlow(activity, bookmarkModel, tab, bottomSheetController); + callback.onResult(newBookmarkId); + return; + } + + // TODO(crbug.com/1249283): Add separate entrypoint to save reading list items that uses + // the improved save flow. if (CachedFeatureFlags.isEnabled(ChromeFeatureList.BOOKMARK_BOTTOM_SHEET)) { // Show a bottom sheet to let the user select target bookmark folder. showBookmarkBottomSheet(bookmarkModel, tab, snackbarManager, bottomSheetController, @@ -132,6 +141,17 @@ }); } + private static BookmarkId addBookmarkAndShowSaveFlow(Activity activity, + BookmarkModel bookmarkModel, Tab tab, BottomSheetController bottomSheetController) { + BookmarkId bookmarkId = + addBookmarkInternal(activity, bookmarkModel, tab.getTitle(), tab.getOriginalUrl()); + BookmarkSaveFlowCoordinator bookmarkSaveFlowCoordinator = + new BookmarkSaveFlowCoordinator(activity, bottomSheetController); + bookmarkSaveFlowCoordinator.show(bookmarkId); + + return bookmarkId; + } + // The legacy code path to add or edit bookmark without triggering the bookmark bottom sheet. private static BookmarkId addBookmarkAndShowSnackbar(BookmarkModel bookmarkModel, Tab tab, SnackbarManager snackbarManager, Activity activity, boolean fromCustomTab) { @@ -383,6 +403,11 @@ } } + /** Starts an {@link BookmarkFolderSelectActivity} for the given {@link BookmarkId}. */ + public static void startFolderSelectActivity(Context context, BookmarkId bookmarkId) { + BookmarkFolderSelectActivity.startFolderSelectActivity(context, bookmarkId); + } + /** * Opens a bookmark and reports UMA. * @param context The current context used to launch the intent. @@ -453,6 +478,40 @@ : R.color.default_icon_color_tint_list; } + /** + * Retrieve the save flow title for the given bookmark. + * + * @param context The current Android {@link Context}. + * @param bookmarkId The {@link BookmarkId} to get the title for. + * @return The title associated with the given bookmarkId. + */ + public static String getSaveFlowTitleForBookmark(Context context, BookmarkId bookmarkId) { + // TODO(crbug.com/1243383): Add title for price tracking. + return context.getResources().getString(R.string.bookmark_page_saved_default); + } + + /** + * Retrieve the save flow subtitle for the given bookmark. + * + * @param bookmarkId The {@link BookmarkId} to get the subtitle for. + * @return The subtitle associated with the given bookmarkId. + */ + public static String getSaveFlowSubtitleForBookmark(BookmarkId bookmarkId) { + // TODO(crbug.com/1243383): Add subtitle for price tracking. + return null; + } + + /** + * Retrieve the save flow start icon for the given bookmark. + * + * @param bookmarkId The {@link BookmarkId} to get the start icon for. + * @return The start icon associated with the given bookmarkId. + */ + public static Drawable getSaveFlowStartIconForBookmark(BookmarkId bookmarkId) { + // TODO(crbug.com/1243383): Add start icon for price tracking. + return null; + } + private static void openUrl(Context context, String url, ComponentName componentName) { Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); intent.putExtra( @@ -582,4 +641,9 @@ ChromePreferenceKeys.BOOKMARKS_LAST_USED_URL); } } + + private static boolean isImprovedSaveFlowEnabled() { + return ChromeFeatureList.isInitialized() + && ChromeFeatureList.isEnabled(ChromeFeatureList.BOOKMARKS_IMPROVED_SAVE_FLOW); + } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowTest.java new file mode 100644 index 0000000..f3fa70b --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowTest.java
@@ -0,0 +1,134 @@ +// Copyright 2021 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. + +package org.chromium.chrome.browser.bookmarks; + +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.assertion.ViewAssertions.matches; +import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; +import static androidx.test.espresso.matcher.ViewMatchers.withText; + +import androidx.test.espresso.Espresso; +import androidx.test.filters.MediumTest; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.Feature; +import org.chromium.chrome.R; +import org.chromium.chrome.browser.ChromeTabbedActivity; +import org.chromium.chrome.browser.flags.ChromeFeatureList; +import org.chromium.chrome.browser.flags.ChromeSwitches; +import org.chromium.chrome.browser.partnerbookmarks.PartnerBookmarksShim; +import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.test.ChromeActivityTestRule; +import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.ChromeTabbedActivityTestRule; +import org.chromium.chrome.test.util.BookmarkTestUtil; +import org.chromium.chrome.test.util.ChromeRenderTestRule; +import org.chromium.chrome.test.util.browser.Features.EnableFeatures; +import org.chromium.components.bookmarks.BookmarkId; +import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; +import org.chromium.components.browser_ui.bottomsheet.BottomSheetTestSupport; +import org.chromium.content_public.browser.test.util.ClickUtils; +import org.chromium.content_public.browser.test.util.TestThreadUtils; +import org.chromium.ui.test.util.DisableAnimationsTestRule; +import org.chromium.url.GURL; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +/** Tests for the bookmark save flow. */ +@RunWith(ChromeJUnit4ClassRunner.class) +@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) +@EnableFeatures(ChromeFeatureList.OMNIBOX_ASSISTANT_VOICE_SEARCH) +public class BookmarkSaveFlowTest { + @Rule + public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); + + @Rule + public DisableAnimationsTestRule mDisableAnimationsTestRule = new DisableAnimationsTestRule(); + + @Rule + public ChromeRenderTestRule mRenderTestRule = + ChromeRenderTestRule.Builder.withPublicCorpus().build(); + + private BookmarkSaveFlowCoordinator mBookmarkSaveFlowCoordinator; + private BottomSheetController mBottomSheetController; + private BottomSheetTestSupport mBottomSheetTestSupport; + private BookmarkModel mBookmarkModel; + private BookmarkBridge mBookmarkBridge; + + @Before + public void setUp() throws ExecutionException { + mActivityTestRule.startMainActivityOnBlankPage(); + ChromeActivityTestRule.waitForActivityNativeInitializationComplete( + mActivityTestRule.getActivity()); + + TestThreadUtils.runOnUiThreadBlocking(() -> { + ChromeTabbedActivity cta = mActivityTestRule.getActivity(); + mBottomSheetController = + cta.getRootUiCoordinatorForTesting().getBottomSheetController(); + mBottomSheetTestSupport = new BottomSheetTestSupport(mBottomSheetController); + mBookmarkSaveFlowCoordinator = + new BookmarkSaveFlowCoordinator(cta, mBottomSheetController); + mBookmarkModel = new BookmarkModel(Profile.fromWebContents( + mActivityTestRule.getActivity().getActivityTab().getWebContents())); + mBookmarkBridge = mActivityTestRule.getActivity().getBookmarkBridgeForTesting(); + }); + + loadBookmarkModel(); + BookmarkId id = addBookmark("Test bookmark", new GURL("http://a.com")); + TestThreadUtils.runOnUiThreadBlocking(() -> { mBookmarkSaveFlowCoordinator.show(id); }); + } + + @Test + @MediumTest + @Feature({"RenderTest"}) + public void testBookmarkSaveFlow() throws IOException { + mRenderTestRule.render( + mBookmarkSaveFlowCoordinator.getViewForTesting(), "bookmark_save_flow"); + } + + @Test + @MediumTest + public void testBookmarkSaveFlowEdit() throws IOException { + ChromeTabbedActivity cta = mActivityTestRule.getActivity(); + ClickUtils.clickButton(cta.findViewById(R.id.bookmark_edit)); + onView(withText(mActivityTestRule.getActivity().getResources().getString( + R.string.edit_bookmark))) + .check(matches(isDisplayed())); + + // Dismiss the activity. + Espresso.pressBack(); + } + + @Test + @MediumTest + public void testBookmarkSaveFlowChooseFolder() throws IOException { + ChromeTabbedActivity cta = mActivityTestRule.getActivity(); + ClickUtils.clickButton(cta.findViewById(R.id.bookmark_select_folder)); + onView(withText(mActivityTestRule.getActivity().getResources().getString( + R.string.bookmark_choose_folder))) + .check(matches(isDisplayed())); + + // Dismiss the activity. + Espresso.pressBack(); + } + + private void loadBookmarkModel() { + // Do not read partner bookmarks in setUp(), so that the lazy reading is covered. + TestThreadUtils.runOnUiThreadBlocking( + () -> PartnerBookmarksShim.kickOffReading(mActivityTestRule.getActivity())); + BookmarkTestUtil.waitForBookmarkModelLoaded(); + } + + private BookmarkId addBookmark(final String title, final GURL url) throws ExecutionException { + return TestThreadUtils.runOnUiThreadBlocking( + () -> mBookmarkModel.addBookmark(mBookmarkModel.getDefaultFolder(), 0, title, url)); + } +} \ No newline at end of file
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index aa439b1..83bdf638 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp
@@ -854,6 +854,9 @@ <message name="IDS_BLUETOOTH_PAIRING_LEARN_MORE" desc="Bluetooth pairing dialog: Message informing the user on what actions to take in order to see a device in the list of available devices."> Make sure your Bluetooth device is in pairing mode and nearby. <ph name="BEGIN_LINK_LEARN_MORE"><a target="_blank" href="$1"></ph>Learn more<ph name="END_LINK_LEARN_MORE"></a></ph> </message> + <message name="IDS_BLUETOOTH_PAIRING_ENTER_PIN" desc="Bluetooth pairing dialog: Message displayed informing the user to enter a PIN in other to complete device pairing."> + Enter PIN to pair with <ph name="DEVICE_NAME">$1<ex>Nexus S</ex></ph> + </message> <!-- Strings for the OOBE packaged license screen --> <message name="IDS_OOBE_PACKAGED_LICENSE_TITLE" desc="Title of the screen which advertises use of packaged license.">
diff --git a/chrome/app/chromeos_strings_grdp/IDS_BLUETOOTH_PAIRING_ENTER_PIN.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_BLUETOOTH_PAIRING_ENTER_PIN.png.sha1 new file mode 100644 index 0000000..54d5fa4f --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_BLUETOOTH_PAIRING_ENTER_PIN.png.sha1
@@ -0,0 +1 @@ +dfb28105967fe87eb3934f7d00815bcd21b4d795 \ No newline at end of file
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index b0de3e10..4c12149 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -46,7 +46,6 @@ #include "chrome/browser/net/stub_resolver_config_reader.h" #include "chrome/browser/net/system_network_context_manager.h" #include "chrome/browser/notifications/scheduler/public/features.h" -#include "chrome/browser/performance_hints/performance_hints_features.h" #include "chrome/browser/performance_manager/policies/policy_features.h" #include "chrome/browser/permissions/abusive_origin_notifications_permission_revocation_config.h" #include "chrome/browser/permissions/quiet_notification_permission_ui_config.h" @@ -3097,10 +3096,6 @@ flag_descriptions::kDefaultCalculatorWebAppName, flag_descriptions::kDefaultCalculatorWebAppDescription, kOsCrOS, FEATURE_VALUE_TYPE(web_app::kDefaultCalculatorWebApp)}, - {"enable-notification-indicator", - flag_descriptions::kNotificationIndicatorName, - flag_descriptions::kNotificationIndicatorDescription, kOsCrOS, - FEATURE_VALUE_TYPE(features::kNotificationIndicator)}, {"enable-notifications-revamp", flag_descriptions::kNotificationsRevampName, flag_descriptions::kNotificationsRevampDescription, kOsCrOS, FEATURE_VALUE_TYPE(ash::features::kNotificationsRefresh)}, @@ -3320,6 +3315,10 @@ flag_descriptions::kWebBluetoothNewPermissionsBackendDescription, kOsAndroid | kOsDesktop, FEATURE_VALUE_TYPE(features::kWebBluetoothNewPermissionsBackend)}, + {"enable-webusb-device-detection", + flag_descriptions::kWebUsbDeviceDetectionName, + flag_descriptions::kWebUsbDeviceDetectionDescription, kOsDesktop, + FEATURE_VALUE_TYPE(features::kWebUsbDeviceDetection)}, #if defined(USE_AURA) {"overscroll-history-navigation", flag_descriptions::kOverscrollHistoryNavigationName, @@ -5745,6 +5744,11 @@ flag_descriptions::kEnableShortcutCustomizationAppDescription, kOsCrOS, FEATURE_VALUE_TYPE(features::kShortcutCustomizationApp)}, + {"enable-firmware-updater-app", + flag_descriptions::kEnableFirmwareUpdaterAppName, + flag_descriptions::kEnableFirmwareUpdaterAppDescription, kOsCrOS, + FEATURE_VALUE_TYPE(ash::features::kFirmwareUpdaterApp)}, + {"enhanced-network-voices", flag_descriptions::kEnhancedNetworkVoicesName, flag_descriptions::kEnhancedNetworkVoicesDescription, kOsCrOS, FEATURE_VALUE_TYPE(features::kEnhancedNetworkVoices)}, @@ -6420,13 +6424,6 @@ kPasswordChangeFeatureVariations, "PasswordChangeFeatureVariations")}, - {"context-menu-performance-info-and-remote-hints-fetching", - flag_descriptions::kContextMenuPerformanceInfoAndRemoteHintFetchingName, - flag_descriptions:: - kContextMenuPerformanceInfoAndRemoteHintFetchingDescription, - kOsAndroid, - FEATURE_VALUE_TYPE(optimization_guide::features:: - kContextMenuPerformanceInfoAndRemoteHintFetching)}, #endif // !defined(OS_ANDROID) #if defined(OS_ANDROID) @@ -7634,6 +7631,11 @@ FEATURE_VALUE_TYPE(features::kCanvasOopRasterization)}, #if defined(OS_ANDROID) + {"bookmarks-improved-save-flow", + flag_descriptions::kBookmarksImprovedSaveFlowName, + flag_descriptions::kBookmarksImprovedSaveFlowDescription, kOsAndroid, + FEATURE_VALUE_TYPE(chrome::android::kBookmarksImprovedSaveFlow)}, + {"bookmarks-refresh", flag_descriptions::kBookmarksRefreshName, flag_descriptions::kBookmarksRefreshDescription, kOsAndroid, FEATURE_VALUE_TYPE(chrome::android::kBookmarksRefresh)},
diff --git a/chrome/browser/ash/accessibility/spoken_feedback_app_list_browsertest.cc b/chrome/browser/ash/accessibility/spoken_feedback_app_list_browsertest.cc index 5977f7a6..1aac9e6 100644 --- a/chrome/browser/ash/accessibility/spoken_feedback_app_list_browsertest.cc +++ b/chrome/browser/ash/accessibility/spoken_feedback_app_list_browsertest.cc
@@ -12,7 +12,6 @@ #include "ash/public/cpp/test/shell_test_api.h" #include "ash/shell.h" #include "base/strings/utf_string_conversions.h" -#include "base/test/scoped_feature_list.h" #include "chrome/browser/ash/accessibility/spoken_feedback_browsertest.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/app_list/app_list_client_impl.h" @@ -145,9 +144,7 @@ class NotificationSpokenFeedbackAppListTest : public SpokenFeedbackAppListTest { protected: - NotificationSpokenFeedbackAppListTest() { - scoped_features_.InitWithFeatures({::features::kNotificationIndicator}, {}); - } + NotificationSpokenFeedbackAppListTest() = default; ~NotificationSpokenFeedbackAppListTest() = default; void SetUpCommandLine(base::CommandLine* command_line) override { @@ -161,9 +158,6 @@ item->UpdateNotificationBadgeForTesting(has_badge); } - - private: - base::test::ScopedFeatureList scoped_features_; }; INSTANTIATE_TEST_SUITE_P(TestAsNormalAndGuestUser,
diff --git a/chrome/browser/ash/accessibility/spoken_feedback_browsertest.cc b/chrome/browser/ash/accessibility/spoken_feedback_browsertest.cc index 6804245..4470cd8 100644 --- a/chrome/browser/ash/accessibility/spoken_feedback_browsertest.cc +++ b/chrome/browser/ash/accessibility/spoken_feedback_browsertest.cc
@@ -511,26 +511,9 @@ sm_.Replay(); } -class ShelfNotificationBadgeSpokenFeedbackTest : public SpokenFeedbackTest { - protected: - ShelfNotificationBadgeSpokenFeedbackTest() { - scoped_features_.InitWithFeatures({::features::kNotificationIndicator}, {}); - } - ~ShelfNotificationBadgeSpokenFeedbackTest() override = default; - - private: - base::test::ScopedFeatureList scoped_features_; -}; - -INSTANTIATE_TEST_SUITE_P(TestAsNormalAndGuestUser, - ShelfNotificationBadgeSpokenFeedbackTest, - ::testing::Values(kTestAsNormalUser, - kTestAsGuestUser)); - // Verifies that an announcement is triggered when focusing a ShelfItem with a // notification badge shown. -IN_PROC_BROWSER_TEST_P(ShelfNotificationBadgeSpokenFeedbackTest, - ShelfNotificationBadgeAnnouncement) { +IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, ShelfNotificationBadgeAnnouncement) { EnableChromeVox(); // Create and add a test app to the shelf model.
diff --git a/chrome/browser/browser_features.cc b/chrome/browser/browser_features.cc index d22035a..08c07d18 100644 --- a/chrome/browser/browser_features.cc +++ b/chrome/browser/browser_features.cc
@@ -86,4 +86,9 @@ return false; } +// Enables runtime detection of USB devices which provide a WebUSB landing page +// descriptor. +const base::Feature kWebUsbDeviceDetection{"WebUsbDeviceDetection", + base::FEATURE_ENABLED_BY_DEFAULT}; + } // namespace features
diff --git a/chrome/browser/browser_features.h b/chrome/browser/browser_features.h index bf1e7fb..d0ce977 100644 --- a/chrome/browser/browser_features.h +++ b/chrome/browser/browser_features.h
@@ -48,6 +48,8 @@ // determine whether data migration should occur or not. bool ShouldTriggerNetworkDataMigration(); +extern const base::Feature kWebUsbDeviceDetection; + } // namespace features #endif // CHROME_BROWSER_BROWSER_FEATURES_H_
diff --git a/chrome/browser/content_creation/reactions/internal/android/BUILD.gn b/chrome/browser/content_creation/reactions/internal/android/BUILD.gn index 7471a09..4308df6 100644 --- a/chrome/browser/content_creation/reactions/internal/android/BUILD.gn +++ b/chrome/browser/content_creation/reactions/internal/android/BUILD.gn
@@ -33,5 +33,6 @@ "java/res/layout/reactions_dialog.xml", "java/res/layout/scene.xml", "java/res/layout/toolbar.xml", + "java/res/values/dimens.xml", ] }
diff --git a/chrome/browser/content_creation/reactions/internal/android/java/res/layout/reactions_dialog.xml b/chrome/browser/content_creation/reactions/internal/android/java/res/layout/reactions_dialog.xml index 0d951c5..f399ab0 100644 --- a/chrome/browser/content_creation/reactions/internal/android/java/res/layout/reactions_dialog.xml +++ b/chrome/browser/content_creation/reactions/internal/android/java/res/layout/reactions_dialog.xml
@@ -3,18 +3,31 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> - -<!-- TODO(crbug.com/1251666): Add android:contentDescription="@string/foo" attribute--> -<LinearLayout +<!-- TODO(crbug.com/1252182): Add android:contentDescription="@string/foo" attributes --> +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" + android:id="@+id/lightweight_reactions_dialog" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="@color/default_bg_color" - android:orientation="vertical" - android:importantForAccessibility="yes"> + android:orientation="vertical"> - <include layout="@layout/scene"/> + <include layout="@layout/scene" + android:id="@+id/lightweight_reactions_scene" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_above="@id/lightweight_reactions_divider"/> - <include layout="@layout/toolbar"/> -</LinearLayout> \ No newline at end of file + <View + android:id="@+id/lightweight_reactions_divider" + android:background="@color/divider_line_bg_color" + android:layout_above="@id/lightweight_reactions_toolbar" + android:layout_height="@dimen/toolbar_separator_height" + android:layout_width="match_parent"/> + + <include layout="@layout/toolbar" + android:id="@+id/lightweight_reactions_toolbar" + android:layout_width="match_parent" + android:layout_height="@dimen/toolbar_total_height" + android:layout_alignParentBottom="true" + /> +</RelativeLayout> \ No newline at end of file
diff --git a/chrome/browser/content_creation/reactions/internal/android/java/res/layout/scene.xml b/chrome/browser/content_creation/reactions/internal/android/java/res/layout/scene.xml index 750f7a3..346273ae 100644 --- a/chrome/browser/content_creation/reactions/internal/android/java/res/layout/scene.xml +++ b/chrome/browser/content_creation/reactions/internal/android/java/res/layout/scene.xml
@@ -3,13 +3,13 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> -<!-- TODO(crbug.com/1252182): Add android:contentDescription="@string/foo" attribute--> +<!-- TODO(crbug.com/1252182): Add android:contentDescription="@string/foo" attributes --> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="@color/modern_blue_600" android:orientation="vertical" + android:background="@color/default_scrim_color" android:importantForAccessibility="yes"> <ImageView android:id="@+id/lightweight_reactions_background"
diff --git a/chrome/browser/content_creation/reactions/internal/android/java/res/layout/toolbar.xml b/chrome/browser/content_creation/reactions/internal/android/java/res/layout/toolbar.xml index 63d3e51..a0391050 100644 --- a/chrome/browser/content_creation/reactions/internal/android/java/res/layout/toolbar.xml +++ b/chrome/browser/content_creation/reactions/internal/android/java/res/layout/toolbar.xml
@@ -3,22 +3,65 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> -<!-- TODO:(crbug.com/1251662) Add android:contentDescription="@string/foo" attribute--> +<!-- TODO(crbug.com/1252182): Add android:contentDescription="@string/foo" attributes --> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" - android:layout_height="match_parent" - android:background="@color/modern_blue_700" + android:layout_height="wrap_content" android:orientation="vertical" android:importantForAccessibility="yes"> - <TextView - android:id="@+id/lightweight_reactions_toolbar_test" + <LinearLayout + android:id="@+id/lightweight_reactions_toolbar_reaction_picker" android:gravity="center" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:layout_gravity="center" - android:text="@string/sharing_lightweight_reactions" - android:textAppearance="@style/TextAppearance.TextMedium.Secondary" /> + android:orientation="horizontal" + android:layout_above="@id/lightweight_reactions_toolbar_controls" + android:paddingHorizontal="@dimen/toolbar_button_margin" + android:layout_height="@dimen/toolbar_row_height" + android:layout_width="match_parent"> + <!-- Empty for now --> + </LinearLayout> + + <LinearLayout + android:id="@+id/lightweight_reactions_toolbar_controls" + android:gravity="center" + android:orientation="horizontal" + android:paddingHorizontal="@dimen/toolbar_button_margin" + android:layout_alignParentBottom="true" + android:layout_height="@dimen/toolbar_row_height" + android:layout_width="match_parent"> + + <org.chromium.ui.widget.ChromeImageButton + android:id="@+id/close_button" + android:contentDescription="@string/close" + android:src="@drawable/btn_close" + android:layout_height="match_parent" + android:layout_width="@dimen/toolbar_button_size" + android:paddingHorizontal="@dimen/toolbar_button_padding" + app:tint="@color/default_icon_color_tint_list" + style="@style/ToolbarButton"/> + + <TextView + android:id="@+id/lightweight_reactions_toolbar_title" + android:gravity="center" + android:layout_height="wrap_content" + android:layout_width="0dp" + android:layout_weight="1" + android:layout_gravity="center" + android:text="@string/sharing_lightweight_reactions" + android:textAppearance="@style/TextAppearance.TextMedium.Secondary"/> + + <!-- TODO(crbug.com/1252182): Fix the android:contentDescription attribute --> + <org.chromium.ui.widget.ChromeImageButton + android:id="@+id/done_button" + android:contentDescription="@string/screenshot_save_title" + android:src="@drawable/ic_checkmark_24dp" + android:layout_height="match_parent" + android:layout_width="@dimen/toolbar_button_size" + android:paddingHorizontal="@dimen/toolbar_button_padding" + app:tint="@color/default_icon_color_tint_list" + style="@style/ToolbarButton"/> + </LinearLayout> </RelativeLayout> \ No newline at end of file
diff --git a/chrome/browser/content_creation/reactions/internal/android/java/res/values/dimens.xml b/chrome/browser/content_creation/reactions/internal/android/java/res/values/dimens.xml new file mode 100644 index 0000000..e1df5f0 --- /dev/null +++ b/chrome/browser/content_creation/reactions/internal/android/java/res/values/dimens.xml
@@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2021 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. --> + +<resources> + <dimen name="toolbar_row_height">56dp</dimen> + <dimen name="toolbar_total_height">112dp</dimen> + <dimen name="toolbar_separator_height">1dp</dimen> + <dimen name="toolbar_button_size">40dp</dimen> + <dimen name="toolbar_button_margin">16dp</dimen> + <dimen name="toolbar_button_padding">8dp</dimen> +</resources> \ No newline at end of file
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 8e7e4902..bf8b3dc 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -559,6 +559,11 @@ "expiry_milestone": 98 }, { + "name": "bookmarks-improved-save-flow", + "owners": ["wylieb", "fgorski", "mdjones"], + "expiry_milestone": 100 + }, + { "name": "bookmarks-refresh", "owners": ["wylieb", "fgorski", "mdjones"], "expiry_milestone": 100 @@ -791,11 +796,6 @@ "owners": [ "yusuyoutube@google.com", "benwgold@google.com", "lens-chrome@google.com" ], "expiry_milestone": 96 }, - { - "name": "context-menu-performance-info-and-remote-hints-fetching", - "owners": [ "jds" ], - "expiry_milestone": 90 - }, { "name":"context-menu-phase2", "owners":["gambard", "bling-flags@google.com"], "expiry_milestone":100 @@ -1914,6 +1914,11 @@ "expiry_milestone": 85 }, { + "name": "enable-firmware-updater-app", + "owners": [ "zentaro", "jimmyxgong", "swifton", "cros-peripherals@google.com" ], + "expiry_milestone": 102 + }, + { "name": "enable-first-party-sets", "owners": [ "chrome-first-party-sets@chromium.org" ], "expiry_milestone": 99 @@ -2042,7 +2047,7 @@ { "name": "enable-image-reader", "owners": [ "vikassoni", "liberato" ], - "expiry_milestone": 95 + "expiry_milestone": 115 }, { "name": "enable-immersive-fullscreen-toolbar", @@ -2146,6 +2151,11 @@ "expiry_milestone": 92 }, { + "name": "enable-long-message-duration", + "owners": [ "tinazwang", "bling-flags@google.com" ], + "expiry_milestone": 110 + }, + { "name": "enable-magnifier-continuous-mouse-following-mode-setting", "owners": [ "josiahk", "//ui/accessibility/OWNERS" ], "expiry_milestone": 92 @@ -2251,11 +2261,6 @@ "expiry_milestone": -1 }, { - "name": "enable-notification-indicator", - "owners": [ "mmourgos", "newcomer" ], - "expiry_milestone": 91 - }, - { "name": "enable-notifications-revamp", "owners": [ "amehfooz", "newcomer" ], "expiry_milestone": 100 @@ -2859,6 +2864,11 @@ "expiry_milestone": 88 }, { + "name": "enable-webusb-device-detection", + "owners": [ "reillyg", "deviceapi-team@google.com" ], + "expiry_milestone": 104 + }, + { "name": "enable-windows-gaming-input-data-fetcher", "owners": [ "qiaye@microsoft.com" ], "expiry_milestone": 92 @@ -5170,7 +5180,15 @@ { "name": "system-keyboard-lock", "owners": [ "joedow", "garykac", "jamiewalch" ], - "expiry_milestone": 95 + // This flag allows users to prevent the keyboard-lock API from capturing + // system keys (e.g. by using low-level hooks) which might interfere with + // their workflows or other apps running on the machine. It is also needed + // for browsertests as the test framework relies on low-level keyboard hooks + // which prevents testing this feature if this flag is not disabled. + // Note that there is a second version of this API being discussed which + // allows the caller to select whether system hooks are enabled. + // See: https://github.com/WICG/keyboard-lock/blob/gh-pages/explainer2.md + "expiry_milestone": -1 }, { "name": "tab-groups-auto-create",
diff --git a/chrome/browser/flag-never-expire-list.json b/chrome/browser/flag-never-expire-list.json index 199edf6..3680718 100644 --- a/chrome/browser/flag-never-expire-list.json +++ b/chrome/browser/flag-never-expire-list.json
@@ -98,6 +98,7 @@ "show-taps", "show-touch-hud", "smooth-scrolling", + "system-keyboard-lock", "tint-composited-content", "top-chrome-touch-ui", "ui-debug-tools",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 9cd7de5a..54a9924 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -921,6 +921,11 @@ "embedding an isolated top-level page. See " "https://github.com/shivanigithub/fenced-frame"; +const char kEnableFirmwareUpdaterAppName[] = "Enable firmware updater app"; +const char kEnableFirmwareUpdaterAppDescription[] = + "Enable the firmware updater SWA, allowing users to update firmware " + "on supported peripherals."; + const char kEnableGamepadButtonAxisEventsName[] = "Gamepad Button and Axis Events"; const char kEnableGamepadButtonAxisEventsDescription[] = @@ -1680,11 +1685,6 @@ const char kNewUsbBackendDescription[] = "Enables the new experimental USB backend for macOS"; -const char kNotificationIndicatorName[] = "Notification Indicators"; -const char kNotificationIndicatorDescription[] = - "Enable notification indicators, which appear on shelf app icons and " - "launcher apps when a notification is active."; - const char kNotificationsRevampName[] = "Notifications Revamp"; const char kNotificationsRevampDescription[] = "Enable notification UI revamp and grouped web notifications."; @@ -2093,10 +2093,13 @@ "to true, pointer movements wil not be affected by the underlying platform " "modications such as mouse accelaration."; -const char kBookmarksRefreshName[] = - "Enables the a visual refresh for bookmarks"; +const char kBookmarksImprovedSaveFlowName[] = "Improved bookmarks save flow"; +const char kBookmarksImprovedSaveFlowDescription[] = + "Enabled an improved save flow for bookmarks."; + +const char kBookmarksRefreshName[] = "Bookmarks visual refresh"; const char kBookmarksRefreshDescription[] = - "Changes the bookmark list visuals."; + "Enalbed a visual refresh for bookmarks."; const char kPrerender2Name[] = "Prerender2"; const char kPrerender2Description[] = @@ -2806,6 +2809,13 @@ "When enabled, WebRTC will only use the Video Encode Accelerator for " "video resolutions inside those published as supported."; +const char kWebUsbDeviceDetectionName[] = + "Automatic detection of WebUSB-compatible devices"; +const char kWebUsbDeviceDetectionDescription[] = + "When enabled, the user will be notified when a device which advertises " + "support for WebUSB is connected. Disable if problems with USB devices are " + "observed when the browser is running."; + const char kWebXrForceRuntimeName[] = "Force WebXr Runtime"; const char kWebXrForceRuntimeDescription[] = "Force the browser to use a particular runtime, even if it would not " @@ -3041,13 +3051,6 @@ "A new method of persisting Tab data across restarts has been devised " "and implemented. This actives the new approach."; -const char kContextMenuPerformanceInfoAndRemoteHintFetchingName[] = - "Context menu performance info and remote hint fetching"; -const char kContextMenuPerformanceInfoAndRemoteHintFetchingDescription[] = - "Enables showing link performance information in the context menu and " - "allows communicating with Google servers to fetch performance information " - "for the main frame URL."; - const char kContextualSearchDebugName[] = "Contextual Search debug"; const char kContextualSearchDebugDescription[] = "Enables internal debugging of Contextual Search behavior on the client "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 05b5cea..4940328 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -625,6 +625,9 @@ extern const char kEnableFencedFramesName[]; extern const char kEnableFencedFramesDescription[]; +extern const char kEnableFirmwareUpdaterAppName[]; +extern const char kEnableFirmwareUpdaterAppDescription[]; + extern const char kEnableGamepadButtonAxisEventsName[]; extern const char kEnableGamepadButtonAxisEventsDescription[]; @@ -967,9 +970,6 @@ extern const char kNewUsbBackendName[]; extern const char kNewUsbBackendDescription[]; -extern const char kNotificationIndicatorName[]; -extern const char kNotificationIndicatorDescription[]; - extern const char kNotificationsRevampName[]; extern const char kNotificationsRevampDescription[]; @@ -1151,6 +1151,9 @@ extern const char kPdfXfaFormsName[]; extern const char kPdfXfaFormsDescription[]; +extern const char kBookmarksImprovedSaveFlowName[]; +extern const char kBookmarksImprovedSaveFlowDescription[]; + extern const char kBookmarksRefreshName[]; extern const char kBookmarksRefreshDescription[]; @@ -1586,6 +1589,9 @@ extern const char kWebrtcUseMinMaxVEADimensionsName[]; extern const char kWebrtcUseMinMaxVEADimensionsDescription[]; +extern const char kWebUsbDeviceDetectionName[]; +extern const char kWebUsbDeviceDetectionDescription[]; + extern const char kWebXrForceRuntimeName[]; extern const char kWebXrForceRuntimeDescription[]; @@ -1727,9 +1733,6 @@ extern const char kCriticalPersistedTabDataName[]; extern const char kCriticalPersistedTabDataDescription[]; -extern const char kContextMenuPerformanceInfoAndRemoteHintFetchingName[]; -extern const char kContextMenuPerformanceInfoAndRemoteHintFetchingDescription[]; - extern const char kContextualSearchDebugName[]; extern const char kContextualSearchDebugDescription[];
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc index 9e97644..8fcfc67 100644 --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -238,6 +238,7 @@ &kOfflineIndicatorV2, &kOfflineMeasurementsBackgroundTask, &kPageAnnotationsService, + &kBookmarksImprovedSaveFlow, &kBookmarksRefresh, &kProbabilisticCryptidRenderer, &kQuickActionSearchWidgetAndroid, @@ -652,6 +653,9 @@ const base::Feature kPageAnnotationsService{"PageAnnotationsService", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kBookmarksImprovedSaveFlow{ + "BookmarksImprovedSaveFlow", base::FEATURE_DISABLED_BY_DEFAULT}; + const base::Feature kBookmarksRefresh{"BookmarksRefresh", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h index 9f1412e5..633c2a3 100644 --- a/chrome/browser/flags/android/chrome_feature_list.h +++ b/chrome/browser/flags/android/chrome_feature_list.h
@@ -108,6 +108,7 @@ extern const base::Feature kOfflineIndicatorV2; extern const base::Feature kOfflineMeasurementsBackgroundTask; extern const base::Feature kPageAnnotationsService; +extern const base::Feature kBookmarksImprovedSaveFlow; extern const base::Feature kBookmarksRefresh; extern const base::Feature kProbabilisticCryptidRenderer; extern const base::Feature kQuickActionSearchWidgetAndroid;
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java index bb43df53..af31bbe 100644 --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -420,6 +420,7 @@ public static final String PERMISSION_DELEGATION = "PermissionDelegation"; public static final String PORTALS = "Portals"; public static final String PORTALS_CROSS_ORIGIN = "PortalsCrossOrigin"; + public static final String BOOKMARKS_IMPROVED_SAVE_FLOW = "BookmarksImprovedSaveFlow"; public static final String BOOKMARKS_REFRESH = "BookmarksRefresh"; public static final String PREEMPTIVE_LINK_TO_TEXT_GENERATION = "PreemptiveLinkToTextGeneration";
diff --git a/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc b/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc index e831217..ec48479 100644 --- a/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc +++ b/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc
@@ -630,7 +630,7 @@ // misrepresent it as enabled here (and later ignored when analyzing results), // in order to keep each population at 33%. // - // Alsto note that USE_BACKUP_REF_PTR_FAKE is only used to fake that the + // Also note that USE_BACKUP_REF_PTR_FAKE is only used to fake that the // feature is enabled for the purpose of this Finch setting, while in fact // there are no behavior changes. ChromeMetricsServiceAccessor::RegisterSyntheticFieldTrial( @@ -644,6 +644,22 @@ : "Disabled" #endif // BUILDFLAG(USE_BACKUP_REF_PTR) || BUILDFLAG(USE_BACKUP_REF_PTR_FAKE) ); + + // This synthetic Finch setting reflects the new USE_BACKUP_REF_PTR behavior, + // which simply compiles in the BackupRefPtr support, but keeps it disabled at + // run-time (which can be further enabled via Finch). + // + // Also note that USE_BACKUP_REF_PTR_FAKE is only used to fake that the + // feature is enabled for the purpose of this Finch setting, while in fact + // there are no behavior changes. + ChromeMetricsServiceAccessor::RegisterSyntheticFieldTrial( + "BackupRefPtrSupport", +#if BUILDFLAG(USE_BACKUP_REF_PTR) || BUILDFLAG(USE_BACKUP_REF_PTR_FAKE) + "CompiledIn" +#else + "Disabled" +#endif // BUILDFLAG(USE_BACKUP_REF_PTR) || BUILDFLAG(USE_BACKUP_REF_PTR_FAKE) + ); #endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) #if defined(OS_ANDROID)
diff --git a/chrome/browser/resources/print_preview/BUILD.gn b/chrome/browser/resources/print_preview/BUILD.gn index d221d83..9d84705e 100644 --- a/chrome/browser/resources/print_preview/BUILD.gn +++ b/chrome/browser/resources/print_preview/BUILD.gn
@@ -98,7 +98,7 @@ "ui/highlight_utils.ts", "ui/input_behavior.js", "ui/plugin_proxy.js", - "ui/select_behavior.js", + "ui/select_mixin.ts", "ui/settings_behavior.js", ] @@ -126,7 +126,7 @@ "ui/destination_dialog_css.ts", "ui/destination_list.ts", "ui/destination_list_item.ts", - "ui/destination_select_css.js", + "ui/destination_select_css.ts", "ui/destination_settings.js", "ui/dpi_settings.js", "ui/duplex_settings.js", @@ -155,15 +155,15 @@ if (is_chromeos) { in_files += [ - "ui/destination_dropdown_cros.js", - "ui/destination_select_cros.js", + "ui/destination_dropdown_cros.ts", + "ui/destination_select_cros.ts", "ui/pin_settings.js", "ui/provisional_destination_resolver.ts", "ui/destination_dialog_cros.ts", ] } else { in_files += [ - "ui/destination_select.js", + "ui/destination_select.ts", "ui/link_container.js", "ui/destination_dialog.ts", ] @@ -267,7 +267,7 @@ "ui/destination_dialog_css.ts", "ui/destination_list.ts", "ui/destination_list_item.ts", - "ui/destination_select_css.js", + "ui/destination_select_css.ts", "ui/destination_settings.js", "ui/dpi_settings.js", "ui/duplex_settings.js", @@ -291,7 +291,7 @@ "ui/print_preview_shared_css.js", "ui/print_preview_vars_css.js", "ui/scaling_settings.js", - "ui/select_behavior.js", + "ui/select_mixin.ts", "ui/settings_behavior.js", "ui/settings_section.js", "ui/settings_select.js", @@ -305,15 +305,15 @@ "data/printer_status_cros.ts", "native_layer_cros.ts", "ui/destination_dialog_cros.ts", - "ui/destination_dropdown_cros.js", - "ui/destination_select_cros.js", + "ui/destination_dropdown_cros.ts", + "ui/destination_select_cros.ts", "ui/pin_settings.js", "ui/provisional_destination_resolver.ts", ] } else { in_files += [ "ui/destination_dialog.ts", - "ui/destination_select.js", + "ui/destination_select.ts", "ui/link_container.js", ] }
diff --git a/chrome/browser/resources/print_preview/print_preview.js b/chrome/browser/resources/print_preview/print_preview.js index 57b3a60..afb8bb8 100644 --- a/chrome/browser/resources/print_preview/print_preview.js +++ b/chrome/browser/resources/print_preview/print_preview.js
@@ -69,6 +69,6 @@ export {PreviewAreaState, PrintPreviewPreviewAreaElement} from './ui/preview_area.js'; export {PrintPreviewSearchBoxElement} from './ui/print_preview_search_box.js'; export {PrintPreviewScalingSettingsElement} from './ui/scaling_settings.js'; -export {SelectBehavior} from './ui/select_behavior.js'; +export {SelectMixin} from './ui/select_mixin.js'; export {PrintPreviewSettingsSelectElement, SelectOption} from './ui/settings_select.js'; export {PrintPreviewSidebarElement} from './ui/sidebar.js';
diff --git a/chrome/browser/resources/print_preview/ui/BUILD.gn b/chrome/browser/resources/print_preview/ui/BUILD.gn index db1e7ae1..b7e7a56 100644 --- a/chrome/browser/resources/print_preview/ui/BUILD.gn +++ b/chrome/browser/resources/print_preview/ui/BUILD.gn
@@ -17,7 +17,7 @@ "destination_dialog_css.ts", "destination_list_item.ts", "destination_list.ts", - "destination_select_css.js", + "destination_select_css.ts", "destination_settings.js", "dpi_settings.js", "duplex_settings.js", @@ -47,15 +47,15 @@ if (is_chromeos) { js_files += [ "destination_dialog_cros.ts", - "destination_dropdown_cros.js", - "destination_select_cros.js", + "destination_dropdown_cros.ts", + "destination_select_cros.ts", "pin_settings.js", "provisional_destination_resolver.ts", ] } else { js_files += [ "destination_dialog.ts", - "destination_select.js", + "destination_select.ts", ] } }
diff --git a/chrome/browser/resources/print_preview/ui/color_settings.js b/chrome/browser/resources/print_preview/ui/color_settings.js index c4a7d7d..4027a1d5 100644 --- a/chrome/browser/resources/print_preview/ui/color_settings.js +++ b/chrome/browser/resources/print_preview/ui/color_settings.js
@@ -8,17 +8,17 @@ import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {SelectBehavior, SelectBehaviorInterface} from './select_behavior.js'; +import {SelectMixin, SelectMixinInterface} from './select_mixin.js'; import {SettingsBehavior, SettingsBehaviorInterface} from './settings_behavior.js'; /** * @constructor * @extends {PolymerElement} - * @implements {SelectBehaviorInterface} + * @implements {SelectMixinInterface} * @implements {SettingsBehaviorInterface} */ const PrintPreviewColorSettingsElementBase = - mixinBehaviors([SettingsBehavior, SelectBehavior], PolymerElement); + mixinBehaviors([SettingsBehavior], SelectMixin(PolymerElement)); /** @polymer */ export class PrintPreviewColorSettingsElement extends
diff --git a/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.js b/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.ts similarity index 67% rename from chrome/browser/resources/print_preview/ui/destination_dropdown_cros.js rename to chrome/browser/resources/print_preview/ui/destination_dropdown_cros.ts index 36b1a4f..efb5d34 100644 --- a/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.js +++ b/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.ts
@@ -10,22 +10,23 @@ import './print_preview_vars_css.js'; -import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js'; +import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'; import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {Destination, DestinationOrigin} from '../data/destination.js'; import {ERROR_STRING_KEY_MAP, getPrinterStatusIcon, PrinterStatusReason} from '../data/printer_status_cros.js'; -/** - * @constructor - * @extends {PolymerElement} - * @implements {I18nBehaviorInterface} - */ -const PrintPreviewDestinationDropdownCrosElementBase = - mixinBehaviors([I18nBehavior], PolymerElement); +declare global { + interface HTMLElementEventMap { + 'dropdown-value-selected': CustomEvent<HTMLButtonElement>; + } +} -/** @polymer */ +const PrintPreviewDestinationDropdownCrosElementBase = + mixinBehaviors([I18nBehavior], PolymerElement) as + {new (): PolymerElement & I18nBehavior}; + export class PrintPreviewDestinationDropdownCrosElement extends PrintPreviewDestinationDropdownCrosElementBase { static get is() { @@ -38,16 +39,13 @@ static get properties() { return { - /** @type {!Destination} */ value: Object, - /** @type {!Array<!Destination>} */ itemList: { type: Array, observer: 'enqueueDropdownRefit_', }, - /** @type {boolean} */ disabled: { type: Boolean, value: false, @@ -67,11 +65,9 @@ /** * Index of the highlighted item in the dropdown. - * @private */ highlightedIndex_: Number, - /** @private */ dropdownLength_: { type: Number, computed: 'computeDropdownLength_(itemList, pdfPrinterDisabled, ' + @@ -82,32 +78,37 @@ }; } - constructor() { - super(); + value: Destination; + itemList: Destination[]; + disabled: boolean; + driveDestinationKey: string; + noDestinations: boolean; + pdfPrinterDisabled: boolean; + destinationStatusText: string; + private highlightedIndex_: number; + private dropdownLength_: number; - /** @private {boolean} */ - this.opened_ = false; - } + private opened_: boolean = false; + private dropdownRefitPending_: boolean = false; - /** @override */ ready() { super.ready(); this.addEventListener('mousemove', e => this.onMouseMove_(e)); } - /** @override */ connectedCallback() { super.connectedCallback(); this.updateTabIndex_(); } - /** - * @param {Element} element - * @private - */ - fireDropdownValueSelected_(element) { + focus() { + this.shadowRoot!.querySelector<HTMLElement>( + '#destination-dropdown')!.focus(); + } + + private fireDropdownValueSelected_(element: Element) { this.dispatchEvent(new CustomEvent( 'dropdown-value-selected', {bubbles: true, composed: true, detail: element})); @@ -115,10 +116,9 @@ /** * Enqueues a task to refit the iron-dropdown if it is open. - * @private */ - enqueueDropdownRefit_() { - const dropdown = this.shadowRoot.querySelector('iron-dropdown'); + private enqueueDropdownRefit_() { + const dropdown = this.shadowRoot!.querySelector('iron-dropdown')!; if (!this.dropdownRefitPending_ && dropdown.opened) { this.dropdownRefitPending_ = true; setTimeout(() => { @@ -128,21 +128,19 @@ } } - /** @private */ - openDropdown_() { + private openDropdown_() { if (this.disabled) { return; } this.highlightedIndex_ = this.getButtonListFromDropdown_().findIndex( item => item.value === this.value.key); - this.shadowRoot.querySelector('iron-dropdown').open(); + this.shadowRoot!.querySelector('iron-dropdown')!.open(); this.opened_ = true; } - /** @private */ - closeDropdown_() { - this.shadowRoot.querySelector('iron-dropdown').close(); + private closeDropdown_() { + this.shadowRoot!.querySelector('iron-dropdown')!.close(); this.opened_ = false; this.highlightedIndex_ = -1; } @@ -155,20 +153,19 @@ * @param {!Event} event * @private */ - onMouseMove_(event) { - const item = /** @type {!Element} */ (event.composedPath().find( - elm => elm.classList && elm.classList.contains('list-item'))); + private onMouseMove_(event: Event) { + const item = + (event.composedPath() as HTMLElement[]) + .find(elm => elm.classList && elm.classList.contains('list-item')); if (!item) { return; } - this.highlightedIndex_ = this.getButtonListFromDropdown_().indexOf(item); + this.highlightedIndex_ = + this.getButtonListFromDropdown_().indexOf(item as HTMLButtonElement); } - /** @private */ - onClick_(event) { - const dropdown = - /** @type {!IronDropdownElement} */ ( - this.shadowRoot.querySelector('iron-dropdown')); + private onClick_(event: Event) { + const dropdown = this.shadowRoot!.querySelector('iron-dropdown')!; // Exit if path includes |dropdown| because event will be handled by // onSelect_. if (event.composedPath().includes(dropdown)) { @@ -182,21 +179,13 @@ this.openDropdown_(); } - /** - * @param {!Event} event - * @private - */ - onSelect_(event) { - this.dropdownValueSelected_(/** @type {!Element} */ (event.currentTarget)); + private onSelect_(event: Event) { + this.dropdownValueSelected_(event.currentTarget as Element); } - /** - * @param {!Event} event - * @private - */ - onKeyDown_(event) { + private onKeyDown_(event: KeyboardEvent) { event.stopPropagation(); - const dropdown = this.shadowRoot.querySelector('iron-dropdown'); + const dropdown = this.shadowRoot!.querySelector('iron-dropdown')!; switch (event.code) { case 'ArrowUp': case 'ArrowDown': @@ -221,12 +210,8 @@ } } - /** - * @param {string} eventCode - * @private - */ - onArrowKeyPress_(eventCode) { - const dropdown = this.shadowRoot.querySelector('iron-dropdown'); + private onArrowKeyPress_(eventCode: string) { + const dropdown = this.shadowRoot!.querySelector('iron-dropdown')!; const items = this.getButtonListFromDropdown_(); if (items.length === 0) { return; @@ -256,63 +241,52 @@ } /** - * @param {string} eventCode - * @param {number} currentIndex - * @param {number} numItems - * @return {number} Returns -1 when the next item would be outside the list. - * @private + * @return -1 when the next item would be outside the list. */ - getNextItemIndexInList_(eventCode, currentIndex, numItems) { + private getNextItemIndexInList_( + eventCode: string, currentIndex: number, numItems: number): number { const nextIndex = eventCode === 'ArrowDown' ? currentIndex + 1 : currentIndex - 1; return nextIndex >= 0 && nextIndex < numItems ? nextIndex : -1; } - /** - * @param {Element|undefined} dropdownItem - * @private - */ - dropdownValueSelected_(dropdownItem) { + private dropdownValueSelected_(dropdownItem?: Element) { this.closeDropdown_(); if (dropdownItem) { this.fireDropdownValueSelected_(dropdownItem); } - this.shadowRoot.querySelector('#destination-dropdown').focus(); + this.shadowRoot!.querySelector<HTMLElement>( + '#destination-dropdown')!.focus(); } /** * Returns list of all the visible items in the dropdown. - * @return {!Array<!Element>} - * @private */ - getButtonListFromDropdown_() { + private getButtonListFromDropdown_(): HTMLButtonElement[] { if (!this.shadowRoot) { return []; } - const dropdown = this.shadowRoot.querySelector('iron-dropdown'); - return Array.from(dropdown.getElementsByClassName('list-item')) + const dropdown = this.shadowRoot!.querySelector('iron-dropdown')!; + return Array + .from(dropdown.querySelectorAll<HTMLButtonElement>('.list-item')) .filter(item => !item.hidden); } /** * Sets tabindex to -1 when dropdown is disabled to prevent the dropdown from * being focusable. - * @private */ - updateTabIndex_() { - this.shadowRoot.querySelector('#destination-dropdown') - .setAttribute('tabindex', this.disabled ? '-1' : '0'); + private updateTabIndex_() { + this.shadowRoot!.querySelector('#destination-dropdown')!.setAttribute( + 'tabindex', this.disabled ? '-1' : '0'); } /** * Determines if an item in the dropdown should be highlighted based on the * current value of |highlightedIndex_|. - * @param {string} itemValue - * @return {string} - * @private */ - getHighlightedClass_(itemValue) { + private getHighlightedClass_(itemValue: string): string { const itemToHighlight = this.getButtonListFromDropdown_()[this.highlightedIndex_]; return itemToHighlight && itemValue === itemToHighlight.value ? @@ -323,21 +297,15 @@ /** * Close the dropdown when focus is lost except when an item in the dropdown * is the element that received the focus. - * @param {!Event} event - * @private */ - onBlur_(event) { + private onBlur_(event: FocusEvent) { if (!this.getButtonListFromDropdown_().includes( - /** @type {!Element} */ (event.relatedTarget))) { + (event.relatedTarget as HTMLButtonElement))) { this.closeDropdown_(); } } - /** - * @return {number} - * @private - */ - computeDropdownLength_() { + private computeDropdownLength_(): number { if (this.noDestinations) { return 1; } @@ -357,27 +325,26 @@ return length; } - /** - * @param {!PrinterStatusReason} printerStatusReason - * @return {string} - * @private - */ - getPrinterStatusErrorString_(printerStatusReason) { + private getPrinterStatusErrorString_(printerStatusReason: + PrinterStatusReason): string { const errorStringKey = ERROR_STRING_KEY_MAP.get(printerStatusReason); return errorStringKey ? this.i18n(errorStringKey) : ''; } - /** - * @param {!PrinterStatusReason} printerStatusReason - * @param {boolean} isEnterprisePrinter - * @return {string} - * @private - */ - getPrinterStatusIcon_(printerStatusReason, isEnterprisePrinter) { + private getPrinterStatusIcon_( + printerStatusReason: PrinterStatusReason, + isEnterprisePrinter: boolean): string { return getPrinterStatusIcon(printerStatusReason, isEnterprisePrinter); } } +declare global { + interface HTMLElementTagNameMap { + 'print-preview-destination-dropdown-cros': + PrintPreviewDestinationDropdownCrosElement; + } +} + customElements.define( PrintPreviewDestinationDropdownCrosElement.is, PrintPreviewDestinationDropdownCrosElement);
diff --git a/chrome/browser/resources/print_preview/ui/destination_select.js b/chrome/browser/resources/print_preview/ui/destination_select.ts similarity index 75% rename from chrome/browser/resources/print_preview/ui/destination_select.js rename to chrome/browser/resources/print_preview/ui/destination_select.ts index ad72996..b4a6c822 100644 --- a/chrome/browser/resources/print_preview/ui/destination_select.js +++ b/chrome/browser/resources/print_preview/ui/destination_select.ts
@@ -13,32 +13,26 @@ import 'chrome://resources/cr_elements/md_select_css.m.js'; import 'chrome://resources/js/util.m.js'; import 'chrome://resources/polymer/v3_0/iron-iconset-svg/iron-iconset-svg.js'; -import 'chrome://resources/polymer/v3_0/iron-meta/iron-meta.js'; import './destination_select_css.js'; import './icons.js'; import './print_preview_shared_css.js'; import './throbber_css.js'; import '../strings.m.js'; -import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js'; +import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; -import {Base, html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {IronMeta} from 'chrome://resources/polymer/v3_0/iron-meta/iron-meta.js'; +import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {Destination, DestinationOrigin, GooglePromotedDestinationId, PDF_DESTINATION_KEY, RecentDestination} from '../data/destination.js'; import {getSelectDropdownBackground} from '../print_preview_utils.js'; -import {SelectBehavior, SelectBehaviorInterface} from './select_behavior.js'; +import {SelectMixin, SelectMixinInterface} from './select_mixin.js'; -/** - * @constructor - * @extends {PolymerElement} - * @implements {I18nBehaviorInterface} - * @implements {SelectBehaviorInterface} - */ const PrintPreviewDestinationSelectElementBase = - mixinBehaviors([I18nBehavior, SelectBehavior], PolymerElement); + mixinBehaviors([I18nBehavior], SelectMixin(PolymerElement)) as + {new (): PolymerElement & I18nBehavior & SelectMixinInterface}; -/** @polymer */ export class PrintPreviewDestinationSelectElement extends PrintPreviewDestinationSelectElementBase { static get is() { @@ -55,7 +49,6 @@ dark: Boolean, - /** @type {!Destination} */ destination: Object, disabled: Boolean, @@ -66,16 +59,13 @@ pdfPrinterDisabled: Boolean, - /** @type {!Array<!Destination>} */ recentDestinationList: Array, - /** @private {string} */ pdfDestinationKey_: { type: String, value: PDF_DESTINATION_KEY, }, - /** @private {string} */ statusText_: { type: String, computed: 'computeStatusText_(destination)', @@ -84,16 +74,26 @@ }; } + activeUser: string; + dark: boolean; + destination: Destination; + disabled: boolean; + loaded: boolean; + noDestinations: boolean; + pdfPrinterDisabled: boolean; + recentDestinationList: Destination[]; + private pdfDestinationKey_: string; + private statusText_: string; + private meta_: IronMeta; + constructor() { super(); - /** @private {!IronMetaElement} */ - this.meta_ = /** @type {!IronMetaElement} */ ( - Base.create('iron-meta', {type: 'iconset'})); + this.meta_ = new IronMeta({type: 'iconset', value: undefined}); } focus() { - this.shadowRoot.querySelector('.md-select').focus(); + this.shadowRoot!.querySelector<HTMLElement>('.md-select')!.focus(); } /** Sets the select to the current value of |destination|. */ @@ -105,10 +105,9 @@ * Returns the iconset and icon for the selected printer. If printer details * have not yet been retrieved from the backend, attempts to return an * appropriate icon early based on the printer's sticky information. - * @return {string} The iconset and icon for the current selection. - * @private + * @return The iconset and icon for the current selection. */ - getDestinationIcon_() { + private getDestinationIcon_(): string { if (!this.selectedValue) { return ''; } @@ -143,11 +142,10 @@ } /** - * @return {string} An inline svg corresponding to the icon for the current + * @return An inline svg corresponding to the icon for the current * destination and the image for the dropdown arrow. - * @private */ - getBackgroundImages_() { + private getBackgroundImages_(): string { const icon = this.getDestinationIcon_(); if (!icon) { return ''; @@ -163,17 +161,16 @@ return getSelectDropdownBackground(iconset, iconSetAndIcon[1], this); } - onProcessSelectChange(value) { + onProcessSelectChange(value: string) { this.dispatchEvent(new CustomEvent( 'selected-option-change', {bubbles: true, composed: true, detail: value})); } /** - * @return {string} The connection status text to display. - * @private + * @return The connection status text to display. */ - computeStatusText_() { + private computeStatusText_(): string { // |destination| can be either undefined, or null here. if (!this.destination) { return ''; @@ -191,18 +188,16 @@ return ''; } - /** @private */ - onStatusTextSet_() { - this.shadowRoot.querySelector('.destination-status').innerHTML = + private onStatusTextSet_() { + this.shadowRoot!.querySelector('.destination-status')!.innerHTML = this.statusText_; } /** * Return the options currently visible to the user for testing purposes. - * @return {!NodeList<!Element>} */ - getVisibleItemsForTest() { - return this.shadowRoot.querySelectorAll('option:not([hidden])'); + getVisibleItemsForTest(): NodeListOf<Element> { + return this.shadowRoot!.querySelectorAll('option:not([hidden])'); } }
diff --git a/chrome/browser/resources/print_preview/ui/destination_select_cros.js b/chrome/browser/resources/print_preview/ui/destination_select_cros.ts similarity index 76% rename from chrome/browser/resources/print_preview/ui/destination_select_cros.js rename to chrome/browser/resources/print_preview/ui/destination_select_cros.ts index 7b7ddf4..b5c87df 100644 --- a/chrome/browser/resources/print_preview/ui/destination_select_cros.js +++ b/chrome/browser/resources/print_preview/ui/destination_select_cros.ts
@@ -7,7 +7,6 @@ import 'chrome://resources/js/util.m.js'; import 'chrome://resources/polymer/v3_0/iron-iconset-svg/iron-iconset-svg.js'; import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js'; -import 'chrome://resources/polymer/v3_0/iron-meta/iron-meta.js'; import './destination_dropdown_cros.js'; import './destination_select_css.js'; import './icons.js'; @@ -16,24 +15,18 @@ import '../strings.m.js'; import {assert} from 'chrome://resources/js/assert.m.js'; -import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js'; -import {Base, html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'; +import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {CloudOrigins, Destination, DestinationOrigin, GooglePromotedDestinationId, PDF_DESTINATION_KEY, RecentDestination, SAVE_TO_DRIVE_CROS_DESTINATION_KEY} from '../data/destination.js'; import {ERROR_STRING_KEY_MAP, getPrinterStatusIcon, PrinterStatusReason} from '../data/printer_status_cros.js'; -import {SelectBehavior, SelectBehaviorInterface} from './select_behavior.js'; +import {SelectMixin, SelectMixinInterface} from './select_mixin.js'; -/** - * @constructor - * @extends {PolymerElement} - * @implements {I18nBehaviorInterface} - * @implements {SelectBehaviorInterface} - */ const PrintPreviewDestinationSelectCrosElementBase = - mixinBehaviors([I18nBehavior, SelectBehavior], PolymerElement); + mixinBehaviors([I18nBehavior], SelectMixin(PolymerElement)) as + {new (): I18nBehavior & SelectMixinInterface & PolymerElement}; -/** @polymer */ export class PrintPreviewDestinationSelectCrosElement extends PrintPreviewDestinationSelectCrosElementBase { static get is() { @@ -50,7 +43,6 @@ dark: Boolean, - /** @type {!Destination} */ destination: Object, disabled: Boolean, @@ -63,19 +55,16 @@ pdfPrinterDisabled: Boolean, - /** @type {!Array<!Destination>} */ recentDestinationList: { type: Array, observer: 'onRecentDestinationListChanged_', }, - /** @private {string} */ pdfDestinationKey_: { type: String, value: PDF_DESTINATION_KEY, }, - /** @private {string} */ statusText_: { type: String, computed: @@ -83,15 +72,12 @@ observer: 'onStatusTextSet_', }, - /** @private {string} */ destinationIcon_: { type: String, - computed: - 'computeDestinationIcon_('+ - 'selectedValue, destination, destination.printerStatusReason)', + computed: 'computeDestinationIcon_(' + + 'selectedValue, destination, destination.printerStatusReason)', }, - /** @private */ isCurrentDestinationCrosLocal_: { type: Boolean, computed: 'computeIsCurrentDestinationCrosLocal_(destination)', @@ -100,10 +86,17 @@ }; } + destination: Destination; + pdfPrinterDisabled: boolean; + recentDestinationList: Destination[]; + private pdfDestinationKey_: string; + private statusText_: string; + private destinationIcon_: string; + private isCurrentDestinationCrosLocal_: boolean; + focus() { - this.shadowRoot.querySelector('#dropdown') - .shadowRoot.querySelector('#destination-dropdown') - .focus(); + this.shadowRoot!.querySelector( + 'print-preview-destination-dropdown-cros')!.focus(); } /** Sets the select to the current value of |destination|. */ @@ -115,10 +108,9 @@ * Returns the iconset and icon for the selected printer. If printer details * have not yet been retrieved from the backend, attempts to return an * appropriate icon early based on the printer's sticky information. - * @return {string} The iconset and icon for the current selection. - * @private + * @return The iconset and icon for the current selection. */ - computeDestinationIcon_() { + private computeDestinationIcon_(): string { if (!this.selectedValue) { return ''; } @@ -163,25 +155,17 @@ return 'print-preview:print'; } - /** - * @param {string} value - * @private - */ - fireSelectedOptionChange_(value) { + private fireSelectedOptionChange_(value: string) { this.dispatchEvent(new CustomEvent( 'selected-option-change', {bubbles: true, composed: true, detail: value})); } - onProcessSelectChange(value) { + onProcessSelectChange(value: string) { this.fireSelectedOptionChange_(value); } - /** - * @param {!Event} e - * @private - */ - onDropdownValueSelected_(e) { + private onDropdownValueSelected_(e: CustomEvent<HTMLButtonElement>) { const selectedItem = e.detail; if (!selectedItem || selectedItem.value === this.destination.key) { return; @@ -192,9 +176,8 @@ /** * Send a printer status request for any new destination in the dropdown. - * @private */ - onRecentDestinationListChanged_() { + private onRecentDestinationListChanged_() { for (const destination of this.recentDestinationList) { if (!destination || destination.origin !== DestinationOrigin.CROS) { continue; @@ -208,10 +191,8 @@ /** * Check if the printer is currently in the dropdown then update its status * icon if it's present. - * @param {string} destinationKey - * @private */ - onPrinterStatusReceived_(destinationKey) { + private onPrinterStatusReceived_(destinationKey: string) { const indexFound = this.recentDestinationList.findIndex(destination => { return destination.key === destinationKey; }); @@ -232,11 +213,10 @@ } /** - * @return {string} An error status for the current destination. If no error + * @return An error status for the current destination. If no error * status exists, an empty string. - * @private */ - computeStatusText_() { + private computeStatusText_(): string { // |destination| can be either undefined, or null here. if (!this.destination) { return ''; @@ -258,7 +238,7 @@ } const printerStatusReason = this.destination.printerStatusReason; - if (!printerStatusReason || + if (printerStatusReason === null || printerStatusReason === PrinterStatusReason.NO_ERROR || printerStatusReason === PrinterStatusReason.UNKNOWN_REASON) { return ''; @@ -267,38 +247,29 @@ return this.getErrorString_(printerStatusReason); } - /** @private */ - onStatusTextSet_() { - this.shadowRoot.querySelector('#statusText').innerHTML = this.statusText_; + private onStatusTextSet_() { + this.shadowRoot!.querySelector('#statusText')!.innerHTML = this.statusText_; } - /** - * @param {!PrinterStatusReason} printerStatusReason - * @return {!string} - * @private - */ - getErrorString_(printerStatusReason) { + private getErrorString_(printerStatusReason: PrinterStatusReason): string { const errorStringKey = ERROR_STRING_KEY_MAP.get(printerStatusReason); return errorStringKey ? this.i18n(errorStringKey) : ''; } /** * True when the currently selected destination is a CrOS local printer. - * @return {boolean} - * @private */ - computeIsCurrentDestinationCrosLocal_() { + private computeIsCurrentDestinationCrosLocal_(): boolean { return this.destination && this.destination.origin === DestinationOrigin.CROS; } /** * Return the options currently visible to the user for testing purposes. - * @return {!Array<!Element>} */ - getVisibleItemsForTest() { - return this.shadowRoot.querySelector('#dropdown') - .shadowRoot.querySelectorAll('.list-item:not([hidden])'); + getVisibleItemsForTest(): NodeListOf<Element> { + return this.shadowRoot!.querySelector('#dropdown')!.shadowRoot! + .querySelectorAll('.list-item:not([hidden])'); } }
diff --git a/chrome/browser/resources/print_preview/ui/destination_select_css.js b/chrome/browser/resources/print_preview/ui/destination_select_css.ts similarity index 100% rename from chrome/browser/resources/print_preview/ui/destination_select_css.js rename to chrome/browser/resources/print_preview/ui/destination_select_css.ts
diff --git a/chrome/browser/resources/print_preview/ui/duplex_settings.js b/chrome/browser/resources/print_preview/ui/duplex_settings.js index c1c57b5b..536242a 100644 --- a/chrome/browser/resources/print_preview/ui/duplex_settings.js +++ b/chrome/browser/resources/print_preview/ui/duplex_settings.js
@@ -16,17 +16,17 @@ import {DuplexMode} from '../data/model.js'; import {getSelectDropdownBackground} from '../print_preview_utils.js'; -import {SelectBehavior, SelectBehaviorInterface} from './select_behavior.js'; +import {SelectMixin, SelectMixinInterface} from './select_mixin.js'; import {SettingsBehavior, SettingsBehaviorInterface} from './settings_behavior.js'; /** * @constructor * @extends {PolymerElement} * @implements {SettingsBehaviorInterface} - * @implements {SelectBehaviorInterface} + * @implements {SelectMixinInterface} */ const PrintPreviewDuplexSettingsElementBase = - mixinBehaviors([SettingsBehavior, SelectBehavior], PolymerElement); + mixinBehaviors([SettingsBehavior], SelectMixin(PolymerElement)); /** @polymer */ export class PrintPreviewDuplexSettingsElement extends
diff --git a/chrome/browser/resources/print_preview/ui/layout_settings.js b/chrome/browser/resources/print_preview/ui/layout_settings.js index c027f10..868fbc6 100644 --- a/chrome/browser/resources/print_preview/ui/layout_settings.js +++ b/chrome/browser/resources/print_preview/ui/layout_settings.js
@@ -8,7 +8,7 @@ import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {SelectBehavior, SelectBehaviorInterface} from './select_behavior.js'; +import {SelectMixin, SelectMixinInterface} from './select_mixin.js'; import {SettingsBehavior, SettingsBehaviorInterface} from './settings_behavior.js'; @@ -16,10 +16,10 @@ * @constructor * @extends {PolymerElement} * @implements {SettingsBehaviorInterface} - * @implements {SelectBehaviorInterface} + * @implements {SelectMixinInterface} */ const PrintPreviewLayoutSettingsElementBase = - mixinBehaviors([SettingsBehavior, SelectBehavior], PolymerElement); + mixinBehaviors([SettingsBehavior], SelectMixin(PolymerElement)); /** @polymer */ export class PrintPreviewLayoutSettingsElement extends
diff --git a/chrome/browser/resources/print_preview/ui/margins_settings.js b/chrome/browser/resources/print_preview/ui/margins_settings.js index ca2c239..49eaaa4f0 100644 --- a/chrome/browser/resources/print_preview/ui/margins_settings.js +++ b/chrome/browser/resources/print_preview/ui/margins_settings.js
@@ -11,17 +11,17 @@ import {MarginsType} from '../data/margins.js'; import {State} from '../data/state.js'; -import {SelectBehavior, SelectBehaviorInterface} from './select_behavior.js'; +import {SelectMixin, SelectMixinInterface} from './select_mixin.js'; import {SettingsBehavior, SettingsBehaviorInterface} from './settings_behavior.js'; /** * @constructor * @extends {PolymerElement} - * @implements {SelectBehaviorInterface} + * @implements {SelectMixinInterface} * @implements {SettingsBehaviorInterface} */ const PrintPreviewMarginsSettingsElementBase = - mixinBehaviors([SettingsBehavior, SelectBehavior], PolymerElement); + mixinBehaviors([SettingsBehavior], SelectMixin(PolymerElement)); /** @polymer */ export class PrintPreviewMarginsSettingsElement extends
diff --git a/chrome/browser/resources/print_preview/ui/pages_per_sheet_settings.js b/chrome/browser/resources/print_preview/ui/pages_per_sheet_settings.js index 8e9c538..d60620d 100644 --- a/chrome/browser/resources/print_preview/ui/pages_per_sheet_settings.js +++ b/chrome/browser/resources/print_preview/ui/pages_per_sheet_settings.js
@@ -10,17 +10,17 @@ import {MarginsType} from '../data/margins.js'; -import {SelectBehavior, SelectBehaviorInterface} from './select_behavior.js'; +import {SelectMixin, SelectMixinInterface} from './select_mixin.js'; import {SettingsBehavior, SettingsBehaviorInterface} from './settings_behavior.js'; /** * @constructor * @extends {PolymerElement} - * @implements {SelectBehaviorInterface} + * @implements {SelectMixinInterface} * @implements {SettingsBehaviorInterface} */ const PrintPreviewPagesPerSheetSettingsElementBase = - mixinBehaviors([SettingsBehavior, SelectBehavior], PolymerElement); + mixinBehaviors([SettingsBehavior], SelectMixin(PolymerElement)); /** @polymer */ export class PrintPreviewPagesPerSheetSettingsElement extends
diff --git a/chrome/browser/resources/print_preview/ui/pages_settings.js b/chrome/browser/resources/print_preview/ui/pages_settings.js index 9956eae..87615dba 100644 --- a/chrome/browser/resources/print_preview/ui/pages_settings.js +++ b/chrome/browser/resources/print_preview/ui/pages_settings.js
@@ -17,7 +17,7 @@ import {areRangesEqual} from '../print_preview_utils.js'; import {InputBehavior, InputBehaviorInterface} from './input_behavior.js'; -import {SelectBehavior, SelectBehaviorInterface} from './select_behavior.js'; +import {SelectMixin, SelectMixinInterface} from './select_mixin.js'; import {SettingsBehavior, SettingsBehaviorInterface} from './settings_behavior.js'; /** @enum {number} */ @@ -56,13 +56,13 @@ * @constructor * @extends {PolymerElement} * @implements {InputBehaviorInterface} - * @implements {SelectBehaviorInterface} + * @implements {SelectMixinInterface} * @implements {SettingsBehaviorInterface} * @implements {WebUIListenerBehaviorInterface} */ const PrintPreviewPagesSettingsElementBase = mixinBehaviors( - [SettingsBehavior, InputBehavior, SelectBehavior, WebUIListenerBehavior], - PolymerElement); + [SettingsBehavior, InputBehavior, WebUIListenerBehavior], + SelectMixin(PolymerElement)); /** @polymer */ export class PrintPreviewPagesSettingsElement extends
diff --git a/chrome/browser/resources/print_preview/ui/scaling_settings.js b/chrome/browser/resources/print_preview/ui/scaling_settings.js index 1cfd4161..d19cdb2 100644 --- a/chrome/browser/resources/print_preview/ui/scaling_settings.js +++ b/chrome/browser/resources/print_preview/ui/scaling_settings.js
@@ -12,7 +12,7 @@ import {ScalingType} from '../data/scaling.js'; -import {SelectBehavior, SelectBehaviorInterface} from './select_behavior.js'; +import {SelectMixin, SelectMixinInterface} from './select_mixin.js'; import {SettingsBehavior, SettingsBehaviorInterface} from './settings_behavior.js'; /* @@ -24,11 +24,11 @@ /** * @constructor * @extends {PolymerElement} - * @implements {SelectBehaviorInterface} + * @implements {SelectMixinInterface} * @implements {SettingsBehaviorInterface} */ const PrintPreviewScalingSettingsElementBase = - mixinBehaviors([SettingsBehavior, SelectBehavior], PolymerElement); + mixinBehaviors([SettingsBehavior], SelectMixin(PolymerElement)); /** @polymer */ export class PrintPreviewScalingSettingsElement extends
diff --git a/chrome/browser/resources/print_preview/ui/select_behavior.js b/chrome/browser/resources/print_preview/ui/select_behavior.js deleted file mode 100644 index 92bc3d6..0000000 --- a/chrome/browser/resources/print_preview/ui/select_behavior.js +++ /dev/null
@@ -1,63 +0,0 @@ -// 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. -import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; - -/** - * Helper functions for a select with timeout. Implemented by select settings - * sections, so that the preview does not immediately begin generating and - * freeze the dropdown when the value is changed. - * Assumes that the elements implementing this behavior have no more than one - * select element. - * @polymerBehavior - */ -export const SelectBehavior = { - properties: { - selectedValue: { - type: String, - observer: 'onSelectedValueChange_', - }, - }, - - /** - * @param {string} current - * @param {?string} previous - * @private - */ - onSelectedValueChange_(current, previous) { - // Don't trigger an extra preview request at startup. - if (previous === undefined) { - return; - } - - this.debounce('select-change', () => { - if (this.isConnected) { - this.onProcessSelectChange(this.selectedValue); - // For testing only - this.fire('process-select-change'); - } - }, 100); - }, - - /** - * Should be overridden by elements using this behavior to receive select - * value updates. - * @param {string} value The new select value to process. - */ - onProcessSelectChange(value) {}, -}; - -/** @interface */ -export class SelectBehaviorInterface { - constructor() { - /** @type {string} */ - this.selectedValue; - } - - /** - * Should be overridden by elements using this behavior to receive select - * value updates. - * @param {string} value The new select value to process. - */ - onProcessSelectChange(value) {} -}
diff --git a/chrome/browser/resources/print_preview/ui/select_mixin.ts b/chrome/browser/resources/print_preview/ui/select_mixin.ts new file mode 100644 index 0000000..0ada172 --- /dev/null +++ b/chrome/browser/resources/print_preview/ui/select_mixin.ts
@@ -0,0 +1,70 @@ +// 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. +import {Debouncer, dedupingMixin, PolymerElement, timeOut} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +/** + * Helper functions for a select with timeout. Implemented by select settings + * sections, so that the preview does not immediately begin generating and + * freeze the dropdown when the value is changed. + * Assumes that the elements using this mixin have no more than one select + * element. + */ + +type Constructor<T> = new (...args: any[]) => T; + +export const SelectMixin = dedupingMixin( + <T extends Constructor<PolymerElement>>(superClass: T): T& + Constructor<SelectMixinInterface> => { + class SelectMixin extends superClass { + static get properties() { + return { + selectedValue: { + type: String, + observer: 'onSelectedValueChange_', + }, + }; + } + + selectedValue: string; + private debouncer_: Debouncer|null = null; + + private onSelectedValueChange_( + _current: string, previous: string|null|undefined) { + // Don't trigger an extra preview request at startup. + if (previous === undefined) { + return; + } + + this.debouncer_ = Debouncer.debounce( + this.debouncer_, timeOut.after(100), + () => this.callProcessSelectChange_()); + } + + private callProcessSelectChange_() { + if (!this.isConnected) { + return; + } + + this.onProcessSelectChange(this.selectedValue); + // For testing only + this.dispatchEvent(new CustomEvent( + 'process-select-change', {bubbles: true, composed: true})); + } + + onProcessSelectChange(_value: string) {} + } + + return SelectMixin; + }); + +export interface SelectMixinInterface { + selectedValue: string; + + /** + * Should be overridden by elements using this mixin to receive select + * value updates. + * @param value The new select value to process. + */ + onProcessSelectChange(value: string): void; +}
diff --git a/chrome/browser/resources/print_preview/ui/settings_select.js b/chrome/browser/resources/print_preview/ui/settings_select.js index 8344d9f..423c2e9d 100644 --- a/chrome/browser/resources/print_preview/ui/settings_select.js +++ b/chrome/browser/resources/print_preview/ui/settings_select.js
@@ -10,7 +10,7 @@ import {getStringForCurrentLocale} from '../print_preview_utils.js'; -import {SelectBehavior, SelectBehaviorInterface} from './select_behavior.js'; +import {SelectMixin, SelectMixinInterface} from './select_mixin.js'; import {SettingsBehavior, SettingsBehaviorInterface} from './settings_behavior.js'; /** @@ -28,10 +28,10 @@ * @constructor * @extends {PolymerElement} * @implements {SettingsBehaviorInterface} - * @implements {SelectBehaviorInterface} + * @implements {SelectMixinInterface} */ const PrintPreviewSettingsSelectElementBase = - mixinBehaviors([SettingsBehavior, SelectBehavior], PolymerElement); + mixinBehaviors([SettingsBehavior], SelectMixin(PolymerElement)); /** @polymer */ export class PrintPreviewSettingsSelectElement extends
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_impl_win.cc b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_impl_win.cc index aa58459..346c9e7 100644 --- a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_impl_win.cc +++ b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_impl_win.cc
@@ -123,11 +123,6 @@ : ChromeCleanerController::IdleReason::kConnectionLost; } -void RecordScannerLogsAcceptanceHistogram(bool logs_accepted) { - UMA_HISTOGRAM_BOOLEAN("SoftwareReporter.ScannerLogsAcceptance", - logs_accepted); -} - void RecordCleanerLogsAcceptanceHistogram(bool logs_accepted) { UMA_HISTOGRAM_BOOLEAN("SoftwareReporter.CleanerLogsAcceptance", logs_accepted); @@ -145,10 +140,6 @@ static_cast<int>(SwReporterInvocationType::kMax)); } -void RecordOnDemandUpdateRequiredHistogram(bool value) { - UMA_HISTOGRAM_BOOLEAN("SoftwareReporter.OnDemandUpdateRequired", value); -} - } // namespace ChromeCleanerControllerDelegate::ChromeCleanerControllerDelegate() = default; @@ -383,7 +374,6 @@ SwReporterInvocationType::kUserInitiatedWithLogsDisallowed); const bool logs_enabled = this->logs_enabled(profile); - RecordScannerLogsAcceptanceHistogram(logs_enabled); SwReporterInvocationType invocation_type = logs_enabled ? SwReporterInvocationType::kUserInitiatedWithLogsAllowed @@ -399,8 +389,6 @@ // The invocations will be modified by the |ReporterRunner|. // Give it a copy to keep the cached invocations pristine. std::move(copied_sequence))); - - RecordOnDemandUpdateRequiredHistogram(false); } else { pending_invocation_type_ = invocation_type; OnReporterSequenceStarted(); @@ -415,8 +403,6 @@ base::BindOnce(&ChromeCleanerController::OnReporterSequenceDone, base::Unretained(this), SwReporterInvocationResult::kComponentNotAvailable)); - - RecordOnDemandUpdateRequiredHistogram(true); } }
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_dialog_controller_impl_win.cc b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_dialog_controller_impl_win.cc index 93bdafe..a51f9fc 100644 --- a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_dialog_controller_impl_win.cc +++ b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_dialog_controller_impl_win.cc
@@ -191,8 +191,6 @@ return; } ShowChromeCleanerPrompt(); - RecordPromptShownWithTypeHistogram( - PromptTypeHistogramValue::PROMPT_TYPE_ON_TRANSITION_TO_INFECTED_STATE); } void ChromeCleanerDialogControllerImpl::OnCleaning( @@ -215,8 +213,6 @@ browser_ = browser; ShowChromeCleanerPrompt(); - RecordPromptShownWithTypeHistogram( - PromptTypeHistogramValue::PROMPT_TYPE_ON_BROWSER_WINDOW_AVAILABLE); prompt_pending_ = false; BrowserList::RemoveObserver(this); }
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/settings_resetter_win.cc b/chrome/browser/safe_browsing/chrome_cleaner/settings_resetter_win.cc index b2db33b..a86551cb 100644 --- a/chrome/browser/safe_browsing/chrome_cleaner/settings_resetter_win.cc +++ b/chrome/browser/safe_browsing/chrome_cleaner/settings_resetter_win.cc
@@ -19,6 +19,7 @@ #include "base/sequence_checker.h" #include "base/synchronization/lock.h" #include "base/win/registry.h" +#include "build/build_config.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/profile_resetter/profile_resetter.h" #include "chrome/browser/profiles/profile.h" @@ -220,7 +221,6 @@ DCHECK(profile); RecordResetPending(true, profile); - UMA_HISTOGRAM_BOOLEAN("SoftwareReporter.TaggedProfileForResetting", true); } void PostCleanupSettingsResetter::ResetTaggedProfiles(
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.cc b/chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.cc index 959c0e7..00ae150 100644 --- a/chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.cc +++ b/chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.cc
@@ -89,11 +89,6 @@ return kSRTPromptGroupNameParam.Get(); } -void RecordPromptShownWithTypeHistogram(PromptTypeHistogramValue value) { - UMA_HISTOGRAM_ENUMERATION("SoftwareReporter.PromptShownWithType", value, - PROMPT_TYPE_MAX); -} - void RecordPromptNotShownWithReasonHistogram( NoPromptReasonHistogramValue value) { UMA_HISTOGRAM_ENUMERATION("SoftwareReporter.NoPromptReason", value,
diff --git a/chrome/browser/share/share_submenu_model.cc b/chrome/browser/share/share_submenu_model.cc index 527c306a..aa06bfd 100644 --- a/chrome/browser/share/share_submenu_model.cc +++ b/chrome/browser/share/share_submenu_model.cc
@@ -61,7 +61,7 @@ const base::Feature kShareMenu{ "ShareMenu", - base::FEATURE_DISABLED_BY_DEFAULT, + base::FEATURE_ENABLED_BY_DEFAULT, }; ShareSubmenuModel::ShareSubmenuModel(
diff --git a/chrome/browser/ui/ash/projector/projector_client_impl.cc b/chrome/browser/ui/ash/projector/projector_client_impl.cc index fb9bfc5..ed2a5b6 100644 --- a/chrome/browser/ui/ash/projector/projector_client_impl.cc +++ b/chrome/browser/ui/ash/projector/projector_client_impl.cc
@@ -30,6 +30,9 @@ ProjectorClientImpl::ProjectorClientImpl(ash::ProjectorController* controller) : controller_(controller) { controller_->SetClient(this); + if (ash::ProjectorController::AreExtendedProjectorFeaturesDisabled()) + return; + bool recognition_available = OnDeviceSpeechRecognizer::IsOnDeviceSpeechRecognizerAvailable( kEnglishLanguageCode) || @@ -115,6 +118,9 @@ bool ProjectorClientImpl::GetDriveFsMountPointPath( base::FilePath* result) const { + // TODO(b/197164300) Implement persisting screencasts in this mode by + // creating a temp folder for testing purposes + if (!IsDriveFsMounted()) return false; drive::DriveIntegrationService* integration_service =
diff --git a/chrome/browser/ui/autofill/payments/card_unmask_authentication_selection_dialog_controller_impl.cc b/chrome/browser/ui/autofill/payments/card_unmask_authentication_selection_dialog_controller_impl.cc index 3dffbf8..8d80c07 100644 --- a/chrome/browser/ui/autofill/payments/card_unmask_authentication_selection_dialog_controller_impl.cc +++ b/chrome/browser/ui/autofill/payments/card_unmask_authentication_selection_dialog_controller_impl.cc
@@ -20,12 +20,13 @@ CardUnmaskAuthenticationSelectionDialogControllerImpl:: ~CardUnmaskAuthenticationSelectionDialogControllerImpl() { - // This part of code is executed only if browser window is closed when the + // This part of code is executed only if the browser window is closed when the // dialog is visible. In this case the controller is destroyed before // CardUnmaskAuthenticationSelectionDialogViewImpl::dtor() is called, - // but the reference to controller is not reset. Need to reset via - // CardUnmaskAuthenticationSelectionDialogView::CloseDialog() to avoid a - // crash. + // but the reference to controller is not reset. This reference needs to be + // reset via + // CardUnmaskAuthenticationSelectionDialogView::OnControllerDestroying() to + // avoid a crash. if (dialog_view_) dialog_view_->OnControllerDestroying(); }
diff --git a/chrome/browser/ui/messages/android/java/res/layout/snackbar.xml b/chrome/browser/ui/messages/android/java/res/layout/snackbar.xml index 6303c20..a254ba4 100644 --- a/chrome/browser/ui/messages/android/java/res/layout/snackbar.xml +++ b/chrome/browser/ui/messages/android/java/res/layout/snackbar.xml
@@ -65,7 +65,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_gravity="start|center_vertical" - android:layout_marginStart="24dp" + android:layout_marginStart="@dimen/snackbar_text_view_margin" android:layout_marginTop="14dp" android:layout_marginBottom="14dp" android:layout_weight="1"
diff --git a/chrome/browser/ui/messages/android/java/res/values/dimens.xml b/chrome/browser/ui/messages/android/java/res/values/dimens.xml index 03cc8738..29ad6b0 100644 --- a/chrome/browser/ui/messages/android/java/res/values/dimens.xml +++ b/chrome/browser/ui/messages/android/java/res/values/dimens.xml
@@ -9,4 +9,5 @@ <dimen name="snackbar_width_tablet">450dp</dimen> <dimen name="snackbar_margin_tablet">24dp</dimen> <dimen name="snackbar_shadow_height">8dp</dimen> + <dimen name="snackbar_text_view_margin">24dp</dimen> </resources>
diff --git a/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarView.java b/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarView.java index d1909c3..b3adb456 100644 --- a/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarView.java +++ b/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarView.java
@@ -22,6 +22,7 @@ import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.ImageView; +import android.widget.LinearLayout.LayoutParams; import android.widget.TextView; import androidx.annotation.Nullable; @@ -312,8 +313,21 @@ mActionButtonView.setVisibility(View.VISIBLE); mActionButtonView.setContentDescription(snackbar.getActionText()); setViewText(mActionButtonView, snackbar.getActionText(), animate); + // Set the end margin on the message view to 0 when there is action text. + if (mMessageView.getLayoutParams() instanceof LayoutParams) { + LayoutParams lp = (LayoutParams) mMessageView.getLayoutParams(); + lp.setMarginEnd(0); + mMessageView.setLayoutParams(lp); + } } else { mActionButtonView.setVisibility(View.GONE); + // Set a non-zero end margin on the message view when there is no action text. + if (mMessageView.getLayoutParams() instanceof LayoutParams) { + LayoutParams lp = (LayoutParams) mMessageView.getLayoutParams(); + lp.setMarginEnd(mParent.getResources().getDimensionPixelSize( + R.dimen.snackbar_text_view_margin)); + mMessageView.setLayoutParams(lp); + } } Drawable profileImage = snackbar.getProfileImage(); if (profileImage != null) {
diff --git a/chrome/browser/ui/search/omnibox_utils.cc b/chrome/browser/ui/search/omnibox_utils.cc index c9033bb6..5a8a491 100644 --- a/chrome/browser/ui/search/omnibox_utils.cc +++ b/chrome/browser/ui/search/omnibox_utils.cc
@@ -48,8 +48,9 @@ // Remove focus only if the popup is closed. This will prevent someone // from changing the omnibox value and closing the popup without user // interaction. - if (!omnibox_view->model()->popup_model()->IsOpen()) + if (!omnibox_view->model()->PopupIsOpen()) { web_contents->Focus(); + } } }
diff --git a/chrome/browser/ui/views/autofill/payments/card_unmask_authentication_selection_dialog_view_impl.cc b/chrome/browser/ui/views/autofill/payments/card_unmask_authentication_selection_dialog_view_impl.cc index cfbfb8f..08d0f9d 100644 --- a/chrome/browser/ui/views/autofill/payments/card_unmask_authentication_selection_dialog_view_impl.cc +++ b/chrome/browser/ui/views/autofill/payments/card_unmask_authentication_selection_dialog_view_impl.cc
@@ -39,6 +39,7 @@ CardUnmaskAuthenticationSelectionDialogViewImpl:: ~CardUnmaskAuthenticationSelectionDialogViewImpl() { + // Inform `controller_` of the dialog's destruction. if (controller_) controller_->OnDialogClosed(); }
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc index 5ea4422..1af9a97 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_view.cc +++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -912,7 +912,7 @@ // Also hide them if the popup is open for any other reason, e.g. ZeroSuggest. // The page action icons are not relevant to the displayed suggestions. - return omnibox_view_->model()->popup_model()->IsOpen(); + return omnibox_view_->model()->PopupIsOpen(); } // static @@ -1057,7 +1057,7 @@ OmniboxPopupView* LocationBarView::GetOmniboxPopupView() { DCHECK(IsInitialized()); - return omnibox_view_->model()->popup_model()->view(); + return omnibox_view_->model()->get_popup_view(); } void LocationBarView::KeywordHintViewPressed(const ui::Event& event) {
diff --git a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc index 2762a9f..66310c1 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
@@ -222,27 +222,22 @@ DCHECK(HasMatchAt(index)); OmniboxPopupSelection::LineState line_state = OmniboxPopupSelection::NORMAL; - edit_model_->popup_model()->SetSelection( - OmniboxPopupSelection(index, line_state)); - OnPropertyChanged(edit_model_->popup_model(), views::kPropertyEffectsNone); + edit_model_->SetPopupSelection(OmniboxPopupSelection(index, line_state)); + OnPropertyChanged(edit_model_, views::kPropertyEffectsNone); } size_t OmniboxPopupContentsView::GetSelectedIndex() const { - return edit_model_->popup_model()->selected_line(); + return GetSelection().line; } OmniboxPopupSelection OmniboxPopupContentsView::GetSelection() const { - // TODO(orinj): This should get full selection straight from popup model - // and should be the only selection method; eliminate others and - // reconcile with test code overrides of `GetSelectedIndex` and - // `SetSelectedIndex`. - return OmniboxPopupSelection( - GetSelectedIndex(), edit_model_->popup_model()->selected_line_state()); + return edit_model_->GetPopupSelection(); } void OmniboxPopupContentsView::UnselectButton() { - edit_model_->popup_model()->SetSelectedLineState( - OmniboxPopupSelection::NORMAL); + OmniboxPopupSelection selection = edit_model_->GetPopupSelection(); + selection.state = OmniboxPopupSelection::NORMAL; + edit_model_->SetPopupSelection(selection); } OmniboxResultView* OmniboxPopupContentsView::result_view_at(size_t i) { @@ -412,8 +407,7 @@ pref_service, match.suggestion_group_id.value()); result_view->SetVisible(!match_hidden); - const SkBitmap* bitmap = - edit_model_->popup_model()->RichSuggestionBitmapAt(i); + const SkBitmap* bitmap = edit_model_->GetPopupRichSuggestionBitmap(i); if (bitmap) { result_view->SetRichSuggestionImage( gfx::ImageSkia::CreateFrom1xBitmap(*bitmap));
diff --git a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h index a9dc2bc..d3edc46 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h +++ b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h
@@ -61,7 +61,7 @@ virtual size_t GetSelectedIndex() const; // Returns current popup selection (includes line index). - OmniboxPopupSelection GetSelection() const; + virtual OmniboxPopupSelection GetSelection() const; // Called by the active result view to inform model (due to mouse event). void UnselectButton();
diff --git a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc index 9315280..659cb4a 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
@@ -432,7 +432,7 @@ void OmniboxResultView::ButtonPressed(OmniboxPopupSelection::LineState state, const ui::Event& event) { - model_->popup_model()->TriggerSelectionAction( + model_->TriggerPopupSelectionAction( OmniboxPopupSelection(model_index_, state), event.time_stamp()); } @@ -500,11 +500,10 @@ // The selected match can have a special name, e.g. when is one or more // buttons that can be tabbed to. std::u16string label = - is_selected - ? model_->popup_model()->GetAccessibilityLabelForCurrentSelection( - raw_match.contents, false) - : AutocompleteMatchType::ToAccessibilityLabel(raw_match, - raw_match.contents); + is_selected ? model_->GetPopupAccessibilityLabelForCurrentSelection( + raw_match.contents, false) + : AutocompleteMatchType::ToAccessibilityLabel( + raw_match, raw_match.contents); node_data->SetName(label); } @@ -562,7 +561,7 @@ void OmniboxResultView::UpdateRemoveSuggestionVisibility() { bool old_visibility = remove_suggestion_button_->GetVisible(); bool new_visibility = - model_->popup_model()->IsControlPresentOnMatch(OmniboxPopupSelection( + model_->IsPopupControlPresentOnMatch(OmniboxPopupSelection( model_index_, OmniboxPopupSelection::FOCUSED_BUTTON_REMOVE_SUGGESTION)) && (GetMatchSelected() || IsMouseHovered());
diff --git a/chrome/browser/ui/views/omnibox/omnibox_result_view_unittest.cc b/chrome/browser/ui/views/omnibox/omnibox_result_view_unittest.cc index 5e80712..9b144b9b 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_result_view_unittest.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_result_view_unittest.cc
@@ -37,18 +37,20 @@ /*omnibox_view=*/nullptr, edit_model, /*location_bar_view=*/nullptr), - selected_index_(0) {} + selection_(OmniboxPopupSelection(0, OmniboxPopupSelection::NORMAL)) {} TestOmniboxPopupContentsView(const TestOmniboxPopupContentsView&) = delete; TestOmniboxPopupContentsView& operator=(const TestOmniboxPopupContentsView&) = delete; - void SetSelectedIndex(size_t index) override { selected_index_ = index; } + void SetSelectedIndex(size_t index) override { selection_.line = index; } - size_t GetSelectedIndex() const override { return selected_index_; } + size_t GetSelectedIndex() const override { return selection_.line; } + + OmniboxPopupSelection GetSelection() const override { return selection_; } private: - size_t selected_index_; + OmniboxPopupSelection selection_; }; } // namespace
diff --git a/chrome/browser/ui/views/omnibox/omnibox_row_view.cc b/chrome/browser/ui/views/omnibox/omnibox_row_view.cc index 70cd11c3..31fc4f0 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_row_view.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_row_view.cc
@@ -72,8 +72,7 @@ views::FocusRing::Get(header_toggle_button_) ->SetHasFocusPredicate([&](View* view) { return view->GetVisible() && - row_view_->model_->popup_model()->selection() == - GetHeaderSelection(); + row_view_->model_->GetPopupSelection() == GetHeaderSelection(); }); if (row_view_->pref_service_) { @@ -125,8 +124,7 @@ return true; } void OnMouseReleased(const ui::MouseEvent& event) override { - row_view_->model_->popup_model()->TriggerSelectionAction( - GetHeaderSelection()); + row_view_->model_->TriggerPopupSelectionAction(GetHeaderSelection()); } void OnMouseEntered(const ui::MouseEvent& event) override { UpdateUI(); } void OnMouseExited(const ui::MouseEvent& event) override { UpdateUI(); } @@ -150,7 +148,7 @@ // Updates the UI state for the new hover or selection state. void UpdateUI() { OmniboxPartState part_state = OmniboxPartState::NORMAL; - if (row_view_->model_->popup_model()->selection() == GetHeaderSelection()) { + if (row_view_->model_->GetPopupSelection() == GetHeaderSelection()) { part_state = OmniboxPartState::SELECTED; } else if (IsMouseHovered()) { part_state = OmniboxPartState::HOVERED; @@ -200,8 +198,7 @@ private: void HeaderToggleButtonPressed() { - row_view_->model_->popup_model()->TriggerSelectionAction( - GetHeaderSelection()); + row_view_->model_->TriggerPopupSelectionAction(GetHeaderSelection()); // The PrefChangeRegistrar will update the actual button toggle state. } @@ -350,8 +347,8 @@ } views::View* OmniboxRowView::GetActiveAuxiliaryButtonForAccessibility() const { - DCHECK(model_->popup_model()->selection().IsButtonFocused()); - if (model_->popup_model()->selected_line_state() == + DCHECK(model_->GetPopupSelection().IsButtonFocused()); + if (model_->GetPopupSelection().state == OmniboxPopupSelection::FOCUSED_BUTTON_HEADER) { return header_view_->header_toggle_button(); }
diff --git a/chrome/browser/ui/views/omnibox/omnibox_suggestion_button_row_view.cc b/chrome/browser/ui/views/omnibox/omnibox_suggestion_button_row_view.cc index 26c0343..30594bf 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_suggestion_button_row_view.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_suggestion_button_row_view.cc
@@ -265,7 +265,7 @@ !OmniboxFieldTrial::IsKeywordSearchButtonEnabled()) { button->SetVisible(false); } else { - button->SetVisible(model_->popup_model()->IsControlPresentOnMatch( + button->SetVisible(model_->IsPopupControlPresentOnMatch( OmniboxPopupSelection(model_index_, state))); } } @@ -282,7 +282,7 @@ // a second click of the button violates assumptions in |AcceptKeyword|. // Note: Since keyword mode logic depends on state of the edit model, the // selection must first be set to prepare for keyword mode before accepting. - model_->popup_model()->SetSelection(selection); + model_->SetPopupSelection(selection); if (model_->is_keyword_hint()) { const auto entry_method = event.IsMouseEvent() ? metrics::OmniboxEventProto::CLICK_HINT_VIEW @@ -290,8 +290,7 @@ model_->AcceptKeyword(entry_method); } } else { - model_->popup_model()->TriggerSelectionAction(selection, - event.time_stamp()); + model_->TriggerPopupSelectionAction(selection, event.time_stamp()); } }
diff --git a/chrome/browser/ui/views/toolbar/read_later_toolbar_button.cc b/chrome/browser/ui/views/toolbar/read_later_toolbar_button.cc index 251d45dd..c0beb18 100644 --- a/chrome/browser/ui/views/toolbar/read_later_toolbar_button.cc +++ b/chrome/browser/ui/views/toolbar/read_later_toolbar_button.cc
@@ -174,14 +174,7 @@ dot_bounds_updater_( std::make_unique<DotBoundsUpdater>(dot_indicator_, image())), reading_list_model_( - ReadingListModelFactory::GetForBrowserContext(browser_->profile())), - contents_wrapper_(std::make_unique<BubbleContentsWrapperT<ReadLaterUI>>( - GURL(chrome::kChromeUIReadLaterURL), - browser_->profile(), - IDS_READ_LATER_TITLE, - true)) { - contents_wrapper_->ReloadWebContents(); - + ReadingListModelFactory::GetForBrowserContext(browser_->profile())) { SetVectorIcons(kSidePanelIcon, kSidePanelTouchIcon); SetTooltipText(l10n_util::GetStringUTF16(IDS_TOOLTIP_SIDE_PANEL_SHOW)); button_controller()->set_notify_action(
diff --git a/chrome/browser/ui/views/toolbar/read_later_toolbar_button.h b/chrome/browser/ui/views/toolbar/read_later_toolbar_button.h index 0a14c5d..510e7b0 100644 --- a/chrome/browser/ui/views/toolbar/read_later_toolbar_button.h +++ b/chrome/browser/ui/views/toolbar/read_later_toolbar_button.h
@@ -72,7 +72,6 @@ reading_list_model_scoped_observation_{this}; views::View* side_panel_webview_ = nullptr; - std::unique_ptr<BubbleContentsWrapperT<ReadLaterUI>> contents_wrapper_; }; #endif // CHROME_BROWSER_UI_VIEWS_TOOLBAR_READ_LATER_TOOLBAR_BUTTON_H_
diff --git a/chrome/browser/ui/webui/chromeos/bluetooth_shared_load_time_data_provider.cc b/chrome/browser/ui/webui/chromeos/bluetooth_shared_load_time_data_provider.cc index 9d77139c..fb49dac 100644 --- a/chrome/browser/ui/webui/chromeos/bluetooth_shared_load_time_data_provider.cc +++ b/chrome/browser/ui/webui/chromeos/bluetooth_shared_load_time_data_provider.cc
@@ -31,6 +31,7 @@ {"bluetoothPair", IDS_BLUETOOTH_PAIRING_PAIR}, {"bluetoothReject", IDS_BLUETOOTH_PAIRING_REJECT_PASSKEY}, {"bluetoothStartConnecting", IDS_BLUETOOTH_PAIRING_START_CONNECTING}, + {"bluetoothEnterPin", IDS_BLUETOOTH_PAIRING_ENTER_PIN}, // Device connecting and pairing. // These ids are generated in JS using 'bluetooth_' + a value from // bluetoothPrivate.PairingEventType (see bluetooth_private.idl).
diff --git a/chrome/browser/usb/web_usb_detector.cc b/chrome/browser/usb/web_usb_detector.cc index dcdbe63..e8c10fe 100644 --- a/chrome/browser/usb/web_usb_detector.cc +++ b/chrome/browser/usb/web_usb_detector.cc
@@ -13,6 +13,7 @@ #include "base/metrics/histogram_macros.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" +#include "chrome/browser/browser_features.h" #include "chrome/browser/net/referrer.h" #include "chrome/browser/notifications/system_notification_helper.h" #include "chrome/browser/profiles/profile_manager.h" @@ -28,7 +29,6 @@ #include "components/vector_icons/vector_icons.h" #include "content/public/browser/device_service.h" #include "content/public/browser/web_contents.h" -#include "device/base/features.h" #include "services/device/public/mojom/usb_device.mojom.h" #include "services/network/public/cpp/is_potentially_trustworthy.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -184,13 +184,10 @@ WebUsbDetector::~WebUsbDetector() = default; void WebUsbDetector::Initialize() { -#if defined(OS_WIN) - // The WebUSB device detector is disabled on Windows due to jank and hangs - // caused by enumerating devices. The new USB backend is designed to resolve - // these issues so enable it for testing. https://crbug.com/656702 - if (!base::FeatureList::IsEnabled(device::kNewUsbBackend)) + // The WebUSB device detector can be disabled if it causes trouble due to + // buggy devices and drivers. + if (!base::FeatureList::IsEnabled(features::kWebUsbDeviceDetection)) return; -#endif // defined(OS_WIN) // Tests may set a fake manager. if (!device_manager_) {
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index 2b59e649..2afac7e 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-main-1632505958-ddbb37bcdfa7dbd7b10cf3a9b6a5bc45e7a958a6.profdata +chrome-linux-main-1632548054-42d159d4e6ae5be86a2b7f9ab12a65b0c796632a.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index 24b7016c..39184a0 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-main-1632505958-ecc19202c484df17292092b0300480b0359444be.profdata +chrome-mac-main-1632548054-2383c30487282da9f24ad124189b84c254f5c156.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index a5a174b..6608e09d 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1632505958-14b6d621069ddb732268efb1d0bc37f7b09da8dd.profdata +chrome-win32-main-1632548054-6f16a736e66e0c44e71f7c21b592130c479acc9d.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index 6d37d23..34f910a1 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1632505958-83c3e60c48b4982e54d0488757ed9325a0b41134.profdata +chrome-win64-main-1632548054-de492a60f14cd25cedf09e8ac57ba676dd67f040.profdata
diff --git a/chrome/service/service_utility_process_host.cc b/chrome/service/service_utility_process_host.cc index 03a933e..302370d 100644 --- a/chrome/service/service_utility_process_host.cc +++ b/chrome/service/service_utility_process_host.cc
@@ -339,8 +339,8 @@ cmd_line, delegate.GetSandboxType()); base::Process process; - sandbox::ResultCode result = content::StartSandboxedProcess( - &delegate, cmd_line, handles, &process); + sandbox::ResultCode result = + content::StartSandboxedProcess(&delegate, *cmd_line, handles, &process); if (result != sandbox::SBOX_ALL_OK) return false;
diff --git a/chrome/test/data/webui/cr_components/chromeos/bluetooth/BUILD.gn b/chrome/test/data/webui/cr_components/chromeos/bluetooth/BUILD.gn index 9582fa32..79c92ba 100644 --- a/chrome/test/data/webui/cr_components/chromeos/bluetooth/BUILD.gn +++ b/chrome/test/data/webui/cr_components/chromeos/bluetooth/BUILD.gn
@@ -17,6 +17,7 @@ ":bluetooth_icon_test", ":bluetooth_pairing_device_item_test", ":bluetooth_pairing_device_selection_page_test", + ":bluetooth_pairing_request_code_page_test", ":bluetooth_pairing_ui_test", ":fake_bluetooth_config", ":fake_bluetooth_discovery_delegate", @@ -67,6 +68,14 @@ externs_list = [ "$externs_path/mocha-2.5.js" ] } +js_library("bluetooth_pairing_request_code_page_test") { + deps = [ + "../../..:chai_assert", + "//ui/webui/resources/cr_components/chromeos/bluetooth:bluetooth_pairing_request_code_page", + ] + externs_list = [ "$externs_path/mocha-2.5.js" ] +} + js_library("fake_bluetooth_config") { deps = [ "../../..:chai_assert",
diff --git a/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_pairing_request_code_page_test.js b/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_pairing_request_code_page_test.js new file mode 100644 index 0000000..e3ab491d --- /dev/null +++ b/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_pairing_request_code_page_test.js
@@ -0,0 +1,71 @@ +// Copyright 2021 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. + +// clang-format off +import 'chrome://bluetooth-pairing/strings.m.js'; + +import {SettingsBluetoothRequestCodePageElement} from 'chrome://resources/cr_components/chromeos/bluetooth/bluetooth_pairing_request_code_page.js'; +import {ButtonState} from 'chrome://resources/cr_components/chromeos/bluetooth/bluetooth_types.js'; +import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {assertEquals, assertTrue} from '../../../chai_assert.js'; +import {createDefaultBluetoothDevice} from './fake_bluetooth_config.js'; +// clang-format on + +const mojom = chromeos.bluetoothConfig.mojom; + +suite('CrComponentsBluetoothPairingRequestCodePageTest', function() { + /** @type {?SettingsBluetoothRequestCodePageElement} */ + let bluetoothPairingRequestCodePage; + + async function flushAsync() { + flush(); + return new Promise(resolve => setTimeout(resolve)); + } + + setup(function() { + bluetoothPairingRequestCodePage = + /** @type {?SettingsBluetoothRequestCodePageElement} */ ( + document.createElement('bluetooth-pairing-request-code-page')); + document.body.appendChild(bluetoothPairingRequestCodePage); + assertTrue(!!bluetoothPairingRequestCodePage); + flush(); + }); + + test('Message and button states test', async function() { + const getInput = () => + bluetoothPairingRequestCodePage.shadowRoot.querySelector('#pin'); + const getPairButtonState = () => { + const basePage = bluetoothPairingRequestCodePage.shadowRoot.querySelector( + 'bluetooth-base-page'); + return basePage.buttonBarState.pair; + }; + const deviceName = 'BeatsX'; + const device = createDefaultBluetoothDevice( + /*id=*/ '123456789', + /*publicName=*/ deviceName, + /*connected=*/ true, + /*opt_nickname=*/ 'device1', + /*opt_audioCapability=*/ + mojom.AudioOutputCapability.kCapableOfAudioOutput, + /*opt_deviceType=*/ mojom.DeviceType.kMouse); + + bluetoothPairingRequestCodePage.device = device.deviceProperties; + await flushAsync(); + + const message = + bluetoothPairingRequestCodePage.shadowRoot.querySelector('#message'); + assertTrue(!!message); + assertEquals( + bluetoothPairingRequestCodePage.i18n('bluetoothEnterPin', deviceName), + message.textContent.trim()); + + // Test button states. + assertEquals(ButtonState.DISABLED, getPairButtonState()); + assertTrue(!!getInput()); + + getInput().value = '12345'; + await flushAsync(); + assertEquals(ButtonState.ENABLED, getPairButtonState()); + }); +}); \ No newline at end of file
diff --git a/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_pairing_ui_test.js b/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_pairing_ui_test.js index a5ac4dc3..cebbf3b 100644 --- a/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_pairing_ui_test.js +++ b/chrome/test/data/webui/cr_components/chromeos/bluetooth/bluetooth_pairing_ui_test.js
@@ -59,7 +59,7 @@ assertEquals(1, deviceSelectionPage.devices.length); }); - test('finished event fired on succesful device pair', async function() { + test('finished event fired on successful device pair', async function() { const id = '12//345&6789'; const deviceSelectionPage = bluetoothPairingUi.shadowRoot.querySelector('#deviceSelectionPage'); @@ -78,7 +78,8 @@ bluetoothConfig.appendToDiscoveredDeviceList([device.deviceProperties]); await flushAsync(); - const event = new CustomEvent('pair-device', {detail: {deviceId: id}}); + const event = new CustomEvent( + 'pair-device', {detail: {device: device.deviceProperties}}); deviceSelectionPage.dispatchEvent(event); await flushAsync(); @@ -116,7 +117,7 @@ assertEquals(deviceHandler.getPairDeviceCalledCount(), 0); let event = new CustomEvent( - 'pair-device', {detail: {deviceId: device.deviceProperties.id}}); + 'pair-device', {detail: {device: device.deviceProperties}}); deviceSelectionPage.dispatchEvent(event); await flushAsync(); @@ -126,7 +127,7 @@ await flushAsync(); event = new CustomEvent( - 'pair-device', {detail: {deviceId: device.deviceProperties.id}}); + 'pair-device', {detail: {device: device.deviceProperties}}); deviceSelectionPage.dispatchEvent(event); await flushAsync();
diff --git a/chrome/test/data/webui/cr_components/chromeos/cr_components_chromeos_v3_browsertest.js b/chrome/test/data/webui/cr_components/chromeos/cr_components_chromeos_v3_browsertest.js index 2838cce..81f6ed0 100644 --- a/chrome/test/data/webui/cr_components/chromeos/cr_components_chromeos_v3_browsertest.js +++ b/chrome/test/data/webui/cr_components/chromeos/cr_components_chromeos_v3_browsertest.js
@@ -17,6 +17,10 @@ 'DeviceSelectionPage', 'bluetooth/bluetooth_pairing_device_selection_page_test.js' ], + [ + 'PairingRequestCodePage', + 'bluetooth/bluetooth_pairing_request_code_page_test.js' + ], ['BluetoothIcon', 'bluetooth/bluetooth_icon_test.js'], ['PairingUi', 'bluetooth/bluetooth_pairing_ui_test.js'], ['PairingDeviceItem', 'bluetooth/bluetooth_pairing_device_item_test.js'],
diff --git a/chrome/test/data/webui/print_preview/select_behavior_test.js b/chrome/test/data/webui/print_preview/select_behavior_test.js index ea8c301..6c21b585 100644 --- a/chrome/test/data/webui/print_preview/select_behavior_test.js +++ b/chrome/test/data/webui/print_preview/select_behavior_test.js
@@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {SelectBehavior} from 'chrome://print/print_preview.js'; +import {SelectMixin} from 'chrome://print/print_preview.js'; import {assert} from 'chrome://resources/js/assert.m.js'; -import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {eventToPromise} from 'chrome://test/test_util.js'; window.select_behavior_test = {}; -select_behavior_test.suiteName = 'SelectBehaviorTest'; +select_behavior_test.suiteName = 'SelectMixinTest'; /** @enum {string} */ select_behavior_test.TestNames = { CallProcessSelectChange: 'call process select change', @@ -21,28 +21,38 @@ /** @type {string} */ let settingValue = '0'; + suiteSetup(function() { + const TestSelectElementBase = SelectMixin(PolymerElement); + + class TestSelectElement extends TestSelectElementBase { + static get is() { + return 'test-select'; + } + + static get template() { + return html` + <select value="{{selectedValue::change}}"> + <option value="0" selected>0</option> + <option value="1">1</option> + <option value="2">2</option> + </select> + `; + } + + onProcessSelectChange(value) { + settingValue = value; + this.dispatchEvent(new CustomEvent( + 'process-select-change-called', + {bubbles: true, composed: true, detail: value})); + } + } + + customElements.define(TestSelectElement.is, TestSelectElement); + }); + /** @override */ setup(function() { - Polymer({ - is: 'test-select', - - _template: html` - <select value="{{selectedValue::change}}"> - <option value="0" selected>0</option> - <option value="1">1</option> - <option value="2">2</option> - </select> - `, - - behaviors: [SelectBehavior], - - onProcessSelectChange: function(value) { - settingValue = value; - this.fire('process-select-change-called', value); - }, - }); - - PolymerTest.clearBody(); + document.body.innerHTML = ''; testSelect = document.createElement('test-select'); document.body.appendChild(testSelect); testSelect.selectedValue = '0';
diff --git a/chrome/test/enterprise/e2e/.vpython b/chrome/test/enterprise/e2e/.vpython index 3ad7696..d53e2d9f 100644 --- a/chrome/test/enterprise/e2e/.vpython +++ b/chrome/test/enterprise/e2e/.vpython
@@ -11,8 +11,8 @@ wheel: < name: "infra/celab/celab/windows-amd64" - # Source: https://ci.chromium.org/p/celab/builders/ci/Windows/b8863242163218578192 - version: "IQHknf30R2DyRmnCQ9PWQToO1x-rS7ecoTeaDqncGmoC" + # Source: https://ci.chromium.org/p/celab/builders/ci/Windows/b8839159667690916800 + version: "ESovjdrWROIDnSgn5pI9YH26d43O2_iYLvqCFSAZ7u0C" > # googleapiclient
diff --git a/chromeos/components/phonehub/cros_state_sender.cc b/chromeos/components/phonehub/cros_state_sender.cc index 361a070..01786746 100644 --- a/chromeos/components/phonehub/cros_state_sender.cc +++ b/chromeos/components/phonehub/cros_state_sender.cc
@@ -89,10 +89,16 @@ bool are_notifications_enabled = multidevice_setup_client_->GetFeatureState( Feature::kPhoneHubNotifications) == FeatureState::kEnabledByUser; + bool is_camera_roll_enabled = + multidevice_setup_client_->GetFeatureState( + Feature::kPhoneHubCameraRoll) == FeatureState::kEnabledByUser; PA_LOG(INFO) << "Attempting to send cros state with notifications enabled " - << "state as: " << are_notifications_enabled; - message_sender_->SendCrosState(are_notifications_enabled); + << "state as: " << are_notifications_enabled + << " and camera roll enabled state as: " + << is_camera_roll_enabled; + message_sender_->SendCrosState(are_notifications_enabled, + is_camera_roll_enabled); retry_timer_->Start(FROM_HERE, retry_delay_, base::BindOnce(&CrosStateSender::OnRetryTimerFired,
diff --git a/chromeos/components/phonehub/cros_state_sender_unittest.cc b/chromeos/components/phonehub/cros_state_sender_unittest.cc index 58a32f5..60dbdd7 100644 --- a/chromeos/components/phonehub/cros_state_sender_unittest.cc +++ b/chromeos/components/phonehub/cros_state_sender_unittest.cc
@@ -106,6 +106,9 @@ // Set notification feature to be enabled. fake_multidevice_setup_client_->SetFeatureState( Feature::kPhoneHubNotifications, FeatureState::kEnabledByUser); + // Set camera roll feature to be enabled. + fake_multidevice_setup_client_->SetFeatureState(Feature::kPhoneHubCameraRoll, + FeatureState::kEnabledByUser); // Expect no new messages since connection has not been established. EXPECT_EQ(0u, fake_message_sender_->GetCrosStateCallCount()); EXPECT_FALSE(mock_timer_->IsRunning()); @@ -120,7 +123,8 @@ // Simulate connected state. Expect a new message to be sent. fake_connection_manager_->SetStatus( secure_channel::ConnectionManager::Status::kConnected); - EXPECT_TRUE(fake_message_sender_->GetRecentCrosState()); + EXPECT_TRUE(fake_message_sender_->GetRecentCrosState().first); + EXPECT_TRUE(fake_message_sender_->GetRecentCrosState().second); EXPECT_EQ(1u, fake_message_sender_->GetCrosStateCallCount()); // Phone model is populated. @@ -131,7 +135,8 @@ // Simulate disconnected state, this should not trigger a new request. fake_connection_manager_->SetStatus( secure_channel::ConnectionManager::Status::kDisconnected); - EXPECT_TRUE(fake_message_sender_->GetRecentCrosState()); + EXPECT_TRUE(fake_message_sender_->GetRecentCrosState().first); + EXPECT_TRUE(fake_message_sender_->GetRecentCrosState().second); EXPECT_EQ(1u, fake_message_sender_->GetCrosStateCallCount()); EXPECT_FALSE(mock_timer_->IsRunning()); } @@ -146,7 +151,8 @@ EXPECT_TRUE(mock_timer_->IsRunning()); // Expect new messages to be sent when connection state is connected. - EXPECT_FALSE(fake_message_sender_->GetRecentCrosState()); + EXPECT_FALSE(fake_message_sender_->GetRecentCrosState().first); + EXPECT_FALSE(fake_message_sender_->GetRecentCrosState().second); EXPECT_EQ(1u, fake_message_sender_->GetCrosStateCallCount()); mock_timer_->Fire(); @@ -154,7 +160,7 @@ // enabled. fake_multidevice_setup_client_->SetFeatureState( Feature::kPhoneHubNotifications, FeatureState::kEnabledByUser); - EXPECT_TRUE(fake_message_sender_->GetRecentCrosState()); + EXPECT_TRUE(fake_message_sender_->GetRecentCrosState().first); EXPECT_EQ(2u, fake_message_sender_->GetCrosStateCallCount()); mock_timer_->Fire(); @@ -162,7 +168,7 @@ // cros state. fake_multidevice_setup_client_->SetFeatureState( Feature::kSmartLock, FeatureState::kDisabledByUser); - EXPECT_TRUE(fake_message_sender_->GetRecentCrosState()); + EXPECT_TRUE(fake_message_sender_->GetRecentCrosState().first); EXPECT_EQ(3u, fake_message_sender_->GetCrosStateCallCount()); mock_timer_->Fire(); @@ -170,12 +176,19 @@ // disabled. fake_multidevice_setup_client_->SetFeatureState( Feature::kPhoneHubNotifications, FeatureState::kDisabledByUser); - EXPECT_FALSE(fake_message_sender_->GetRecentCrosState()); + EXPECT_FALSE(fake_message_sender_->GetRecentCrosState().first); EXPECT_EQ(4u, fake_message_sender_->GetCrosStateCallCount()); + // Simulate enabling camera roll feature state and expect cros state to be + // updated. + fake_multidevice_setup_client_->SetFeatureState(Feature::kPhoneHubCameraRoll, + FeatureState::kEnabledByUser); + EXPECT_TRUE(fake_message_sender_->GetRecentCrosState().second); + EXPECT_EQ(5u, fake_message_sender_->GetCrosStateCallCount()); + // Firing the timer does not cause the cros state to be sent again. mock_timer_->Fire(); - EXPECT_EQ(4u, fake_message_sender_->GetCrosStateCallCount()); + EXPECT_EQ(5u, fake_message_sender_->GetCrosStateCallCount()); } } // namespace phonehub
diff --git a/chromeos/components/phonehub/fake_message_sender.cc b/chromeos/components/phonehub/fake_message_sender.cc index 180d57a8..506fcdd 100644 --- a/chromeos/components/phonehub/fake_message_sender.cc +++ b/chromeos/components/phonehub/fake_message_sender.cc
@@ -10,8 +10,10 @@ FakeMessageSender::FakeMessageSender() = default; FakeMessageSender::~FakeMessageSender() = default; -void FakeMessageSender::SendCrosState(bool notification_enabled) { - cros_states_.push_back(notification_enabled); +void FakeMessageSender::SendCrosState(bool notification_enabled, + bool camera_roll_enabled) { + cros_states_.push_back( + std::make_pair(notification_enabled, camera_roll_enabled)); } void FakeMessageSender::SendUpdateNotificationModeRequest( @@ -77,7 +79,7 @@ return fetch_camera_roll_items_requests_.size(); } -bool FakeMessageSender::GetRecentCrosState() const { +std::pair<bool, bool> FakeMessageSender::GetRecentCrosState() const { return cros_states_.back(); }
diff --git a/chromeos/components/phonehub/fake_message_sender.h b/chromeos/components/phonehub/fake_message_sender.h index 8ac1cfaf..aeb2b82d 100644 --- a/chromeos/components/phonehub/fake_message_sender.h +++ b/chromeos/components/phonehub/fake_message_sender.h
@@ -22,7 +22,8 @@ ~FakeMessageSender() override; // MessageSender: - void SendCrosState(bool notification_enabled) override; + void SendCrosState(bool notification_enabled, + bool camera_roll_enabled) override; void SendUpdateNotificationModeRequest(bool do_not_disturb_enabled) override; void SendUpdateBatteryModeRequest(bool battery_saver_mode_enabled) override; void SendDismissNotificationRequest(int64_t notification_id) override; @@ -34,7 +35,7 @@ void SendFetchCameraRollItemsRequest( const proto::FetchCameraRollItemsRequest& request) override; - bool GetRecentCrosState() const; + std::pair<bool, bool> GetRecentCrosState() const; bool GetRecentUpdateNotificationModeRequest() const; bool GetRecentUpdateBatteryModeRequest() const; int64_t GetRecentDismissNotificationRequest() const; @@ -63,7 +64,9 @@ size_t GetFetchCameraRollItemsRequestCallCount() const; private: - std::vector<bool> cros_states_; + std::vector<std::pair</*is_notifications_setting_enabled*/ bool, + /*is_camera_roll_setting_enabled*/ bool>> + cros_states_; std::vector<bool> update_notification_mode_requests_; std::vector<bool> update_battery_mode_requests_; std::vector<int64_t> dismiss_notification_requests_;
diff --git a/chromeos/components/phonehub/message_sender.h b/chromeos/components/phonehub/message_sender.h index 4cd09b9..a9c52999 100644 --- a/chromeos/components/phonehub/message_sender.h +++ b/chromeos/components/phonehub/message_sender.h
@@ -22,7 +22,8 @@ virtual ~MessageSender() = default; // Sends whether the notification setting is enabled in the Chrome OS device. - virtual void SendCrosState(bool notification_setting_enabled) = 0; + virtual void SendCrosState(bool notification_setting_enabled, + bool camera_roll_setting_enabled) = 0; // Requests that the phone enables or disables Do Not Disturb mode. virtual void SendUpdateNotificationModeRequest(
diff --git a/chromeos/components/phonehub/message_sender_impl.cc b/chromeos/components/phonehub/message_sender_impl.cc index d3d2cd312..d16e36d 100644 --- a/chromeos/components/phonehub/message_sender_impl.cc +++ b/chromeos/components/phonehub/message_sender_impl.cc
@@ -38,13 +38,18 @@ MessageSenderImpl::~MessageSenderImpl() = default; -void MessageSenderImpl::SendCrosState(bool notification_setting_enabled) { +void MessageSenderImpl::SendCrosState(bool notification_setting_enabled, + bool camera_roll_setting_enabled) { proto::NotificationSetting is_notification_enabled = notification_setting_enabled ? proto::NotificationSetting::NOTIFICATIONS_ON : proto::NotificationSetting::NOTIFICATIONS_OFF; + proto::CameraRollSetting is_camera_roll_enabled = + camera_roll_setting_enabled ? proto::CameraRollSetting::CAMERA_ROLL_ON + : proto::CameraRollSetting::CAMERA_ROLL_OFF; proto::CrosState request; request.set_notification_setting(is_notification_enabled); + request.set_camera_roll_setting(is_camera_roll_enabled); SendMessage(proto::MessageType::PROVIDE_CROS_STATE, &request); }
diff --git a/chromeos/components/phonehub/message_sender_impl.h b/chromeos/components/phonehub/message_sender_impl.h index 0f19ec2..cd689b70 100644 --- a/chromeos/components/phonehub/message_sender_impl.h +++ b/chromeos/components/phonehub/message_sender_impl.h
@@ -27,7 +27,8 @@ ~MessageSenderImpl() override; // MessageSender: - void SendCrosState(bool notification_setting_enabled) override; + void SendCrosState(bool notification_setting_enabled, + bool camera_roll_setting_enabled) override; void SendUpdateNotificationModeRequest(bool do_not_disturb_enabled) override; void SendUpdateBatteryModeRequest(bool battery_saver_mode_enabled) override; void SendDismissNotificationRequest(int64_t notification_id) override;
diff --git a/chromeos/components/phonehub/message_sender_unittest.cc b/chromeos/components/phonehub/message_sender_unittest.cc index 5df0ddd..9d1d053 100644 --- a/chromeos/components/phonehub/message_sender_unittest.cc +++ b/chromeos/components/phonehub/message_sender_unittest.cc
@@ -64,8 +64,10 @@ proto::CrosState request; request.set_notification_setting( proto::NotificationSetting::NOTIFICATIONS_ON); + request.set_camera_roll_setting(proto::CameraRollSetting::CAMERA_ROLL_OFF); - message_sender_->SendCrosState(/*notification_enabled=*/true); + message_sender_->SendCrosState(/*notification_enabled=*/true, + /*camera_roll_enabled=*/false); VerifyMessage(proto::MessageType::PROVIDE_CROS_STATE, &request, fake_connection_manager_->sent_messages().back()); }
diff --git a/chromeos/components/phonehub/proto/phonehub_api.proto b/chromeos/components/phonehub/proto/phonehub_api.proto index 527dee8b..6ff53376 100644 --- a/chromeos/components/phonehub/proto/phonehub_api.proto +++ b/chromeos/components/phonehub/proto/phonehub_api.proto
@@ -40,6 +40,11 @@ NOTIFICATIONS_ON = 1; } +enum CameraRollSetting { + CAMERA_ROLL_OFF = 0; + CAMERA_ROLL_ON = 1; +} + enum ChargingState { NOT_CHARGING = 0; CHARGING_AC = 1; @@ -162,6 +167,7 @@ message CrosState { NotificationSetting notification_setting = 1; + CameraRollSetting camera_roll_setting = 2; } message Action {
diff --git a/chromeos/components/projector_app/annotator_tool.cc b/chromeos/components/projector_app/annotator_tool.cc index 6d4a0a6..2796c54 100644 --- a/chromeos/components/projector_app/annotator_tool.cc +++ b/chromeos/components/projector_app/annotator_tool.cc
@@ -6,6 +6,7 @@ #include <string> +#include "base/notreached.h" #include "base/strings/string_number_conversions.h" #include "base/values.h" @@ -36,6 +37,32 @@ return success ? color : SK_ColorRED; } +std::string ConvertToolTypeToString(AnnotatorToolType type) { + switch (type) { + case AnnotatorToolType::kMarker: + return "marker"; + case AnnotatorToolType::kPen: + return "pen"; + case AnnotatorToolType::kHighlighter: + return "highlighter"; + case AnnotatorToolType::kEraser: + return "eraser"; + } +} + +AnnotatorToolType ConvertStringToToolType(const std::string& type) { + if (type == "marker") + return AnnotatorToolType::kMarker; + if (type == "pen") + return AnnotatorToolType::kPen; + if (type == "highlighter") + return AnnotatorToolType::kHighlighter; + if (type == "eraser") + return AnnotatorToolType::kEraser; + NOTREACHED(); + return AnnotatorToolType::kMarker; +} + } // namespace // static @@ -46,11 +73,11 @@ DCHECK(value.FindKey(kToolSize)); DCHECK(value.FindKey(kToolSize)->is_int()); DCHECK(value.FindKey(kToolType)); - DCHECK(value.FindKey(kToolType)->is_int()); + DCHECK(value.FindKey(kToolType)->is_string()); AnnotatorTool t; t.color = ConvertHexStringToColor(*(value.FindStringPath(kToolColor))); t.size = *(value.FindIntPath(kToolSize)); - t.type = static_cast<AnnotatorToolType>(*(value.FindIntPath(kToolType))); + t.type = ConvertStringToToolType(*(value.FindStringPath(kToolType))); return t; } @@ -58,7 +85,7 @@ base::Value val(base::Value::Type::DICTIONARY); val.SetKey(kToolColor, base::Value(ConvertColorToHexString(color))); val.SetKey(kToolSize, base::Value(size)); - val.SetKey(kToolType, base::Value(static_cast<int>(type))); + val.SetKey(kToolType, base::Value(ConvertToolTypeToString(type))); return val; }
diff --git a/components/bookmarks/common/android/java/src/org/chromium/components/bookmarks/BookmarkId.java b/components/bookmarks/common/android/java/src/org/chromium/components/bookmarks/BookmarkId.java index 36b53209..7782661 100644 --- a/components/bookmarks/common/android/java/src/org/chromium/components/bookmarks/BookmarkId.java +++ b/components/bookmarks/common/android/java/src/org/chromium/components/bookmarks/BookmarkId.java
@@ -86,7 +86,7 @@ * Returns the bookmark type: {@link BookmarkType#NORMAL} or {@link BookmarkType#PARTNER}. */ @CalledByNative - public int getType() { + public @BookmarkType int getType() { return mType; }
diff --git a/components/exo/client_controlled_shell_surface.cc b/components/exo/client_controlled_shell_surface.cc index 8d7e852..3aa694f 100644 --- a/components/exo/client_controlled_shell_surface.cc +++ b/components/exo/client_controlled_shell_surface.cc
@@ -432,7 +432,12 @@ if (!widget_) CreateShellSurfaceWidget(ui::SHOW_STATE_NORMAL); - widget_->GetNativeWindow()->SetProperty(chromeos::kWindowPinTypeKey, type); + if (type == chromeos::WindowPinType::kNone) { + ash::WindowState::Get(widget_->GetNativeWindow())->Restore(); + } else { + bool trusted = type == chromeos::WindowPinType::kTrustedPinned; + ash::window_util::PinWindow(widget_->GetNativeWindow(), trusted); + } } void ClientControlledShellSurface::SetSystemUiVisibility(bool autohide) {
diff --git a/components/exo/client_controlled_shell_surface_unittest.cc b/components/exo/client_controlled_shell_surface_unittest.cc index caf1ace..d228768 100644 --- a/components/exo/client_controlled_shell_surface_unittest.cc +++ b/components/exo/client_controlled_shell_surface_unittest.cc
@@ -87,10 +87,7 @@ } bool IsWidgetPinned(views::Widget* widget) { - chromeos::WindowPinType type = - widget->GetNativeWindow()->GetProperty(chromeos::kWindowPinTypeKey); - return type == chromeos::WindowPinType::kPinned || - type == chromeos::WindowPinType::kTrustedPinned; + return ash::WindowState::Get(widget->GetNativeWindow())->IsPinned(); } int GetShadowElevation(aura::Window* window) {
diff --git a/components/feed/core/v2/api_test/feed_api_subscriptions_unittest.cc b/components/feed/core/v2/api_test/feed_api_subscriptions_unittest.cc index 10c298d..3a3ef6e2 100644 --- a/components/feed/core/v2/api_test/feed_api_subscriptions_unittest.cc +++ b/components/feed/core/v2/api_test/feed_api_subscriptions_unittest.cc
@@ -153,6 +153,8 @@ WebFeedSubscriptionRequestStatus::kSuccess, 1); histograms.ExpectUniqueSample( "ContentSuggestions.Feed.WebFeed.FollowCount.AfterFollow", 1, 1); + histograms.ExpectUniqueSample( + "ContentSuggestions.Feed.WebFeed.NewFollow.IsRecommended", 0, 1); } TEST_F(FeedApiSubscriptionsTest, FollowRecommendedWebFeedById) { @@ -172,6 +174,8 @@ WebFeedSubscriptionRequestStatus::kSuccess, 1); histograms.ExpectUniqueSample( "ContentSuggestions.Feed.WebFeed.FollowCount.AfterFollow", 1, 1); + histograms.ExpectUniqueSample( + "ContentSuggestions.Feed.WebFeed.NewFollow.IsRecommended", 1, 1); } // Make two Follow attempts for the same page. Both appear successful, but only @@ -263,7 +267,29 @@ EXPECT_EQ("{}", PrintToString(CheckAllSubscriptions())); } +TEST_F(FeedApiSubscriptionsTest, CantFollowWebFeedByIdWhileOffline) { + base::HistogramTester histograms; + is_offline_ = true; + network_.InjectResponse(SuccessfulFollowResponse("cats")); + CallbackReceiver<WebFeedSubscriptions::FollowWebFeedResult> callback; + + subscriptions().FollowWebFeed("feed_id", callback.Bind()); + + EXPECT_EQ(0, network_.GetFollowRequestCount()); + EXPECT_EQ(WebFeedSubscriptionRequestStatus::kFailedOffline, + callback.RunAndGetResult().request_status); + EXPECT_EQ("{}", PrintToString(CheckAllSubscriptions())); + histograms.ExpectUniqueSample( + "ContentSuggestions.Feed.WebFeed.FollowByIdResult", + WebFeedSubscriptionRequestStatus::kFailedOffline, 1); + histograms.ExpectTotalCount( + "ContentSuggestions.Feed.WebFeed.FollowCount.AfterFollow", 0); + histograms.ExpectTotalCount( + "ContentSuggestions.Feed.WebFeed.NewFollow.IsRecommended", 0); +} + TEST_F(FeedApiSubscriptionsTest, FollowWebFeedNetworkError) { + base::HistogramTester histograms; network_.InjectFollowResponse(MakeFailedResponse()); CallbackReceiver<WebFeedSubscriptions::FollowWebFeedResult> callback; EXPECT_FALSE(feedstore::IsKnownStale(stream_->GetMetadata(), kWebFeedStream)); @@ -275,6 +301,9 @@ callback.RunAndGetResult().request_status); EXPECT_EQ("{}", PrintToString(CheckAllSubscriptions())); EXPECT_FALSE(feedstore::IsKnownStale(stream_->GetMetadata(), kWebFeedStream)); + histograms.ExpectUniqueSample( + "ContentSuggestions.Feed.WebFeed.FollowUriResult", + WebFeedSubscriptionRequestStatus::kFailedUnknownError, 1); } // Follow and then unfollow a web feed successfully.
diff --git a/components/feed/core/v2/metrics_reporter.cc b/components/feed/core/v2/metrics_reporter.cc index af0c231c..136f613 100644 --- a/components/feed/core/v2/metrics_reporter.cc +++ b/components/feed/core/v2/metrics_reporter.cc
@@ -799,6 +799,9 @@ base::UmaHistogramSparse( "ContentSuggestions.Feed.WebFeed.FollowCount.AfterFollow", result.subscription_count); + base::UmaHistogramBoolean( + "ContentSuggestions.Feed.WebFeed.NewFollow.IsRecommended", + result.web_feed_metadata.is_recommended); } }
diff --git a/components/metrics/metrics_state_manager.cc b/components/metrics/metrics_state_manager.cc index 6bb01f6a..8b74110 100644 --- a/components/metrics/metrics_state_manager.cc +++ b/components/metrics/metrics_state_manager.cc
@@ -407,16 +407,16 @@ std::string client_id_from_prefs = ReadClientId(local_state_); // If client id in prefs matches the cached copy, return early. if (!client_id_from_prefs.empty() && client_id_from_prefs == client_id_) { - UMA_HISTOGRAM_ENUMERATION("UMA.ClientIdSource", - ClientIdSource::kClientIdMatches); + base::UmaHistogramEnumeration("UMA.ClientIdSource", + ClientIdSource::kClientIdMatches); return; } client_id_.swap(client_id_from_prefs); } if (!client_id_.empty()) { - UMA_HISTOGRAM_ENUMERATION("UMA.ClientIdSource", - ClientIdSource::kClientIdFromLocalState); + base::UmaHistogramEnumeration("UMA.ClientIdSource", + ClientIdSource::kClientIdFromLocalState); #if BUILDFLAG(IS_CHROMEOS_ASH) LogClientIdChanged( metrics::structured::NeutrinoDevicesLocation::kClientIdFromLocalState, @@ -450,8 +450,8 @@ recovered_installation_age = now - base::Time::FromTimeT(client_info_backup->installation_date); } - UMA_HISTOGRAM_ENUMERATION("UMA.ClientIdSource", - ClientIdSource::kClientIdBackupRecovered); + base::UmaHistogramEnumeration("UMA.ClientIdSource", + ClientIdSource::kClientIdBackupRecovered); UMA_HISTOGRAM_COUNTS_10000("UMA.ClientIdBackupRecoveredWithAge", recovered_installation_age.InHours()); #if BUILDFLAG(IS_CHROMEOS_ASH) @@ -472,8 +472,8 @@ // otherwise (e.g. UMA enabled in a future session), generate a new one. if (provisional_client_id_.empty()) { client_id_ = base::GenerateGUID(); - UMA_HISTOGRAM_ENUMERATION("UMA.ClientIdSource", - ClientIdSource::kClientIdNew); + base::UmaHistogramEnumeration("UMA.ClientIdSource", + ClientIdSource::kClientIdNew); #if BUILDFLAG(IS_CHROMEOS_ASH) LogClientIdChanged( metrics::structured::NeutrinoDevicesLocation::kClientIdNew, @@ -482,8 +482,8 @@ } else { client_id_ = provisional_client_id_; provisional_client_id_.clear(); - UMA_HISTOGRAM_ENUMERATION("UMA.ClientIdSource", - ClientIdSource::kClientIdFromProvisionalId); + base::UmaHistogramEnumeration("UMA.ClientIdSource", + ClientIdSource::kClientIdFromProvisionalId); #if BUILDFLAG(IS_CHROMEOS_ASH) LogClientIdChanged(metrics::structured::NeutrinoDevicesLocation:: kClientIdFromProvisionalId,
diff --git a/components/nacl/broker/nacl_broker_listener.cc b/components/nacl/broker/nacl_broker_listener.cc index 9c4e7c6a..57b2420 100644 --- a/components/nacl/broker/nacl_broker_listener.cc +++ b/components/nacl/broker/nacl_broker_listener.cc
@@ -109,7 +109,7 @@ base::Process loader_process; sandbox::ResultCode result = content::StartSandboxedProcess( - this, cmd_line, handles, &loader_process); + this, *cmd_line, handles, &loader_process); if (result == sandbox::SBOX_ALL_OK) { mojo::OutgoingInvitation::Send(std::move(invitation),
diff --git a/components/no_state_prefetch/renderer/DEPS b/components/no_state_prefetch/renderer/DEPS index f94db2aa..49fd61f 100644 --- a/components/no_state_prefetch/renderer/DEPS +++ b/components/no_state_prefetch/renderer/DEPS
@@ -1,6 +1,7 @@ include_rules = [ "+content/public/common", "+content/public/renderer", + "+media/mojo/mojom/media_player.mojom.h", "+mojo/public/cpp/bindings", "+third_party/blink/public", ]
diff --git a/components/no_state_prefetch/renderer/no_state_prefetch_utils.cc b/components/no_state_prefetch/renderer/no_state_prefetch_utils.cc index c2e231d..0ed22ab 100644 --- a/components/no_state_prefetch/renderer/no_state_prefetch_utils.cc +++ b/components/no_state_prefetch/renderer/no_state_prefetch_utils.cc
@@ -4,9 +4,13 @@ #include "components/no_state_prefetch/renderer/no_state_prefetch_utils.h" +#include "base/memory/weak_ptr.h" #include "components/no_state_prefetch/renderer/no_state_prefetch_helper.h" #include "content/public/common/page_visibility_state.h" #include "content/public/renderer/render_frame.h" +#include "media/mojo/mojom/media_player.mojom.h" +#include "mojo/public/cpp/bindings/generic_pending_receiver.h" +#include "third_party/blink/public/common/browser_interface_broker_proxy.h" #include "third_party/blink/public/web/web_local_frame.h" #include "third_party/blink/public/web/web_view.h" #include "third_party/blink/public/web/web_view_observer.h" @@ -15,13 +19,24 @@ namespace { -// Defers media player loading in background pages until they're visible. +// Defers media player loading in background pages until they're visible unless +// the tab has previously played content before. class MediaLoadDeferrer : public blink::WebViewObserver { public: - MediaLoadDeferrer(blink::WebView* web_view, + MediaLoadDeferrer(content::RenderFrame* render_frame, + blink::WebView* web_view, base::OnceClosure continue_loading_cb) : blink::WebViewObserver(web_view), - continue_loading_cb_(std::move(continue_loading_cb)) {} + continue_loading_cb_(std::move(continue_loading_cb)) { + mojo::PendingReceiver<media::mojom::MediaPlayerObserverClient> + media_player_observer_client_receiver = + media_player_observer_client_.BindNewPipeAndPassReceiver(); + render_frame->GetBrowserInterfaceBroker()->GetInterface( + std::move(media_player_observer_client_receiver)); + media_player_observer_client_->GetHasPlayedBefore( + base::BindOnce(&MediaLoadDeferrer::OnGetHasPlayedBeforeCallback, + weak_factory_.GetWeakPtr())); + } MediaLoadDeferrer(const MediaLoadDeferrer&) = delete; MediaLoadDeferrer& operator=(const MediaLoadDeferrer&) = delete; @@ -38,8 +53,19 @@ delete this; } + void OnGetHasPlayedBeforeCallback(bool has_played_before) { + if (has_played_before) { + std::move(continue_loading_cb_).Run(); + delete this; + } + } + private: + mojo::Remote<media::mojom::MediaPlayerObserverClient> + media_player_observer_client_; base::OnceClosure continue_loading_cb_; + + base::WeakPtrFactory<MediaLoadDeferrer> weak_factory_{this}; }; } // namespace @@ -56,7 +82,7 @@ content::PageVisibilityState::kVisible && !has_played_media_before) || NoStatePrefetchHelper::IsPrefetching(render_frame)) { - new MediaLoadDeferrer(render_frame->GetWebFrame()->View(), + new MediaLoadDeferrer(render_frame, render_frame->GetWebFrame()->View(), std::move(closure)); return true; }
diff --git a/components/omnibox/browser/omnibox_controller.cc b/components/omnibox/browser/omnibox_controller.cc index b1d116c..c0e8879e 100644 --- a/components/omnibox/browser/omnibox_controller.cc +++ b/components/omnibox/browser/omnibox_controller.cc
@@ -46,8 +46,7 @@ bool default_match_changed) { DCHECK(controller == autocomplete_controller_.get()); - OmniboxPopupModel* popup = omnibox_edit_model_->popup_model(); - const bool was_open = popup && popup->IsOpen(); + const bool was_open = omnibox_edit_model_->PopupIsOpen(); if (default_match_changed) { // The default match has changed, we need to let the OmniboxEditModel know // about new inline autocomplete text (blue highlight). @@ -56,18 +55,17 @@ omnibox_edit_model_->OnCurrentMatchChanged(); } else { InvalidateCurrentMatch(); - if (popup) - popup->OnResultChanged(); + omnibox_edit_model_->OnPopupResultChanged(); omnibox_edit_model_->OnPopupDataChanged( std::u16string(), /*is_temporary_text=*/false, std::u16string(), std::u16string(), {}, std::u16string(), false, std::u16string()); } - } else if (popup) { - popup->OnResultChanged(); + } else { + omnibox_edit_model_->OnPopupResultChanged(); } - if (was_open && !popup->IsOpen()) { + if (was_open && !omnibox_edit_model_->PopupIsOpen()) { // Accept the temporary text as the user text, because it makes little sense // to have temporary text when the popup is closed. omnibox_edit_model_->AcceptTemporaryTextAsUserText(); @@ -93,17 +91,16 @@ } void OmniboxController::ClearPopupKeywordMode() const { - OmniboxPopupModel* popup = omnibox_edit_model_->popup_model(); - // |popup| can be nullptr in tests. - if (popup && popup->IsOpen() && - popup->selected_line_state() == OmniboxPopupSelection::KEYWORD_MODE) { - popup->SetSelectedLineState(OmniboxPopupSelection::NORMAL); + if (omnibox_edit_model_->PopupIsOpen()) { + OmniboxPopupSelection selection = omnibox_edit_model_->GetPopupSelection(); + if (selection.state == OmniboxPopupSelection::KEYWORD_MODE) { + selection.state = OmniboxPopupSelection::NORMAL; + omnibox_edit_model_->SetPopupSelection(selection); + } } } void OmniboxController::SetRichSuggestionBitmap(int result_index, const SkBitmap& bitmap) { - DCHECK(omnibox_edit_model_->popup_model()); - omnibox_edit_model_->popup_model()->SetRichSuggestionBitmap(result_index, - bitmap); + omnibox_edit_model_->SetPopupRichSuggestionBitmap(result_index, bitmap); }
diff --git a/components/omnibox/browser/omnibox_edit_model.cc b/components/omnibox/browser/omnibox_edit_model.cc index 95fdf473..9d14d9a 100644 --- a/components/omnibox/browser/omnibox_edit_model.cc +++ b/components/omnibox/browser/omnibox_edit_model.cc
@@ -169,6 +169,10 @@ } } +OmniboxPopupView* OmniboxEditModel::get_popup_view() { + return popup_model_->view(); +} + metrics::OmniboxEventProto::PageClassification OmniboxEditModel::GetPageClassification() const { return controller()->GetLocationBarModel()->GetPageClassification( @@ -1770,6 +1774,12 @@ return popup_model()->StepSelection(direction, step); } +bool OmniboxEditModel::IsPopupControlPresentOnMatch( + OmniboxPopupSelection selection) const { + DCHECK(popup_model()); + return popup_model()->IsControlPresentOnMatch(selection); +} + bool OmniboxEditModel::TriggerPopupSelectionAction( OmniboxPopupSelection selection, base::TimeTicks timestamp, @@ -1793,6 +1803,24 @@ match_text, include_positional_info, label_prefix_length); } +void OmniboxEditModel::OnPopupResultChanged() { + if (popup_model()) { + popup_model()->OnResultChanged(); + } +} + +const SkBitmap* OmniboxEditModel::GetPopupRichSuggestionBitmap( + int result_index) const { + DCHECK(popup_model()); + return popup_model()->RichSuggestionBitmapAt(result_index); +} + +void OmniboxEditModel::SetPopupRichSuggestionBitmap(int result_index, + const SkBitmap& bitmap) { + DCHECK(popup_model()); + popup_model()->SetRichSuggestionBitmap(result_index, bitmap); +} + PrefService* OmniboxEditModel::GetPrefService() const { return autocomplete_controller()->autocomplete_provider_client()->GetPrefs(); }
diff --git a/components/omnibox/browser/omnibox_edit_model.h b/components/omnibox/browser/omnibox_edit_model.h index 78dfc75..ed3fc7d 100644 --- a/components/omnibox/browser/omnibox_edit_model.h +++ b/components/omnibox/browser/omnibox_edit_model.h
@@ -76,6 +76,7 @@ } void set_popup_view(OmniboxPopupView* popup_view); + OmniboxPopupView* get_popup_view(); // NOTE: popup_model() can be NULL for testing. OmniboxPopupModel* popup_model() const { return popup_model_.get(); } @@ -458,6 +459,11 @@ OmniboxPopupSelection::Direction direction, OmniboxPopupSelection::Step step); + // Returns true if the control represented by |selection.state| is present on + // the match in |selection.line|. This is the source-of-truth the UI code + // should query to decide whether or not to draw the control. + bool IsPopupControlPresentOnMatch(OmniboxPopupSelection selection) const; + // On popup, triggers the action on |selection| (usually an auxiliary button). // If the popup model supports the action and performs it, this returns true. // This can't handle all actions currently, and returns false in those cases. @@ -484,6 +490,17 @@ bool include_positional_info, int* label_prefix_length = nullptr); + // Invoked any time the result set of the controller changes. + // TODO(orinj): This method seems like a good candidate for removal; it is + // preserved here only to prevent possible behavior change while refactoring. + void OnPopupResultChanged(); + + // Lookup the bitmap for |result_index|. Returns nullptr if not found. + const SkBitmap* GetPopupRichSuggestionBitmap(int result_index) const; + + // Stores the image in a local data member and schedules a repaint. + void SetPopupRichSuggestionBitmap(int result_index, const SkBitmap& bitmap); + protected: // Utility method to get current PrefService; protected instead of private // because it may be overridden by derived test classes.
diff --git a/components/safe_browsing/content/browser/client_side_model_loader.cc b/components/safe_browsing/content/browser/client_side_model_loader.cc index 9557e7d..69d6862 100644 --- a/components/safe_browsing/content/browser/client_side_model_loader.cc +++ b/components/safe_browsing/content/browser/client_side_model_loader.cc
@@ -70,8 +70,6 @@ "ClientSideDetectionModelOnAndroid"; #endif const char ModelLoader::kClientModelFinchParam[] = "ModelNum"; -const char kUmaModelDownloadResponseMetricName[] = - "SBClientPhishing.ClientModelDownloadResponseOrErrorCode"; // Command-line flag that can be used to override the current CSD model. Must be // provided with an absolute path. @@ -222,9 +220,6 @@ int response_code = 0; if (url_loader_->ResponseInfo() && url_loader_->ResponseInfo()->headers) response_code = url_loader_->ResponseInfo()->headers->response_code(); - V4ProtocolManagerUtil::RecordHttpResponseOrErrorCode( - kUmaModelDownloadResponseMetricName, url_loader_->NetError(), - response_code); // max_age is valid iff !0. base::TimeDelta max_age;
diff --git a/components/safe_browsing/content/browser/password_protection/password_protection_request_content.cc b/components/safe_browsing/content/browser/password_protection/password_protection_request_content.cc index cb2cc36..a7e46fe 100644 --- a/components/safe_browsing/content/browser/password_protection/password_protection_request_content.cc +++ b/components/safe_browsing/content/browser/password_protection/password_protection_request_content.cc
@@ -265,23 +265,10 @@ !password_protection_service()->IsIncognito()) { content::RenderWidgetHostView* view = web_contents_ ? web_contents_->GetRenderWidgetHostView() : nullptr; - base::UmaHistogramBoolean( - "PasswordProtection.AndroidVisualFeaturesViewNull", (view == nullptr)); - if (view) { - base::UmaHistogramBoolean( - "PasswordProtection.AndroidVisualFeaturesNativeViewNull", - (view->GetNativeView() == nullptr)); - } if (view && view->GetNativeView()) { gfx::SizeF content_area_size = view->GetNativeView()->viewport_size(); request_proto_->set_content_area_height(content_area_size.height()); request_proto_->set_content_area_width(content_area_size.width()); - base::UmaHistogramCounts10000( - "PasswordProtection.AndroidVisualFeaturesNativeViewWidth", - content_area_size.width()); - base::UmaHistogramCounts10000( - "PasswordProtection.AndroidVisualFeaturesNativeViewHeight", - content_area_size.height()); } } #endif
diff --git a/components/safe_browsing/content/resources/PRESUBMIT.py b/components/safe_browsing/content/resources/PRESUBMIT.py index dc5d2bfa..6fe451c 100644 --- a/components/safe_browsing/content/resources/PRESUBMIT.py +++ b/components/safe_browsing/content/resources/PRESUBMIT.py
@@ -45,6 +45,19 @@ download_file_types_file.LocalPath() + ' if you are ' 'updating the file types proto.')) + if len(download_file_types_files) == 1: + results.append( + output_api.PresubmitPromptWarning( + 'You only modified either of download_file_types.asciipb or ' + + 'download_file_types_experiment.asciipb, please make sure ' + + 'your change does not affect any ongoing experiment.')) + + results.append( + output_api.PresubmitPromptWarning( + 'Please make sure you have read https://chromium.googlesource.com' + + '/chromium/src/+/HEAD/chrome/browser/resources/safe_browsing/' + + 'README.md before editing the download_file_types config files.')) + return results
diff --git a/content/browser/browser_interface_binders.cc b/content/browser/browser_interface_binders.cc index d777ac54..7545c5e 100644 --- a/content/browser/browser_interface_binders.cc +++ b/content/browser/browser_interface_binders.cc
@@ -27,6 +27,7 @@ #include "content/browser/interest_group/ad_auction_service_impl.h" #include "content/browser/keyboard_lock/keyboard_lock_service_impl.h" #include "content/browser/loader/content_security_notifier.h" +#include "content/browser/media/media_web_contents_observer.h" #include "content/browser/media/midi_host.h" #include "content/browser/media/session/media_session_service_impl.h" #include "content/browser/picture_in_picture/picture_in_picture_service_impl.h" @@ -69,6 +70,7 @@ #include "media/capture/mojom/video_capture.mojom.h" #include "media/mojo/mojom/interface_factory.mojom.h" #include "media/mojo/mojom/media_metrics_provider.mojom.h" +#include "media/mojo/mojom/media_player.mojom.h" #include "media/mojo/mojom/remoting.mojom.h" #include "media/mojo/mojom/video_decode_perf_history.mojom.h" #include "services/device/public/mojom/battery_monitor.mojom.h" @@ -587,6 +589,16 @@ GetDeviceService().BindVibrationManager(std::move(receiver)); } +void BindMediaPlayerObserverClientHandler( + content::RenderFrameHost* frame_host, + mojo::PendingReceiver<media::mojom::MediaPlayerObserverClient> receiver) { + content::WebContentsImpl* web_contents = + static_cast<content::WebContentsImpl*>( + content::WebContents::FromRenderFrameHost(frame_host)); + web_contents->media_web_contents_observer()->BindMediaPlayerObserverClient( + std::move(receiver)); +} + void BindSocketManager( RenderFrameHostImpl* frame, mojo::PendingReceiver<network::mojom::P2PSocketManager> receiver) { @@ -674,6 +686,9 @@ GetIOThreadTaskRunner({})); } + map->Add<media::mojom::MediaPlayerObserverClient>(base::BindRepeating( + &BindMediaPlayerObserverClientHandler, base::Unretained(host))); + map->Add<blink::mojom::NotificationService>(base::BindRepeating( &RenderFrameHostImpl::CreateNotificationService, base::Unretained(host))); @@ -952,6 +967,8 @@ base::BindRepeating( &EmptyBinderForFrame< media::mojom::SpeechRecognitionClientBrowserInterface>)); + map->Add<media::mojom::MediaPlayerObserverClient>(base::BindRepeating( + &EmptyBinderForFrame<media::mojom::MediaPlayerObserverClient>)); #endif #if BUILDFLAG(ENABLE_UNHANDLED_TAP) map->Add<blink::mojom::UnhandledTapNotifier>(base::BindRepeating(
diff --git a/content/browser/child_process_launcher_helper_win.cc b/content/browser/child_process_launcher_helper_win.cc index a89da8e..c6d1bf0 100644 --- a/content/browser/child_process_launcher_helper_win.cc +++ b/content/browser/child_process_launcher_helper_win.cc
@@ -72,11 +72,8 @@ mojo_channel_->PrepareToPassRemoteEndpoint(&handles, command_line()); base::FieldTrialList::AppendFieldTrialHandleIfNeeded(&handles); ChildProcessLauncherHelper::Process process; - *launch_result = StartSandboxedProcess( - delegate_.get(), - command_line(), - handles, - &process.process); + *launch_result = StartSandboxedProcess(delegate_.get(), *command_line(), + handles, &process.process); return process; }
diff --git a/content/browser/media/media_web_contents_observer.cc b/content/browser/media/media_web_contents_observer.cc index 55b8ff5..1edce26 100644 --- a/content/browser/media/media_web_contents_observer.cc +++ b/content/browser/media/media_web_contents_observer.cc
@@ -271,6 +271,17 @@ session_controllers_manager_->WebContentsMutedStateChanged(muted); } +void MediaWebContentsObserver::GetHasPlayedBefore( + GetHasPlayedBeforeCallback callback) { + std::move(callback).Run(has_played_before_); +} + +void MediaWebContentsObserver::BindMediaPlayerObserverClient( + mojo::PendingReceiver<media::mojom::MediaPlayerObserverClient> + pending_receiver) { + receivers_.Add(this, std::move(pending_receiver)); +} + void MediaWebContentsObserver::RequestPersistentVideo(bool value) { if (!fullscreen_player_) return; @@ -442,6 +453,7 @@ if (!player_info->is_playing()) player_info->SetIsPlaying(); + media_web_contents_observer_->OnMediaPlaying(); NotifyAudioStreamMonitorIfNeeded(); } @@ -537,6 +549,10 @@ web_contents_impl()->MediaEffectivelyFullscreenChanged(is_fullscreen); } +void MediaWebContentsObserver::OnMediaPlaying() { + has_played_before_ = true; +} + void MediaWebContentsObserver::OnAudioOutputSinkChanged( const MediaPlayerId& player_id, std::string hashed_device_id) {
diff --git a/content/browser/media/media_web_contents_observer.h b/content/browser/media/media_web_contents_observer.h index a064962..2bcbe3c 100644 --- a/content/browser/media/media_web_contents_observer.h +++ b/content/browser/media/media_web_contents_observer.h
@@ -61,7 +61,9 @@ // browser side. It receives IPC messages from media RenderFrameObservers and // forwards them to the corresponding managers. The managers are responsible // for sending IPCs back to the RenderFrameObservers at the render side. -class CONTENT_EXPORT MediaWebContentsObserver : public WebContentsObserver { +class CONTENT_EXPORT MediaWebContentsObserver + : public WebContentsObserver, + public media::mojom::MediaPlayerObserverClient { public: explicit MediaWebContentsObserver(WebContentsImpl* web_contents); @@ -94,6 +96,13 @@ void MediaPictureInPictureChanged(bool is_picture_in_picture) override; void DidUpdateAudioMutingState(bool muted) override; + // MediaPlayerObserverClient implementation. + void GetHasPlayedBefore(GetHasPlayedBeforeCallback callback) override; + + void BindMediaPlayerObserverClient( + mojo::PendingReceiver<media::mojom::MediaPlayerObserverClient> + pending_receiver); + // TODO(zqzhang): this method is temporarily in MediaWebContentsObserver as // the effectively fullscreen video code is also here. We need to consider // merging the logic of effectively fullscreen, hiding media controls and @@ -255,6 +264,7 @@ void OnMediaEffectivelyFullscreenChanged( const MediaPlayerId& player_id, blink::WebFullscreenVideoStatus fullscreen_status); + void OnMediaPlaying(); void OnAudioOutputSinkChanged(const MediaPlayerId& player_id, std::string hashed_device_id); @@ -285,6 +295,11 @@ // Helper class for recording audible metrics. AudibleMetrics* audible_metrics_; + // A boolean indicating whether media has played before. + bool has_played_before_ = false; + + mojo::ReceiverSet<media::mojom::MediaPlayerObserverClient> receivers_; + // Tracking variables and associated wake locks for media playback. PlayerInfoMap player_info_map_; mojo::Remote<device::mojom::WakeLock> audio_wake_lock_;
diff --git a/content/common/sandbox_init_win.cc b/content/common/sandbox_init_win.cc index 8d8e925..9fb01a2 100644 --- a/content/common/sandbox_init_win.cc +++ b/content/common/sandbox_init_win.cc
@@ -26,29 +26,30 @@ sandbox::ResultCode StartSandboxedProcess( SandboxedProcessLauncherDelegate* delegate, - base::CommandLine* child_command_line, + const base::CommandLine& target_command_line, const base::HandlesToInheritVector& handles_to_inherit, base::Process* process) { std::string type_str = - child_command_line->GetSwitchValueASCII(switches::kProcessType); + target_command_line.GetSwitchValueASCII(switches::kProcessType); TRACE_EVENT1("startup", "StartProcessWithAccess", "type", type_str); // Updates the command line arguments with debug-related flags. If debug // flags have been used with this process, they will be filtered and added - // to child_command_line as needed. - const base::CommandLine* current_command_line = - base::CommandLine::ForCurrentProcess(); - if (current_command_line->HasSwitch(switches::kWaitForDebuggerChildren)) { - std::string value = current_command_line->GetSwitchValueASCII( + // to full_command_line as needed. + const base::CommandLine& current_command_line = + *base::CommandLine::ForCurrentProcess(); + base::CommandLine full_command_line = target_command_line; + if (current_command_line.HasSwitch(switches::kWaitForDebuggerChildren)) { + std::string value = current_command_line.GetSwitchValueASCII( switches::kWaitForDebuggerChildren); - child_command_line->AppendSwitchASCII(switches::kWaitForDebuggerChildren, - value); + full_command_line.AppendSwitchASCII(switches::kWaitForDebuggerChildren, + value); if (value.empty() || value == type_str) - child_command_line->AppendSwitch(switches::kWaitForDebugger); + full_command_line.AppendSwitch(switches::kWaitForDebugger); } return sandbox::policy::SandboxWin::StartSandboxedProcess( - child_command_line, type_str, handles_to_inherit, delegate, process); + full_command_line, type_str, handles_to_inherit, delegate, process); } } // namespace content
diff --git a/content/public/common/sandbox_init.h b/content/public/common/sandbox_init.h index bc576cab..0935e81 100644 --- a/content/public/common/sandbox_init.h +++ b/content/public/common/sandbox_init.h
@@ -47,9 +47,13 @@ // then it just has to outlive this method call. |handles_to_inherit| is a list // of handles for the child process to inherit. The caller retains ownership of // the handles. +// +// Note that calling this function does not always create a sandboxed process, +// as the process might be unsandboxed depending on the behavior of the +// delegate, the command line of the caller, and the command line of the target. CONTENT_EXPORT sandbox::ResultCode StartSandboxedProcess( SandboxedProcessLauncherDelegate* delegate, - base::CommandLine* child_command_line, + const base::CommandLine& target_command_line, const base::HandlesToInheritVector& handles_to_inherit, base::Process* process);
diff --git a/extensions/browser/extension_host.cc b/extensions/browser/extension_host.cc index c273c763c..6596a81 100644 --- a/extensions/browser/extension_host.cc +++ b/extensions/browser/extension_host.cc
@@ -248,10 +248,6 @@ if (first_load) { RecordStopLoadingUMA(); OnDidStopFirstLoad(); - content::NotificationService::current()->Notify( - extensions::NOTIFICATION_EXTENSION_HOST_DID_STOP_FIRST_LOAD, - content::Source<BrowserContext>(browser_context_), - content::Details<ExtensionHost>(this)); ExtensionHostRegistry::Get(browser_context_) ->ExtensionHostCompletedFirstLoad(this); for (auto& observer : observer_list_)
diff --git a/extensions/browser/notification_types.h b/extensions/browser/notification_types.h index 03a1c7d..ed40a53 100644 --- a/extensions/browser/notification_types.h +++ b/extensions/browser/notification_types.h
@@ -60,15 +60,6 @@ // TODO(https://crbug.com/1174736): Remove. NOTIFICATION_EXTENSION_REMOVED, - // Sent by an ExtensionHost* when it has finished its initial page load, - // including any external resources. - // The details are an ExtensionHost* and the source is a BrowserContext*. - // - // DEPRECATED: Use extensions::DeferredStartRenderHostObserver:: - // OnDeferredStartRenderHostDidStopFirstLoad() - // TODO(https://crbug.com/1174741): Remove. - NOTIFICATION_EXTENSION_HOST_DID_STOP_FIRST_LOAD, - // Sent when extension render process ends (whether it crashes or closes). The // details are an ExtensionHost* and the source is a BrowserContext*. Not sent // during browser shutdown.
diff --git a/fuchsia/engine/browser/virtual_keyboard_browsertest.cc b/fuchsia/engine/browser/virtual_keyboard_browsertest.cc index 6baf0ca..9516b69 100644 --- a/fuchsia/engine/browser/virtual_keyboard_browsertest.cc +++ b/fuchsia/engine/browser/virtual_keyboard_browsertest.cc
@@ -137,8 +137,7 @@ // Verifies that RequestShow() is not called redundantly if the virtual // keyboard is reported as visible. -// TODO(https://crbug.com/1226757): Flaky on Fuchsia-x64. -IN_PROC_BROWSER_TEST_F(VirtualKeyboardTest, DISABLED_ShowAndHideWithVisibility) { +IN_PROC_BROWSER_TEST_F(VirtualKeyboardTest, ShowAndHideWithVisibility) { testing::InSequence s; // Alphanumeric field click. @@ -165,6 +164,13 @@ [&on_hide_run_loop]() { on_hide_run_loop.Quit(); })) .RetiresOnSaturation(); + // In some cases, Blink may signal an + // InputMethodClient::OnTextInputTypeChanged event, which will cause + // an extra call to VirtualKeyboardController:RequestHide. This is harmless + // in practice due to RequestHide()'s idempotence, however we still need to + // anticipate that behavior in the controller mocks. + EXPECT_CALL(*controller_, RequestHide()).Times(testing::AtMost(1)); + // Give focus to an alphanumeric input field, which will result in // RequestShow() being called. content::SimulateTapAt(web_contents_,
diff --git a/gpu/command_buffer/service/shared_image_backing_factory_gl_image.cc b/gpu/command_buffer/service/shared_image_backing_factory_gl_image.cc index 37b18c78..0f53c19 100644 --- a/gpu/command_buffer/service/shared_image_backing_factory_gl_image.cc +++ b/gpu/command_buffer/service/shared_image_backing_factory_gl_image.cc
@@ -265,6 +265,12 @@ *allow_legacy_mailbox = gr_context_type == GrContextType::kGL; return true; #else +#if BUILDFLAG(IS_CHROMEOS_ASH) + // On ChromeOS Ash, use only for SHARED_MEMORY gmb + if (gmb_type != gfx::SHARED_MEMORY_BUFFER) { + return false; + } +#endif // Doesn't support contexts other than GL for OOPR Canvas if (gr_context_type != GrContextType::kGL && ((usage & SHARED_IMAGE_USAGE_DISPLAY) || @@ -283,6 +289,7 @@ // return false if it needs interop factory return false; } + *allow_legacy_mailbox = gr_context_type == GrContextType::kGL; return true; #endif
diff --git a/gpu/command_buffer/service/shared_image_backing_factory_ozone.cc b/gpu/command_buffer/service/shared_image_backing_factory_ozone.cc index f13a6ba..33307bd 100644 --- a/gpu/command_buffer/service/shared_image_backing_factory_ozone.cc +++ b/gpu/command_buffer/service/shared_image_backing_factory_ozone.cc
@@ -15,6 +15,7 @@ #include "gpu/command_buffer/service/shared_image_backing_ozone.h" #include "gpu/command_buffer/service/shared_memory_region_wrapper.h" #include "gpu/vulkan/vulkan_device_queue.h" +#include "ui/gfx/buffer_types.h" #include "ui/gfx/gpu_memory_buffer.h" #include "ui/gfx/native_pixmap.h" #include "ui/gl/buildflags.h" @@ -31,8 +32,7 @@ } else if (usage & SHARED_IMAGE_USAGE_SCANOUT) { return gfx::BufferUsage::SCANOUT; } else { - NOTREACHED() << "Unsupported usage flags."; - return gfx::BufferUsage::SCANOUT; + return gfx::BufferUsage::GPU_READ; } } @@ -71,6 +71,12 @@ ui::OzonePlatform::GetInstance()->GetSurfaceFactoryOzone(); scoped_refptr<gfx::NativePixmap> pixmap = surface_factory->CreateNativePixmap( surface_handle, vk_device, size, buffer_format, GetBufferUsage(usage)); + // Fallback to GPU_READ if cannot create pixmap with SCANOUT + if (!pixmap) { + pixmap = surface_factory->CreateNativePixmap(surface_handle, vk_device, + size, buffer_format, + gfx::BufferUsage::GPU_READ); + } if (!pixmap) { return nullptr; } @@ -183,21 +189,6 @@ gmb_type != gfx::SHARED_MEMORY_BUFFER) { return false; } - // TODO(crbug.com/969114): Not all shared image factory implementations - // support concurrent read/write usage. - if (usage & SHARED_IMAGE_USAGE_CONCURRENT_READ_WRITE) { - return false; - } - - // TODO(hitawala): Until SharedImageBackingOzone supports all use cases prefer - // using SharedImageBackingGLImage instead - bool needs_interop_factory = (gr_context_type == GrContextType::kVulkan && - (usage & SHARED_IMAGE_USAGE_DISPLAY)) || - (usage & SHARED_IMAGE_USAGE_WEBGPU) || - (usage & SHARED_IMAGE_USAGE_VIDEO_DECODE); - if (!needs_interop_factory) { - return false; - } *allow_legacy_mailbox = false; return true;
diff --git a/gpu/command_buffer/service/shared_image_backing_ozone.cc b/gpu/command_buffer/service/shared_image_backing_ozone.cc index 39b42ae..1f85356 100644 --- a/gpu/command_buffer/service/shared_image_backing_ozone.cc +++ b/gpu/command_buffer/service/shared_image_backing_ozone.cc
@@ -199,6 +199,7 @@ gfx::BufferFormat buffer_format = viz::BufferFormat(format()); auto image = base::MakeRefCounted<gl::GLImageNativePixmap>( pixmap_->GetBufferSize(), buffer_format); + image->Initialize(std::move(pixmap_)); return std::make_unique<SharedImageRepresentationOverlayOzone>( manager, this, tracker, image); }
diff --git a/gpu/command_buffer/service/shared_image_factory.cc b/gpu/command_buffer/service/shared_image_factory.cc index b41b0952..e21e257 100644 --- a/gpu/command_buffer/service/shared_image_factory.cc +++ b/gpu/command_buffer/service/shared_image_factory.cc
@@ -244,12 +244,9 @@ } #if BUILDFLAG(IS_CHROMEOS_ASH) - if (gpu_preferences.enable_webgpu || - gr_context_type_ == GrContextType::kVulkan) { - auto ozone_factory = - std::make_unique<SharedImageBackingFactoryOzone>(context_state); - factories_.push_back(std::move(ozone_factory)); - } + auto ozone_factory = + std::make_unique<SharedImageBackingFactoryOzone>(context_state); + factories_.push_back(std::move(ozone_factory)); #endif // IS_CHROMEOS_ASH #if defined(OS_FUCHSIA)
diff --git a/gpu/ipc/service/image_transport_surface_overlay_mac.mm b/gpu/ipc/service/image_transport_surface_overlay_mac.mm index 54c5b7b..741c16e 100644 --- a/gpu/ipc/service/image_transport_surface_overlay_mac.mm +++ b/gpu/ipc/service/image_transport_surface_overlay_mac.mm
@@ -398,14 +398,11 @@ } gl_renderer_id_ = context_renderer_id & kCGLRendererIDMatchingMask; - // Post a task holding a reference to the new GL context. The reason for - // this is to avoid creating-then-destroying the context for every image - // transport surface that is observing the GPU switch. - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::BindOnce( - base::DoNothing::Once<scoped_refptr<ui::IOSurfaceContext>>(), - context_on_new_gpu)); + // Delay releasing the reference to the new GL context. The reason for this + // is to avoid creating-then-destroying the context for every image transport + // surface that is observing the GPU switch. + base::ThreadTaskRunnerHandle::Get()->ReleaseSoon( + FROM_HERE, std::move(context_on_new_gpu)); } // Template instantiation
diff --git a/ios/chrome/browser/flags/BUILD.gn b/ios/chrome/browser/flags/BUILD.gn index a155def0..8730e92 100644 --- a/ios/chrome/browser/flags/BUILD.gn +++ b/ios/chrome/browser/flags/BUILD.gn
@@ -59,6 +59,7 @@ "//ios/chrome/browser/ui/download:features", "//ios/chrome/browser/ui/fullscreen:feature_flags", "//ios/chrome/browser/ui/ntp:feature_flags", + "//ios/chrome/browser/ui/overlays/infobar_banner:feature_flags", "//ios/chrome/browser/ui/popup_menu/public:feature_flags", "//ios/chrome/browser/ui/reading_list:features", "//ios/chrome/browser/ui/start_surface:feature_flags",
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm index 0ef5b97..f32aff6 100644 --- a/ios/chrome/browser/flags/about_flags.mm +++ b/ios/chrome/browser/flags/about_flags.mm
@@ -71,6 +71,7 @@ #import "ios/chrome/browser/ui/download/features.h" #import "ios/chrome/browser/ui/fullscreen/fullscreen_features.h" #import "ios/chrome/browser/ui/ntp/new_tab_page_feature.h" +#import "ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_features.h" #import "ios/chrome/browser/ui/popup_menu/public/feature_flags.h" #import "ios/chrome/browser/ui/reading_list/reading_list_features.h" #import "ios/chrome/browser/ui/start_surface/start_surface_features.h" @@ -471,6 +472,10 @@ flag_descriptions::kEnableFullPageScreenshotName, flag_descriptions::kEnableFullPageScreenshotDescription, flags_ui::kOsIos, FEATURE_VALUE_TYPE(kEnableFullPageScreenshot)}, + {"enable-long-message-duration", + flag_descriptions::kEnableLongMessageDurationName, + flag_descriptions::kEnableLongMessageDurationDescription, flags_ui::kOsIos, + FEATURE_VALUE_TYPE(kEnableLongMessageDuration)}, {"enable-optimization-guide", flag_descriptions::kEnableOptimizationGuideName, flag_descriptions::kEnableOptimizationGuideDescription, flags_ui::kOsIos,
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc index 7f2a9a1..79e468dd7 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -194,6 +194,10 @@ "Enables the option of capturing an entire webpage as a PDF when a " "screenshot is taken."; +const char kEnableLongMessageDurationName[] = "Enable long message duration"; +const char kEnableLongMessageDurationDescription[] = + "Enables a long duration when an overlay message is shown."; + const char kEnableManualPasswordGenerationName[] = "Enable manual password generation."; const char kEnableManualPasswordGenerationDescription[] =
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h index 3277d328..ef139bd 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -171,6 +171,10 @@ extern const char kEnableFullPageScreenshotName[]; extern const char kEnableFullPageScreenshotDescription[]; +// Title and description for the flag to enable long message duration. +extern const char kEnableLongMessageDurationName[]; +extern const char kEnableLongMessageDurationDescription[]; + // Title and description for the flag to enable UI that allows the user to // create a strong password even if the field wasn't parsed as a new password // field.
diff --git a/ios/chrome/browser/ui/overlays/infobar_banner/BUILD.gn b/ios/chrome/browser/ui/overlays/infobar_banner/BUILD.gn index 12bba23..9904074 100644 --- a/ios/chrome/browser/ui/overlays/infobar_banner/BUILD.gn +++ b/ios/chrome/browser/ui/overlays/infobar_banner/BUILD.gn
@@ -14,6 +14,17 @@ ] } +source_set("feature_flags") { + sources = [ + "infobar_banner_features.h", + "infobar_banner_features.mm", + ] + + configs += [ "//build/config/compiler:enable_arc" ] + + deps = [ "//base" ] +} + source_set("coordinators") { sources = [ "infobar_banner_overlay_coordinator.h", @@ -23,6 +34,7 @@ configs += [ "//build/config/compiler:enable_arc" ] deps = [ + ":feature_flags", ":mediators", "//base", "//ios/chrome/browser/overlays",
diff --git a/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_features.h b/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_features.h new file mode 100644 index 0000000..7c35b44f --- /dev/null +++ b/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_features.h
@@ -0,0 +1,30 @@ +// Copyright 2021 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. + +#ifndef IOS_CHROME_BROWSER_UI_OVERLAYS_INFOBAR_BANNER_INFOBAR_BANNER_FEATURES_H_ +#define IOS_CHROME_BROWSER_UI_OVERLAYS_INFOBAR_BANNER_INFOBAR_BANNER_FEATURES_H_ + +#include "base/feature_list.h" + +// The feature parameter that indicates the duration of a long presentation +// message. +extern const char kLongPresentationMessagesDurationFeatureParam[]; + +// The feature parameter that indicates the duration of a default +// presentation message. +extern const char kDefaultPresentationMessagesDurationFeatureParam[]; + +// The feature to enable long message duration +extern const base::Feature kEnableLongMessageDuration; + +// Checks whether the long message duration feature is enabled. +bool IsLongMessageDurationEnabled(); + +// Returns the duration of the default presentation messages. +double GetDefaultPresentationMessageDuration(); + +// Returns the duration of the long presentation messages. +double GetLongPresentationMessageDuration(); + +#endif // IOS_CHROME_BROWSER_UI_OVERLAYS_INFOBAR_BANNER_INFOBAR_BANNER_FEATURES_H_
diff --git a/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_features.mm b/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_features.mm new file mode 100644 index 0000000..eb167d96 --- /dev/null +++ b/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_features.mm
@@ -0,0 +1,35 @@ +// Copyright 2021 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. + +#import "ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_features.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +const base::Feature kEnableLongMessageDuration{ + "EnableLongMessageDuration", base::FEATURE_DISABLED_BY_DEFAULT}; + +const char kLongPresentationMessagesDurationFeatureParam[] = + "LongPresentationMessagesDurationFeatureParam"; + +const char kDefaultPresentationMessagesDurationFeatureParam[] = + "DefaultPresentationMessagesDurationFeatureParam"; + +bool IsLongMessageDurationEnabled() { + return base::FeatureList::IsEnabled(kEnableLongMessageDuration); +} + +double GetDefaultPresentationMessageDuration() { + return base::GetFieldTrialParamByFeatureAsDouble( + kEnableLongMessageDuration, + kDefaultPresentationMessagesDurationFeatureParam, + 15 /*default to 15 second*/); +} + +double GetLongPresentationMessageDuration() { + return base::GetFieldTrialParamByFeatureAsDouble( + kEnableLongMessageDuration, kLongPresentationMessagesDurationFeatureParam, + 20 /*default to 20 second*/); +}
diff --git a/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_coordinator.mm b/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_coordinator.mm index ae964bd8..4d2714b 100644 --- a/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_coordinator.mm +++ b/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_coordinator.mm
@@ -18,6 +18,7 @@ #import "ios/chrome/browser/ui/infobars/presentation/infobar_banner_transition_driver.h" #import "ios/chrome/browser/ui/overlays/infobar_banner/autofill_address_profile/save_address_profile_infobar_banner_overlay_mediator.h" #import "ios/chrome/browser/ui/overlays/infobar_banner/confirm/confirm_infobar_banner_overlay_mediator.h" +#import "ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_features.h" #import "ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_mediator.h" #import "ios/chrome/browser/ui/overlays/infobar_banner/passwords/save_password_infobar_banner_overlay_mediator.h" #import "ios/chrome/browser/ui/overlays/infobar_banner/passwords/update_password_infobar_banner_overlay_mediator.h" @@ -119,12 +120,19 @@ self.started = YES; if (!UIAccessibilityIsVoiceOverRunning()) { - // Auto-dismiss the banner after timeout if VoiceOver is off (banner should - // persist until user explicitly swipes it away). - NSTimeInterval timeout = - config->is_high_priority() - ? kInfobarBannerLongPresentationDurationInSeconds - : kInfobarBannerDefaultPresentationDurationInSeconds; + NSTimeInterval timeout; + if (IsLongMessageDurationEnabled()) { + // If long message duration is enabled, set a longer timeout. + timeout = config->is_high_priority() + ? GetLongPresentationMessageDuration() + : GetDefaultPresentationMessageDuration(); + } else { + // Auto-dismiss the banner after timeout if VoiceOver is off (banner + // should persist until user explicitly swipes it away). + timeout = config->is_high_priority() + ? kInfobarBannerLongPresentationDurationInSeconds + : kInfobarBannerDefaultPresentationDurationInSeconds; + } [self performSelector:@selector(dismissBannerIfReady) withObject:nil afterDelay:timeout];
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 new file mode 100644 index 0000000..824b610e --- /dev/null +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
@@ -0,0 +1 @@ +21f3b0fc61895a2d6633ffb8f433ae54fd622a2e \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 new file mode 100644 index 0000000..12bce17 --- /dev/null +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
@@ -0,0 +1 @@ +821c52f56c62f19e2335510e7fd1e0023750c389 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 new file mode 100644 index 0000000..c09acdb --- /dev/null +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
@@ -0,0 +1 @@ +25d38ea705b6018d6e16f50d49e31b1fea12439a \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 new file mode 100644 index 0000000..75a5ff5 --- /dev/null +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
@@ -0,0 +1 @@ +558c9557211debb25c0a7bca2f46b075c87fa8f6 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 new file mode 100644 index 0000000..46d855a3 --- /dev/null +++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
@@ -0,0 +1 @@ +cc3261714b58e88b96c0a474d119a1bf11d2eb6f \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 new file mode 100644 index 0000000..2b6e4cb --- /dev/null +++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
@@ -0,0 +1 @@ +4c695b9ff8bb0b8a97c225945995358730b6c51e \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 new file mode 100644 index 0000000..81cb7ca --- /dev/null +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
@@ -0,0 +1 @@ +ca91d9a136985387dfbff8be623271744f155f5e \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 new file mode 100644 index 0000000..a3438b0 --- /dev/null +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
@@ -0,0 +1 @@ +61610936ac0a2e0816d1594eea6ca05bd50fa7fc \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 new file mode 100644 index 0000000..7853209 --- /dev/null +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
@@ -0,0 +1 @@ +b1895ea885d05284b156c723951d841a9c4726c4 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 new file mode 100644 index 0000000..c7a5690 --- /dev/null +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
@@ -0,0 +1 @@ +245a2d4b7b0061a5f6223ddb9e1aa2be970a8cbc \ No newline at end of file
diff --git a/media/mojo/mojom/media_player.mojom b/media/mojo/mojom/media_player.mojom index fe8f5ee..83f8ade 100644 --- a/media/mojo/mojom/media_player.mojom +++ b/media/mojo/mojom/media_player.mojom
@@ -56,6 +56,13 @@ SuspendForFrameClosed(); }; +// Implemented by the MediaWebContentsObserver. The remote lives in the renderer +// process and the receiver lives in the browser process. +interface MediaPlayerObserverClient { + // Gets a flag indicating whether media has been played before. + GetHasPlayedBefore() => (bool has_played_before); +}; + // Implemented by MediaWebContentsObserver::MediaPlayerObserverHostImpl in the // browser process. interface MediaPlayerObserver {
diff --git a/sandbox/policy/win/sandbox_win.cc b/sandbox/policy/win/sandbox_win.cc index 4dacb688..fd87f29d 100644 --- a/sandbox/policy/win/sandbox_win.cc +++ b/sandbox/policy/win/sandbox_win.cc
@@ -433,7 +433,7 @@ base::UmaHistogramSparse("Process.Sandbox.Launch.Warning", last_error); } -ResultCode AddPolicyForSandboxedProcess(TargetPolicy* policy) { +ResultCode AddDefaultPolicyForSandboxedProcess(TargetPolicy* policy) { ResultCode result = sandbox::SBOX_ALL_OK; // Win8+ adds a device DeviceApi that we don't need. @@ -767,7 +767,7 @@ // a Policy or TargetProcess. This supports both kNoSandbox and the --no-sandbox // command line flag. ResultCode LaunchWithoutSandbox( - base::CommandLine* cmd_line, + const base::CommandLine& cmd_line, const base::HandlesToInheritVector& handles_to_inherit, SandboxDelegate* delegate, base::Process* process) { @@ -799,17 +799,30 @@ // are not. When --no-sandbox is specified we disable CET for all children. // Otherwise we are here because the sandbox type is kNoSandbox, and allow // the process delegate to indicate if it is compatible with CET. - if (cmd_line->HasSwitch(switches::kNoSandbox) || + if (cmd_line.HasSwitch(switches::kNoSandbox) || base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoSandbox)) { options.disable_cetcompat = true; } else if (!delegate->CetCompatible()) { options.disable_cetcompat = true; } - *process = base::LaunchProcess(*cmd_line, options); + *process = base::LaunchProcess(cmd_line, options); return SBOX_ALL_OK; } +bool IsUnsandboxedProcess( + SandboxType sandbox_type, + const base::CommandLine& cmd_line, + const base::CommandLine& launcher_process_command_line) { + if (IsUnsandboxedSandboxType(sandbox_type)) + return true; + if (cmd_line.HasSwitch(switches::kNoSandbox)) + return true; + if (launcher_process_command_line.HasSwitch(switches::kNoSandbox)) + return true; + return false; +} + } // namespace // static @@ -977,29 +990,27 @@ } // static -ResultCode SandboxWin::StartSandboxedProcess( - base::CommandLine* cmd_line, +ResultCode SandboxWin::GeneratePolicyForSandboxedProcess( + const base::CommandLine& cmd_line, const std::string& process_type, const base::HandlesToInheritVector& handles_to_inherit, SandboxDelegate* delegate, - base::Process* process) { + const scoped_refptr<TargetPolicy>& policy) { const base::CommandLine& launcher_process_command_line = *base::CommandLine::ForCurrentProcess(); SandboxType sandbox_type = delegate->GetSandboxType(); - // --no-sandbox and kNoSandbox are launched without creating a Policy. - if (IsUnsandboxedSandboxType(sandbox_type) || - cmd_line->HasSwitch(switches::kNoSandbox) || - launcher_process_command_line.HasSwitch(switches::kNoSandbox)) { - return LaunchWithoutSandbox(cmd_line, handles_to_inherit, delegate, - process); + // --no-sandbox and kNoSandbox are launched without a policy. + if (IsUnsandboxedProcess(sandbox_type, cmd_line, + launcher_process_command_line)) { + return ResultCode::SBOX_ERROR_UNSANDBOXED_PROCESS; } - scoped_refptr<TargetPolicy> policy = g_broker_services->CreatePolicy(); - // Allow no sandbox job if the --allow-no-sandbox-job switch is present. - if (launcher_process_command_line.HasSwitch(switches::kAllowNoSandboxJob)) + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kAllowNoSandboxJob)) { policy->SetAllowNoSandboxJob(); + } // Add any handles to be inherited to the policy. for (HANDLE handle : handles_to_inherit) @@ -1038,7 +1049,7 @@ // Post-startup mitigations. mitigations = MITIGATION_DLL_SEARCH_ORDER; - if (!cmd_line->HasSwitch(switches::kAllowThirdPartyModules) && + if (!cmd_line.HasSwitch(switches::kAllowThirdPartyModules) && sandbox_type != SandboxType::kSpeechRecognition) { mitigations |= MITIGATION_FORCE_MS_SIGNED_BINS; } @@ -1053,12 +1064,12 @@ if (result != SBOX_ALL_OK) return result; - result = SetJobLevel(*cmd_line, JOB_LOCKDOWN, 0, policy.get()); + result = SetJobLevel(cmd_line, JOB_LOCKDOWN, 0, policy.get()); if (result != SBOX_ALL_OK) return result; if (!delegate->DisableDefaultPolicy()) { - result = AddPolicyForSandboxedProcess(policy.get()); + result = AddDefaultPolicyForSandboxedProcess(policy.get()); if (result != SBOX_ALL_OK) return result; } @@ -1086,9 +1097,9 @@ } std::string appcontainer_id; - if (IsAppContainerEnabledForSandbox(*cmd_line, sandbox_type) && + if (IsAppContainerEnabledForSandbox(cmd_line, sandbox_type) && delegate->GetAppContainerId(&appcontainer_id)) { - result = AddAppContainerProfileToPolicy(*cmd_line, sandbox_type, + result = AddAppContainerProfileToPolicy(cmd_line, sandbox_type, appcontainer_id, policy.get()); DCHECK(result == SBOX_ALL_OK); if (result != SBOX_ALL_OK) @@ -1128,14 +1139,35 @@ if (!delegate->PreSpawnTarget(policy.get())) return SBOX_ERROR_DELEGATE_PRE_SPAWN; + return result; +} + +// static +ResultCode SandboxWin::StartSandboxedProcess( + const base::CommandLine& cmd_line, + const std::string& process_type, + const base::HandlesToInheritVector& handles_to_inherit, + SandboxDelegate* delegate, + base::Process* process) { + scoped_refptr<TargetPolicy> policy = g_broker_services->CreatePolicy(); + ResultCode result = GeneratePolicyForSandboxedProcess( + cmd_line, process_type, handles_to_inherit, delegate, policy); + + if (ResultCode::SBOX_ERROR_UNSANDBOXED_PROCESS == result) { + return LaunchWithoutSandbox(cmd_line, handles_to_inherit, delegate, + process); + } + if (SBOX_ALL_OK != result) + return result; + TRACE_EVENT_BEGIN0("startup", "StartProcessWithAccess::LAUNCHPROCESS"); PROCESS_INFORMATION temp_process_info = {}; ResultCode last_warning = sandbox::SBOX_ALL_OK; DWORD last_error = ERROR_SUCCESS; result = g_broker_services->SpawnTarget( - cmd_line->GetProgram().value().c_str(), - cmd_line->GetCommandLineString().c_str(), policy, &last_warning, + cmd_line.GetProgram().value().c_str(), + cmd_line.GetCommandLineString().c_str(), policy, &last_warning, &last_error, &temp_process_info); base::win::ScopedProcessInformation target(temp_process_info); @@ -1162,7 +1194,7 @@ base::debug::GlobalActivityTracker::Get(); if (tracker) { tracker->RecordProcessLaunch(target.process_id(), - cmd_line->GetCommandLineString()); + cmd_line.GetCommandLineString()); } if (SBOX_ALL_OK != last_warning)
diff --git a/sandbox/policy/win/sandbox_win.h b/sandbox/policy/win/sandbox_win.h index bdc7672..167e557e 100644 --- a/sandbox/policy/win/sandbox_win.h +++ b/sandbox/policy/win/sandbox_win.h
@@ -35,13 +35,34 @@ class SANDBOX_POLICY_EXPORT SandboxWin { public: + // Create a sandboxed process `process` with the specified `cmd_line` of type + // `process_type` (e.g. 'renderer' or 'utility'). `handles_to_inherit` + // specifies a set of handles to inherit. `delegate` specifies the sandbox + // delegate to use when resolving specific sandbox policy. + // + // Returns SBOX_ALL_OK if the process was successfully created. + // Otherwise, returns one of sandbox::ResultCode for any other error. static ResultCode StartSandboxedProcess( - base::CommandLine* cmd_line, + const base::CommandLine& cmd_line, const std::string& process_type, const base::HandlesToInheritVector& handles_to_inherit, SandboxDelegate* delegate, base::Process* process); + // Generates a sandbox policy into `policy` to match the one that would be + // applied during `StartSandboxedProcess` for the identical set of arguments. + // + // Returns SBOX_ALL_OK if the policy was successfully generated. + // Returns SBOX_ERROR_UNSANDBOXED_PROCESS if the process has no valid + // sandbox policy because it should be run unsandboxed, otherwise returns one + // of sandbox::ResultCode for any other error while constructing the policy. + static ResultCode GeneratePolicyForSandboxedProcess( + const base::CommandLine& cmd_line, + const std::string& process_type, + const base::HandlesToInheritVector& handles_to_inherit, + SandboxDelegate* delegate, + const scoped_refptr<TargetPolicy>& policy); + // Wrapper around TargetPolicy::SetJobLevel that checks if the // sandbox should be let to run without a job object assigned. static ResultCode SetJobLevel(const base::CommandLine& cmd_line,
diff --git a/sandbox/policy/win/sandbox_win_unittest.cc b/sandbox/policy/win/sandbox_win_unittest.cc index 1d4e9a7..87638d9 100644 --- a/sandbox/policy/win/sandbox_win_unittest.cc +++ b/sandbox/policy/win/sandbox_win_unittest.cc
@@ -28,11 +28,16 @@ #include "sandbox/policy/sandbox_type.h" #include "sandbox/policy/switches.h" #include "sandbox/win/src/app_container_base.h" +#include "sandbox/win/src/sandbox_factory.h" #include "sandbox/win/src/sandbox_policy.h" #include "sandbox/win/src/sandbox_policy_diagnostic.h" #include "sandbox/win/src/sid.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +using ::testing::_; +using ::testing::Return; + namespace sandbox { namespace policy { @@ -390,5 +395,66 @@ } } +// Sandbox can't reach into content to pull the real policies, so these tests +// merely verifies that various parts of the delegate are called correctly and a +// policy can be generated. +class TestSandboxDelegate : public SandboxDelegate { + public: + TestSandboxDelegate(SandboxType sandbox_type) : sandbox_type_(sandbox_type) {} + SandboxType GetSandboxType() override { return sandbox_type_; } + bool DisableDefaultPolicy() override { return false; } + bool GetAppContainerId(std::string* appcontainer_id) override { + NOTREACHED(); + return false; + } + + MOCK_METHOD1(PreSpawnTarget, bool(TargetPolicy* policy)); + + void PostSpawnTarget(base::ProcessHandle process) override {} + + bool ShouldUnsandboxedRunInJob() override { return false; } + + bool CetCompatible() override { return true; } + + private: + SandboxType sandbox_type_; +}; + +TEST_F(SandboxWinTest, GeneratedPolicyTest) { + TestSandboxDelegate test_renderer_delegate(SandboxType::kRenderer); + base::CommandLine cmd_line(base::CommandLine::NO_PROGRAM); + base::HandlesToInheritVector handles_to_inherit; + BrokerServices* broker = SandboxFactory::GetBrokerServices(); + scoped_refptr<TargetPolicy> policy = broker->CreatePolicy(); + // PreSpawn should get called, but not modifying the policy for this test. + EXPECT_CALL(test_renderer_delegate, PreSpawnTarget(_)).WillOnce(Return(true)); + ResultCode result = SandboxWin::GeneratePolicyForSandboxedProcess( + cmd_line, switches::kRendererProcess, handles_to_inherit, + &test_renderer_delegate, policy); + ASSERT_EQ(ResultCode::SBOX_ALL_OK, result); + // Check some default values come back. No need to check the exact policy in + // detail, but just that GeneratePolicyForSandboxedProcess generated some kind + // of valid policy. + EXPECT_EQ(IntegrityLevel::INTEGRITY_LEVEL_LOW, policy->GetIntegrityLevel()); + EXPECT_EQ(JobLevel::JOB_LOCKDOWN, policy->GetJobLevel()); + EXPECT_EQ(TokenLevel::USER_LOCKDOWN, policy->GetLockdownTokenLevel()); +} + +TEST_F(SandboxWinTest, GeneratedPolicyTestNoSandbox) { + TestSandboxDelegate test_unsandboxed_delegate(SandboxType::kNoSandbox); + base::CommandLine cmd_line(base::CommandLine::NO_PROGRAM); + base::HandlesToInheritVector handles_to_inherit; + BrokerServices* broker = SandboxFactory::GetBrokerServices(); + scoped_refptr<TargetPolicy> policy = broker->CreatePolicy(); + // Unsandboxed processes never call the delegate prespawn as there is no + // policy. + EXPECT_CALL(test_unsandboxed_delegate, PreSpawnTarget(_)).Times(0); + + ResultCode result = SandboxWin::GeneratePolicyForSandboxedProcess( + cmd_line, switches::kRendererProcess, handles_to_inherit, + &test_unsandboxed_delegate, policy); + ASSERT_EQ(ResultCode::SBOX_ERROR_UNSANDBOXED_PROCESS, result); +} + } // namespace policy } // namespace sandbox
diff --git a/sandbox/win/src/sandbox_types.h b/sandbox/win/src/sandbox_types.h index 5b6ab9f..5c959ec 100644 --- a/sandbox/win/src/sandbox_types.h +++ b/sandbox/win/src/sandbox_types.h
@@ -143,6 +143,8 @@ SBOX_ERROR_CANNOT_UPDATE_JOB_PROCESS_LIMIT = 60, // Cannot create an impersonation lowbox token SBOX_ERROR_CANNOT_CREATE_LOWBOX_IMPERSONATION_TOKEN = 61, + // Cannot create a sandbox policy for an unsandboxed process. + SBOX_ERROR_UNSANDBOXED_PROCESS = 62, // Placeholder for last item of the enum. SBOX_ERROR_LAST };
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json index 03f86e5..097c053 100644 --- a/testing/buildbot/chromium.android.fyi.json +++ b/testing/buildbot/chromium.android.fyi.json
@@ -5693,7 +5693,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M94", - "revision": "version:94.0.4606.63" + "revision": "version:94.0.4606.64" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -5780,7 +5780,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M95", - "revision": "version:95.0.4638.24" + "revision": "version:95.0.4638.25" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -5954,7 +5954,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M94", - "revision": "version:94.0.4606.63" + "revision": "version:94.0.4606.64" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -6041,7 +6041,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M95", - "revision": "version:95.0.4638.24" + "revision": "version:95.0.4638.25" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json index 4b952b5..7fb1ee0 100644 --- a/testing/buildbot/chromium.android.json +++ b/testing/buildbot/chromium.android.json
@@ -56581,7 +56581,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M94", - "revision": "version:94.0.4606.63" + "revision": "version:94.0.4606.64" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -56669,7 +56669,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M95", - "revision": "version:95.0.4638.24" + "revision": "version:95.0.4638.25" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -56845,7 +56845,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M94", - "revision": "version:94.0.4606.63" + "revision": "version:94.0.4606.64" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -56933,7 +56933,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M95", - "revision": "version:95.0.4638.24" + "revision": "version:95.0.4638.25" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -57182,7 +57182,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M94", - "revision": "version:94.0.4606.63" + "revision": "version:94.0.4606.64" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -57269,7 +57269,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M95", - "revision": "version:95.0.4638.24" + "revision": "version:95.0.4638.25" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -57443,7 +57443,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M94", - "revision": "version:94.0.4606.63" + "revision": "version:94.0.4606.64" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -57530,7 +57530,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M95", - "revision": "version:95.0.4638.24" + "revision": "version:95.0.4638.25" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -57779,7 +57779,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M94", - "revision": "version:94.0.4606.63" + "revision": "version:94.0.4606.64" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -57866,7 +57866,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M95", - "revision": "version:95.0.4638.24" + "revision": "version:95.0.4638.25" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -58040,7 +58040,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M94", - "revision": "version:94.0.4606.63" + "revision": "version:94.0.4606.64" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -58127,7 +58127,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M95", - "revision": "version:95.0.4638.24" + "revision": "version:95.0.4638.25" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json index 5332bb3..dd257c73 100644 --- a/testing/buildbot/chromium.chromiumos.json +++ b/testing/buildbot/chromium.chromiumos.json
@@ -5840,21 +5840,21 @@ }, { "args": [ - "--ash-chrome-path-override=../../lacros_version_skew_tests_v94.0.4606.50/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v94.0.4606.58/test_ash_chrome", "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests_Lacros version skew testing ash 94.0.4606.50", + "name": "lacros_chrome_browsertests_Lacros version skew testing ash 94.0.4606.58", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v94.0.4606.50", - "revision": "version:94.0.4606.50" + "location": "lacros_version_skew_tests_v94.0.4606.58", + "revision": "version:94.0.4606.58" } ], "dimension_sets": [ @@ -5898,21 +5898,21 @@ }, { "args": [ - "--ash-chrome-path-override=../../lacros_version_skew_tests_v96.0.4652.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v96.0.4653.0/test_ash_chrome", "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests_Lacros version skew testing ash 96.0.4652.0", + "name": "lacros_chrome_browsertests_Lacros version skew testing ash 96.0.4653.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v96.0.4652.0", - "revision": "version:96.0.4652.0" + "location": "lacros_version_skew_tests_v96.0.4653.0", + "revision": "version:96.0.4653.0" } ], "dimension_sets": [ @@ -5948,21 +5948,21 @@ }, { "args": [ - "--ash-chrome-path-override=../../lacros_version_skew_tests_v94.0.4606.50/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v94.0.4606.58/test_ash_chrome", "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests_run_in_series_Lacros version skew testing ash 94.0.4606.50", + "name": "lacros_chrome_browsertests_run_in_series_Lacros version skew testing ash 94.0.4606.58", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v94.0.4606.50", - "revision": "version:94.0.4606.50" + "location": "lacros_version_skew_tests_v94.0.4606.58", + "revision": "version:94.0.4606.58" } ], "dimension_sets": [ @@ -6006,21 +6006,21 @@ }, { "args": [ - "--ash-chrome-path-override=../../lacros_version_skew_tests_v96.0.4652.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v96.0.4653.0/test_ash_chrome", "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests_run_in_series_Lacros version skew testing ash 96.0.4652.0", + "name": "lacros_chrome_browsertests_run_in_series_Lacros version skew testing ash 96.0.4653.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v96.0.4652.0", - "revision": "version:96.0.4652.0" + "location": "lacros_version_skew_tests_v96.0.4653.0", + "revision": "version:96.0.4653.0" } ], "dimension_sets": [
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 51cfa68..1493f84 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -27033,9 +27033,6 @@ ], "gtest_tests": [ { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27054,9 +27051,6 @@ "test_id_prefix": "ninja://third_party/abseil-cpp:absl_hardening_tests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27075,9 +27069,6 @@ "test_id_prefix": "ninja://ui/accessibility:accessibility_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27096,9 +27087,6 @@ "test_id_prefix": "ninja://ui/aura:aura_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27117,9 +27105,6 @@ "test_id_prefix": "ninja://base:base_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27138,9 +27123,6 @@ "test_id_prefix": "ninja://third_party/blink/common:blink_common_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27159,9 +27141,6 @@ "test_id_prefix": "ninja://third_party/blink/renderer/platform/heap:blink_heap_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27181,8 +27160,7 @@ }, { "args": [ - "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.blink_unittests.filter", - "--device=fvdl" + "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.blink_unittests.filter" ], "merge": { "args": [], @@ -27202,9 +27180,6 @@ "test_id_prefix": "ninja://third_party/blink/renderer/controller:blink_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27223,9 +27198,6 @@ "test_id_prefix": "ninja://third_party/boringssl:boringssl_crypto_tests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27244,9 +27216,6 @@ "test_id_prefix": "ninja://third_party/boringssl:boringssl_ssl_tests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27265,9 +27234,6 @@ "test_id_prefix": "ninja://media/capture:capture_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27286,9 +27252,6 @@ "test_id_prefix": "ninja://fuchsia/runners:cast_runner_browsertests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27307,9 +27270,6 @@ "test_id_prefix": "ninja://fuchsia/runners:cast_runner_integration_tests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27328,9 +27288,6 @@ "test_id_prefix": "ninja://fuchsia/runners:cast_runner_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27350,9 +27307,6 @@ "test_id_prefix": "ninja://cc:cc_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27371,9 +27325,6 @@ "test_id_prefix": "ninja://ui/color:color_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27393,8 +27344,7 @@ }, { "args": [ - "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.content_unittests.filter", - "--device=fvdl" + "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.content_unittests.filter" ], "merge": { "args": [], @@ -27414,9 +27364,6 @@ "test_id_prefix": "ninja://content/test:content_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27435,9 +27382,6 @@ "test_id_prefix": "ninja://courgette:courgette_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27456,9 +27400,6 @@ "test_id_prefix": "ninja://fuchsia/base:cr_fuchsia_base_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27477,9 +27418,6 @@ "test_id_prefix": "ninja://components/cronet:cronet_tests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27498,9 +27436,6 @@ "test_id_prefix": "ninja://components/cronet:cronet_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27519,9 +27454,6 @@ "test_id_prefix": "ninja://crypto:crypto_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27540,9 +27472,6 @@ "test_id_prefix": "ninja://ui/display:display_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27561,9 +27490,6 @@ "test_id_prefix": "ninja://ui/events:events_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27582,9 +27508,6 @@ "test_id_prefix": "ninja://extensions:extensions_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27603,9 +27526,6 @@ "test_id_prefix": "ninja://fuchsia/mojom:fuchsia_mojo_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27624,9 +27544,6 @@ "test_id_prefix": "ninja://google_apis/gcm:gcm_unit_tests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27645,9 +27562,6 @@ "test_id_prefix": "ninja://ui/gfx:gfx_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27666,9 +27580,6 @@ "test_id_prefix": "ninja://gin:gin_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27687,9 +27598,6 @@ "test_id_prefix": "ninja://google_apis:google_apis_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27708,9 +27616,6 @@ "test_id_prefix": "ninja://gpu:gpu_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27730,8 +27635,7 @@ }, { "args": [ - "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.headless_browsertests.filter", - "--device=fvdl" + "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.headless_browsertests.filter" ], "merge": { "args": [], @@ -27751,9 +27655,6 @@ "test_id_prefix": "ninja://headless:headless_browsertests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27772,9 +27673,6 @@ "test_id_prefix": "ninja://headless:headless_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27793,9 +27691,6 @@ "test_id_prefix": "ninja://fuchsia/http:http_service_tests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27815,8 +27710,7 @@ }, { "args": [ - "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.jingle_unittests.filter", - "--device=fvdl" + "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.jingle_unittests.filter" ], "merge": { "args": [], @@ -27836,9 +27730,6 @@ "test_id_prefix": "ninja://jingle:jingle_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27857,9 +27748,6 @@ "test_id_prefix": "ninja://ui/latency:latency_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27878,9 +27766,6 @@ "test_id_prefix": "ninja://media:media_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27899,9 +27784,6 @@ "test_id_prefix": "ninja://ui/message_center:message_center_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27920,9 +27802,6 @@ "test_id_prefix": "ninja://media/midi:midi_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27941,9 +27820,6 @@ "test_id_prefix": "ninja://mojo:mojo_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -27963,8 +27839,7 @@ }, { "args": [ - "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.net_unittests.filter", - "--device=fvdl" + "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.net_unittests.filter" ], "merge": { "args": [], @@ -27986,8 +27861,7 @@ }, { "args": [ - "--child-arg=--ozone-platform=headless", - "--device=fvdl" + "--child-arg=--ozone-platform=headless" ], "merge": { "args": [], @@ -28007,9 +27881,6 @@ "test_id_prefix": "ninja://ui/ozone/gl:ozone_gl_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -28028,9 +27899,6 @@ "test_id_prefix": "ninja://ui/ozone:ozone_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -28049,9 +27917,6 @@ "test_id_prefix": "ninja://third_party/perfetto:perfetto_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -28071,8 +27936,7 @@ }, { "args": [ - "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.services_unittests.filter", - "--device=fvdl" + "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.services_unittests.filter" ], "merge": { "args": [], @@ -28092,9 +27956,6 @@ "test_id_prefix": "ninja://services:services_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -28113,9 +27974,6 @@ "test_id_prefix": "ninja://ui/shell_dialogs:shell_dialogs_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -28134,9 +27992,6 @@ "test_id_prefix": "ninja://skia:skia_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -28155,9 +28010,6 @@ "test_id_prefix": "ninja://ui/snapshot:snapshot_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -28177,8 +28029,7 @@ }, { "args": [ - "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.storage_unittests.filter", - "--device=fvdl" + "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.storage_unittests.filter" ], "merge": { "args": [], @@ -28199,8 +28050,7 @@ }, { "args": [ - "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.ui_base_unittests.filter", - "--device=fvdl" + "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.ui_base_unittests.filter" ], "merge": { "args": [], @@ -28220,9 +28070,6 @@ "test_id_prefix": "ninja://ui/base:ui_base_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -28241,9 +28088,6 @@ "test_id_prefix": "ninja://ui/touch_selection:ui_touch_selection_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -28263,8 +28107,7 @@ }, { "args": [ - "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.views_examples_unittests.filter", - "--device=fvdl" + "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.views_examples_unittests.filter" ], "merge": { "args": [], @@ -28285,8 +28128,7 @@ }, { "args": [ - "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.views_unittests.filter", - "--device=fvdl" + "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.views_unittests.filter" ], "merge": { "args": [], @@ -28307,8 +28149,7 @@ }, { "args": [ - "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.viz_unittests.filter", - "--device=fvdl" + "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.viz_unittests.filter" ], "merge": { "args": [], @@ -28328,9 +28169,6 @@ "test_id_prefix": "ninja://components/viz:viz_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -28350,8 +28188,7 @@ }, { "args": [ - "--child-arg=--vmodule=test_navigation_listener=1", - "--device=fvdl" + "--child-arg=--vmodule=test_navigation_listener=1" ], "merge": { "args": [], @@ -28371,9 +28208,6 @@ "test_id_prefix": "ninja://fuchsia/engine:web_engine_integration_tests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -28392,9 +28226,6 @@ "test_id_prefix": "ninja://fuchsia/engine:web_engine_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -28413,9 +28244,6 @@ "test_id_prefix": "ninja://fuchsia/runners:web_runner_integration_tests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -28434,9 +28262,6 @@ "test_id_prefix": "ninja://ui/wm:wm_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -28455,9 +28280,6 @@ "test_id_prefix": "ninja://third_party/blink/renderer/platform/wtf:wtf_unittests/" }, { - "args": [ - "--device=fvdl" - ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -28480,7 +28302,6 @@ { "args": [ "bin/run_angle_unittests", - "--device=fvdl", "--logs-dir=${ISOLATED_OUTDIR}/logs" ], "isolate_name": "angle_unittests", @@ -28510,8 +28331,7 @@ "gtest_tests": [ { "args": [ - "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.components_unittests.filter", - "--device=fvdl" + "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.components_unittests.filter" ], "merge": { "args": [], @@ -28532,8 +28352,7 @@ }, { "args": [ - "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.unit_tests.filter", - "--device=fvdl" + "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.unit_tests.filter" ], "merge": { "args": [], @@ -28561,8 +28380,7 @@ "--browser=web-engine-shell", "--passthrough", "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating", - "--device=fvdl" + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating" ], "isolate_name": "fuchsia_telemetry_gpu_integration_test", "merge": { @@ -28595,8 +28413,7 @@ "--browser=web-engine-shell", "--passthrough", "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--device=fvdl" + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" ], "isolate_name": "fuchsia_telemetry_gpu_integration_test", "merge": { @@ -28629,8 +28446,7 @@ "--browser=web-engine-shell", "--passthrough", "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--device=fvdl" + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" ], "isolate_name": "fuchsia_telemetry_gpu_integration_test", "merge": { @@ -28663,8 +28479,7 @@ "--browser=web-engine-shell", "--passthrough", "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--device=fvdl" + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" ], "isolate_name": "fuchsia_telemetry_gpu_integration_test", "merge": { @@ -28701,8 +28516,7 @@ "--expected-vendor-id", "0", "--expected-device-id", - "0", - "--device=fvdl" + "0" ], "isolate_name": "fuchsia_telemetry_gpu_integration_test", "merge": { @@ -28736,7 +28550,6 @@ "--passthrough", "-v", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--device=fvdl", "--git-revision=${got_revision}" ], "isolate_name": "fuchsia_telemetry_gpu_integration_test", @@ -28775,8 +28588,7 @@ "--browser=web-engine-shell", "--passthrough", "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --force_higher_performance_gpu --use-cmd-decoder=validating", - "--device=fvdl" + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --force_higher_performance_gpu --use-cmd-decoder=validating" ], "isolate_name": "fuchsia_telemetry_gpu_integration_test", "merge": { @@ -28810,7 +28622,6 @@ "--passthrough", "-v", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--device=fvdl", "--git-revision=${got_revision}" ], "isolate_name": "fuchsia_telemetry_gpu_integration_test", @@ -28849,8 +28660,7 @@ "--browser=web-engine-shell", "--passthrough", "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--device=fvdl" + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" ], "isolate_name": "fuchsia_telemetry_gpu_integration_test", "merge": { @@ -28883,8 +28693,7 @@ "--browser=web-engine-shell", "--passthrough", "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--device=fvdl" + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" ], "isolate_name": "fuchsia_telemetry_gpu_integration_test", "merge": { @@ -28917,8 +28726,7 @@ "--browser=web-engine-shell", "--passthrough", "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--device=fvdl" + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" ], "isolate_name": "fuchsia_telemetry_gpu_integration_test", "merge": { @@ -83613,7 +83421,7 @@ }, { "args": [ - "--ash-chrome-path-override=../../lacros_version_skew_tests_v94.0.4606.50/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v94.0.4606.58/test_ash_chrome", "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter" ], "isolate_profile_data": true, @@ -83621,14 +83429,14 @@ "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests_Lacros version skew testing ash 94.0.4606.50", + "name": "lacros_chrome_browsertests_Lacros version skew testing ash 94.0.4606.58", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v94.0.4606.50", - "revision": "version:94.0.4606.50" + "location": "lacros_version_skew_tests_v94.0.4606.58", + "revision": "version:94.0.4606.58" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -83663,7 +83471,7 @@ }, { "args": [ - "--ash-chrome-path-override=../../lacros_version_skew_tests_v96.0.4652.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v96.0.4653.0/test_ash_chrome", "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter" ], "isolate_profile_data": true, @@ -83671,14 +83479,14 @@ "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests_Lacros version skew testing ash 96.0.4652.0", + "name": "lacros_chrome_browsertests_Lacros version skew testing ash 96.0.4653.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v96.0.4652.0", - "revision": "version:96.0.4652.0" + "location": "lacros_version_skew_tests_v96.0.4653.0", + "revision": "version:96.0.4653.0" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -83705,7 +83513,7 @@ }, { "args": [ - "--ash-chrome-path-override=../../lacros_version_skew_tests_v94.0.4606.50/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v94.0.4606.58/test_ash_chrome", "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter" ], "isolate_profile_data": true, @@ -83713,14 +83521,14 @@ "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests_run_in_series_Lacros version skew testing ash 94.0.4606.50", + "name": "lacros_chrome_browsertests_run_in_series_Lacros version skew testing ash 94.0.4606.58", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v94.0.4606.50", - "revision": "version:94.0.4606.50" + "location": "lacros_version_skew_tests_v94.0.4606.58", + "revision": "version:94.0.4606.58" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -83755,7 +83563,7 @@ }, { "args": [ - "--ash-chrome-path-override=../../lacros_version_skew_tests_v96.0.4652.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v96.0.4653.0/test_ash_chrome", "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter" ], "isolate_profile_data": true, @@ -83763,14 +83571,14 @@ "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests_run_in_series_Lacros version skew testing ash 96.0.4652.0", + "name": "lacros_chrome_browsertests_run_in_series_Lacros version skew testing ash 96.0.4653.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v96.0.4652.0", - "revision": "version:96.0.4652.0" + "location": "lacros_version_skew_tests_v96.0.4653.0", + "revision": "version:96.0.4653.0" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -85079,21 +84887,21 @@ }, { "args": [ - "--ash-chrome-path-override=../../lacros_version_skew_tests_v94.0.4606.50/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v94.0.4606.58/test_ash_chrome", "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests_Lacros version skew testing ash 94.0.4606.50", + "name": "lacros_chrome_browsertests_Lacros version skew testing ash 94.0.4606.58", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v94.0.4606.50", - "revision": "version:94.0.4606.50" + "location": "lacros_version_skew_tests_v94.0.4606.58", + "revision": "version:94.0.4606.58" } ], "dimension_sets": [ @@ -85139,21 +84947,21 @@ }, { "args": [ - "--ash-chrome-path-override=../../lacros_version_skew_tests_v96.0.4652.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v96.0.4653.0/test_ash_chrome", "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests_Lacros version skew testing ash 96.0.4652.0", + "name": "lacros_chrome_browsertests_Lacros version skew testing ash 96.0.4653.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v96.0.4652.0", - "revision": "version:96.0.4652.0" + "location": "lacros_version_skew_tests_v96.0.4653.0", + "revision": "version:96.0.4653.0" } ], "dimension_sets": [ @@ -85191,21 +84999,21 @@ }, { "args": [ - "--ash-chrome-path-override=../../lacros_version_skew_tests_v94.0.4606.50/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v94.0.4606.58/test_ash_chrome", "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests_run_in_series_Lacros version skew testing ash 94.0.4606.50", + "name": "lacros_chrome_browsertests_run_in_series_Lacros version skew testing ash 94.0.4606.58", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v94.0.4606.50", - "revision": "version:94.0.4606.50" + "location": "lacros_version_skew_tests_v94.0.4606.58", + "revision": "version:94.0.4606.58" } ], "dimension_sets": [ @@ -85251,21 +85059,21 @@ }, { "args": [ - "--ash-chrome-path-override=../../lacros_version_skew_tests_v96.0.4652.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v96.0.4653.0/test_ash_chrome", "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests_run_in_series_Lacros version skew testing ash 96.0.4652.0", + "name": "lacros_chrome_browsertests_run_in_series_Lacros version skew testing ash 96.0.4653.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v96.0.4652.0", - "revision": "version:96.0.4652.0" + "location": "lacros_version_skew_tests_v96.0.4653.0", + "revision": "version:96.0.4653.0" } ], "dimension_sets": [ @@ -86746,21 +86554,21 @@ }, { "args": [ - "--ash-chrome-path-override=../../lacros_version_skew_tests_v94.0.4606.50/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v94.0.4606.58/test_ash_chrome", "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests_Lacros version skew testing ash 94.0.4606.50", + "name": "lacros_chrome_browsertests_Lacros version skew testing ash 94.0.4606.58", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v94.0.4606.50", - "revision": "version:94.0.4606.50" + "location": "lacros_version_skew_tests_v94.0.4606.58", + "revision": "version:94.0.4606.58" } ], "dimension_sets": [ @@ -86806,21 +86614,21 @@ }, { "args": [ - "--ash-chrome-path-override=../../lacros_version_skew_tests_v96.0.4652.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v96.0.4653.0/test_ash_chrome", "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests_Lacros version skew testing ash 96.0.4652.0", + "name": "lacros_chrome_browsertests_Lacros version skew testing ash 96.0.4653.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v96.0.4652.0", - "revision": "version:96.0.4652.0" + "location": "lacros_version_skew_tests_v96.0.4653.0", + "revision": "version:96.0.4653.0" } ], "dimension_sets": [ @@ -86858,21 +86666,21 @@ }, { "args": [ - "--ash-chrome-path-override=../../lacros_version_skew_tests_v94.0.4606.50/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v94.0.4606.58/test_ash_chrome", "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests_run_in_series_Lacros version skew testing ash 94.0.4606.50", + "name": "lacros_chrome_browsertests_run_in_series_Lacros version skew testing ash 94.0.4606.58", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v94.0.4606.50", - "revision": "version:94.0.4606.50" + "location": "lacros_version_skew_tests_v94.0.4606.58", + "revision": "version:94.0.4606.58" } ], "dimension_sets": [ @@ -86918,21 +86726,21 @@ }, { "args": [ - "--ash-chrome-path-override=../../lacros_version_skew_tests_v96.0.4652.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v96.0.4653.0/test_ash_chrome", "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests_run_in_series_Lacros version skew testing ash 96.0.4652.0", + "name": "lacros_chrome_browsertests_run_in_series_Lacros version skew testing ash 96.0.4653.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v96.0.4652.0", - "revision": "version:96.0.4652.0" + "location": "lacros_version_skew_tests_v96.0.4653.0", + "revision": "version:96.0.4653.0" } ], "dimension_sets": [ @@ -87603,21 +87411,21 @@ "gtest_tests": [ { "args": [ - "--ash-chrome-path-override=../../lacros_version_skew_tests_v93.0.4577.85/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v93.0.4577.95/test_ash_chrome", "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests_Lacros version skew testing ash 93.0.4577.85", + "name": "lacros_chrome_browsertests_Lacros version skew testing ash 93.0.4577.95", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v93.0.4577.85", - "revision": "version:93.0.4577.85" + "location": "lacros_version_skew_tests_v93.0.4577.95", + "revision": "version:93.0.4577.95" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -87627,21 +87435,21 @@ }, { "args": [ - "--ash-chrome-path-override=../../lacros_version_skew_tests_v94.0.4606.50/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v94.0.4606.58/test_ash_chrome", "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests_Lacros version skew testing ash 94.0.4606.50", + "name": "lacros_chrome_browsertests_Lacros version skew testing ash 94.0.4606.58", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v94.0.4606.50", - "revision": "version:94.0.4606.50" + "location": "lacros_version_skew_tests_v94.0.4606.58", + "revision": "version:94.0.4606.58" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -87675,21 +87483,21 @@ }, { "args": [ - "--ash-chrome-path-override=../../lacros_version_skew_tests_v96.0.4652.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v96.0.4653.0/test_ash_chrome", "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests_Lacros version skew testing ash 96.0.4652.0", + "name": "lacros_chrome_browsertests_Lacros version skew testing ash 96.0.4653.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v96.0.4652.0", - "revision": "version:96.0.4652.0" + "location": "lacros_version_skew_tests_v96.0.4653.0", + "revision": "version:96.0.4653.0" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -87699,21 +87507,21 @@ }, { "args": [ - "--ash-chrome-path-override=../../lacros_version_skew_tests_v93.0.4577.85/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v93.0.4577.95/test_ash_chrome", "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests_run_in_series_Lacros version skew testing ash 93.0.4577.85", + "name": "lacros_chrome_browsertests_run_in_series_Lacros version skew testing ash 93.0.4577.95", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v93.0.4577.85", - "revision": "version:93.0.4577.85" + "location": "lacros_version_skew_tests_v93.0.4577.95", + "revision": "version:93.0.4577.95" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -87723,21 +87531,21 @@ }, { "args": [ - "--ash-chrome-path-override=../../lacros_version_skew_tests_v94.0.4606.50/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v94.0.4606.58/test_ash_chrome", "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests_run_in_series_Lacros version skew testing ash 94.0.4606.50", + "name": "lacros_chrome_browsertests_run_in_series_Lacros version skew testing ash 94.0.4606.58", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v94.0.4606.50", - "revision": "version:94.0.4606.50" + "location": "lacros_version_skew_tests_v94.0.4606.58", + "revision": "version:94.0.4606.58" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -87771,21 +87579,21 @@ }, { "args": [ - "--ash-chrome-path-override=../../lacros_version_skew_tests_v96.0.4652.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v96.0.4653.0/test_ash_chrome", "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests_run_in_series_Lacros version skew testing ash 96.0.4652.0", + "name": "lacros_chrome_browsertests_run_in_series_Lacros version skew testing ash 96.0.4653.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v96.0.4652.0", - "revision": "version:96.0.4652.0" + "location": "lacros_version_skew_tests_v96.0.4653.0", + "revision": "version:96.0.4653.0" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
diff --git a/testing/buildbot/chromium.json b/testing/buildbot/chromium.json index 78fa9ef..b624855 100644 --- a/testing/buildbot/chromium.json +++ b/testing/buildbot/chromium.json
@@ -32,6 +32,12 @@ ], "scripts": [] }, + "linux-archive-tagged": { + "additional_compile_targets": [ + "all" + ], + "scripts": [] + }, "linux-official": { "additional_compile_targets": [ "all"
diff --git a/testing/buildbot/mixins.pyl b/testing/buildbot/mixins.pyl index 86e606b..9220825 100644 --- a/testing/buildbot/mixins.pyl +++ b/testing/buildbot/mixins.pyl
@@ -426,14 +426,7 @@ '--device=aemu', ], }, - }, - 'fuchsia-fvdl': { - '$mixin_append': { - 'args': [ - '--device=fvdl', - ], - }, - }, + }, 'fuchsia_logs': { '$mixin_append': { 'args': [
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index 4407ebbf0..c90b42f 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -802,6 +802,7 @@ 'remove_from': [ 'linux-archive-dbg', 'linux-archive-rel', + 'linux-archive-tagged', 'mac-archive-dbg', 'mac-archive-rel', 'mac-arm64-archive-dbg',
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl index 45143ae0..28adaea 100644 --- a/testing/buildbot/variants.pyl +++ b/testing/buildbot/variants.pyl
@@ -52,16 +52,16 @@ }, 'LACROS_VERSION_SKEW_CANARY': { 'args': [ - '--ash-chrome-path-override=../../lacros_version_skew_tests_v96.0.4652.0/test_ash_chrome', + '--ash-chrome-path-override=../../lacros_version_skew_tests_v96.0.4653.0/test_ash_chrome', '--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter', ], - 'identifier': 'Lacros version skew testing ash 96.0.4652.0', + 'identifier': 'Lacros version skew testing ash 96.0.4653.0', 'swarming': { 'cipd_packages': [ { 'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip', - 'location': 'lacros_version_skew_tests_v96.0.4652.0', - 'revision': 'version:96.0.4652.0', + 'location': 'lacros_version_skew_tests_v96.0.4653.0', + 'revision': 'version:96.0.4653.0', }, ], }, @@ -84,32 +84,32 @@ }, 'LACROS_VERSION_SKEW_BETA': { 'args': [ - '--ash-chrome-path-override=../../lacros_version_skew_tests_v94.0.4606.50/test_ash_chrome', + '--ash-chrome-path-override=../../lacros_version_skew_tests_v94.0.4606.58/test_ash_chrome', '--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter', ], - 'identifier': 'Lacros version skew testing ash 94.0.4606.50', + 'identifier': 'Lacros version skew testing ash 94.0.4606.58', 'swarming': { 'cipd_packages': [ { 'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip', - 'location': 'lacros_version_skew_tests_v94.0.4606.50', - 'revision': 'version:94.0.4606.50', + 'location': 'lacros_version_skew_tests_v94.0.4606.58', + 'revision': 'version:94.0.4606.58', }, ], }, }, 'LACROS_VERSION_SKEW_STABLE': { 'args': [ - '--ash-chrome-path-override=../../lacros_version_skew_tests_v93.0.4577.85/test_ash_chrome', + '--ash-chrome-path-override=../../lacros_version_skew_tests_v93.0.4577.95/test_ash_chrome', '--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter', ], - 'identifier': 'Lacros version skew testing ash 93.0.4577.85', + 'identifier': 'Lacros version skew testing ash 93.0.4577.95', 'swarming': { 'cipd_packages': [ { 'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip', - 'location': 'lacros_version_skew_tests_v93.0.4577.85', - 'revision': 'version:93.0.4577.85', + 'location': 'lacros_version_skew_tests_v93.0.4577.95', + 'revision': 'version:93.0.4577.95', }, ], }, @@ -387,7 +387,7 @@ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M95', - 'revision': 'version:95.0.4638.24', + 'revision': 'version:95.0.4638.25', } ], }, @@ -411,7 +411,7 @@ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M94', - 'revision': 'version:94.0.4606.63', + 'revision': 'version:94.0.4606.64', } ], }, @@ -459,7 +459,7 @@ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M95', - 'revision': 'version:95.0.4638.24', + 'revision': 'version:95.0.4638.25', } ], }, @@ -483,7 +483,7 @@ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M94', - 'revision': 'version:94.0.4606.63', + 'revision': 'version:94.0.4606.64', } ], }, @@ -531,7 +531,7 @@ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M95', - 'revision': 'version:95.0.4638.24', + 'revision': 'version:95.0.4638.25', } ], }, @@ -555,7 +555,7 @@ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M94', - 'revision': 'version:94.0.4606.63', + 'revision': 'version:94.0.4606.64', } ], },
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index fa9f4b4..887f539d 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -263,6 +263,17 @@ 'scripts': 'public_build_scripts', }, }, + 'linux-archive-tagged': { + 'mixins': [ + 'linux-archive-rel-args', + ], + 'additional_compile_targets': [ + 'all', + ], + 'test_suites': { + 'scripts': 'public_build_scripts', + }, + }, 'linux-official': { 'additional_compile_targets': [ 'all', @@ -2881,7 +2892,6 @@ 'all', ], 'mixins': [ - 'fuchsia-fvdl', 'linux-bionic', ], 'swarming': { @@ -2903,7 +2913,6 @@ 'browser_config': 'web-engine-shell', 'os_type': 'linux', 'mixins': [ - 'fuchsia-fvdl', 'linux-bionic', ], 'swarming': {
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index b637b5d..be5da9b 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -1217,6 +1217,46 @@ ] } ], + "AutofillSurveys": [ + { + "platforms": [ + "mac", + "windows" + ], + "experiments": [ + { + "name": "Card", + "params": { + "en_site_id": "F2fsskHvB0ugnJ3q1cK0NXLjUaK5", + "probability": "1.0" + }, + "enable_features": [ + "AutofillCardSurvey" + ] + }, + { + "name": "Password", + "params": { + "en_site_id": "6VQ4NCCaq0ugnJ3q1cK0TR13rB8t", + "probability": "1.0" + }, + "enable_features": [ + "AutofillPasswordSurvey" + ] + }, + { + "name": "Address", + "params": { + "en_site_id": "qQW9c2ho10ugnJ3q1cK0X48UQjZs", + "probability": "1.0" + }, + "enable_features": [ + "AutofillAddressSurvey" + ] + } + ] + } + ], "AutofillUseOnlyFormRendererIDForOldDuplicateFormRemoval": [ { "platforms": [ @@ -4388,33 +4428,6 @@ ] } ], - "InterestFeedContentSuggestions": [ - { - "platforms": [ - "android" - ], - "experiments": [ - { - "name": "EnabledUndoableActions", - "params": { - "card_menu_tooltip_eligible": "true", - "default_action_ttl_seconds": "90000", - "feed_ui_enabled": "true", - "init_feed_after_startup": "false", - "manage_interests_enabled": "true", - "snippets_enabled": "true", - "spinner_delay": "500", - "spinner_minimum_show_time": "0", - "storage_miss_threshold": "100", - "undoable_actions_enabled": "true" - }, - "enable_features": [ - "InterestFeedContentSuggestions" - ] - } - ] - } - ], "IsolatePasswordSites": [ { "platforms": [ @@ -7400,6 +7413,29 @@ ] } ], + "SharingHubDesktop": [ + { + "platforms": [ + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "EnabledOmnibox", + "enable_features": [ + "SharingHubDesktopOmnibox" + ] + }, + { + "name": "EnabledAppMenu", + "enable_features": [ + "SharingHubDesktopAppMenu" + ] + } + ] + } + ], "SharingHubLinkToggle": [ { "platforms": [
diff --git a/third_party/.gitignore b/third_party/.gitignore index e496483..0115415a 100644 --- a/third_party/.gitignore +++ b/third_party/.gitignore
@@ -54,7 +54,9 @@ /byte_buddy/android_sdk_build_tools_25_0_2 /byte_buddy/lib/ /cardboard-java/src +/cast_core/prebuilts /cast_core/public/src +/cast_web_runtime /catapult /ced/src /checkstyle/*.jar
diff --git a/third_party/android_support_test_runner/README.chromium b/third_party/android_support_test_runner/README.chromium index d6cb4129..2172f98 100644 --- a/third_party/android_support_test_runner/README.chromium +++ b/third_party/android_support_test_runner/README.chromium
@@ -15,3 +15,4 @@ Local Modifications: - Imports were automatically sorted (annoying to avoid this, and shouldn't have any impact) +- https:/crbug.com/1252584 Shorter log when JavaScriptBridge not found.
diff --git a/third_party/android_support_test_runner/runner/src/main/java/android/support/test/runner/MonitoringInstrumentation.java b/third_party/android_support_test_runner/runner/src/main/java/android/support/test/runner/MonitoringInstrumentation.java index b8a9d7c..00b34c35 100644 --- a/third_party/android_support_test_runner/runner/src/main/java/android/support/test/runner/MonitoringInstrumentation.java +++ b/third_party/android_support_test_runner/runner/src/main/java/android/support/test/runner/MonitoringInstrumentation.java
@@ -651,7 +651,7 @@ Method install = jsBridge.getDeclaredMethod("installBridge"); install.invoke(null); } catch (ClassNotFoundException ignored) { - Log.i(LOG_TAG, "No JSBridge.", ignored); + Log.i(LOG_TAG, "Espresso Web not found."); } catch (NoSuchMethodException nsme) { Log.i(LOG_TAG, "No JSBridge.", nsme); } catch (InvocationTargetException ite) {
diff --git a/third_party/blink/public/public_features.gni b/third_party/blink/public/public_features.gni index b5cc81d..da83b8e 100644 --- a/third_party/blink/public/public_features.gni +++ b/third_party/blink/public/public_features.gni
@@ -10,9 +10,6 @@ # Enables young generation collections in Oilpan. enable_blink_heap_young_generation = false - - # Enables Blink's heap to use V8's version of Oilpan. - enable_blink_heap_use_v8_oilpan = true } declare_args() {
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.cc b/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.cc index 25628294..5d94478 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.cc +++ b/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.cc
@@ -4,691 +4,9 @@ #include "third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.h" -#include <memory> -#include <sstream> -#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h" -#include "third_party/blink/renderer/bindings/core/v8/v8_gc_controller.h" -#include "third_party/blink/renderer/bindings/core/v8/v8_node.h" -#include "third_party/blink/renderer/core/execution_context/execution_context.h" -#include "third_party/blink/renderer/platform/bindings/active_script_wrappable_manager.h" -#include "third_party/blink/renderer/platform/bindings/script_wrappable.h" -#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h" -#include "third_party/blink/renderer/platform/bindings/wrapper_type_info.h" -#include "third_party/blink/renderer/platform/heap/unified_heap_controller.h" -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" -#include "third_party/blink/renderer/platform/wtf/buildflags.h" - -#if BUILDFLAG(USE_V8_OILPAN) - namespace blink { void EmbedderGraphBuilder::BuildEmbedderGraphCallback(v8::Isolate* isolate, v8::EmbedderGraph* graph, void*) {} } // namespace blink -#else // !USE_V8_OILPAN - -namespace blink { - -namespace { - -using Traceable = const void*; -using Graph = v8::EmbedderGraph; -using Detachedness = v8::EmbedderGraph::Node::Detachedness; - -class EmbedderNode : public Graph::Node { - public: - EmbedderNode(const char* name, - Graph::Node* wrapper, - Detachedness detachedness) - : name_(name), wrapper_(wrapper), detachedness_(detachedness) {} - - // Graph::Node overrides. - const char* Name() override { return name_; } - size_t SizeInBytes() override { return 0; } - Graph::Node* WrapperNode() override { return wrapper_; } - Detachedness GetDetachedness() override { return detachedness_; } - - void AddEdgeName(std::unique_ptr<char[]> edge_name) { - edge_names_.push_back(std::move(edge_name)); - } - - private: - const char* name_; - Graph::Node* wrapper_; - const Detachedness detachedness_; - // V8's API uses raw strings for edge names and expect the underlying memory - // to be retained until the end of graph building where strings are copied - // into its internal storage. The following vector retains those edge names - // until a node is freed which is at the end of graph building. - Vector<std::unique_ptr<char[]>> edge_names_; -}; - -class EmbedderRootNode : public EmbedderNode { - public: - explicit EmbedderRootNode(const char* name) - : EmbedderNode(name, nullptr, Detachedness::kUnknown) {} - // Graph::Node override. - bool IsRootNode() override { return true; } -}; - -class NodeBuilder final { - USING_FAST_MALLOC(NodeBuilder); - - public: - explicit NodeBuilder(Graph* graph) : graph_(graph) {} - - Graph::Node* GraphNode(const v8::Local<v8::Value>&); - EmbedderNode* GraphNode(Traceable, - const char* name, - Graph::Node* wrapper, - Detachedness); - bool Contains(Traceable traceable) const { - return graph_nodes_.Contains(traceable); - } - - private: - Graph* const graph_; - HashMap<Traceable, EmbedderNode*> graph_nodes_; -}; - -v8::EmbedderGraph::Node* NodeBuilder::GraphNode( - const v8::Local<v8::Value>& value) { - return graph_->V8Node(value); -} - -EmbedderNode* NodeBuilder::GraphNode(Traceable traceable, - const char* name, - v8::EmbedderGraph::Node* wrapper, - Detachedness detachedness) { - auto iter = graph_nodes_.find(traceable); - if (iter != graph_nodes_.end()) { - return iter->value; - } - // Ownership of the new node is transferred to the graph_. - // graph_node_.at(tracable) is valid for all BuildEmbedderGraph execution. - auto* raw_node = new EmbedderNode(name, wrapper, detachedness); - EmbedderNode* node = static_cast<EmbedderNode*>( - graph_->AddNode(std::unique_ptr<Graph::Node>(raw_node))); - graph_nodes_.insert(traceable, node); - return node; -} - -// V8EmbedderGraphBuilder is used to build heap snapshots of Blink's managed -// object graph. On a high level, the following operations are performed: -// - Node objects are classified as attached, detached, or unknown. -// - Depending an implicit mode, objects are classified as relevant or internal. -// This classification happens based on NameTrait and the fact that all -// ScriptWrappable objects (those that can have JS properties) are using that -// trait. -// - Not relevant objects are filtered where possible, e.g., sub graphs of -// internals are filtered and not reported. -// -// The algorithm performs a single pass on the graph, starting from V8-to-Blink -// references that identify attached nodes. Each object then starts a recursion -// into its own subgraph to identify and filter subgraphs that only consist of -// internals. Roots, which are potentially Blink only, are transitively -// traversed after handling JavaScript related objects. -class V8EmbedderGraphBuilder - : public Visitor, - public v8::PersistentHandleVisitor, - public v8::EmbedderHeapTracer::TracedGlobalHandleVisitor { - public: - V8EmbedderGraphBuilder(v8::Isolate*, Graph*, NodeBuilder*); - ~V8EmbedderGraphBuilder() override; - - void BuildEmbedderGraph(); - - // v8::PersistentHandleVisitor override. - void VisitPersistentHandle(v8::Persistent<v8::Value>*, - uint16_t class_id) override; - - // v8::EmbedderHeapTracer::TracedGlobalHandleVisitor override. - void VisitTracedReference( - const v8::TracedReference<v8::Value>& value) override; - void VisitTracedGlobalHandle(const v8::TracedGlobal<v8::Value>&) override; - - // Visitor overrides. - void VisitRoot(const void*, TraceDescriptor, const base::Location&) final; - void Visit(const TraceWrapperV8Reference<v8::Value>&) final; - void Visit(const void*, TraceDescriptor) final; - void VisitEphemeron(const void*, TraceDescriptor) final; - void VisitWeakContainer(const void*, - const void* const*, - TraceDescriptor, - TraceDescriptor, - WeakCallback, - const void*) final; - - private: - class ParentScope { - STACK_ALLOCATED(); - - public: - ParentScope(V8EmbedderGraphBuilder* visitor, Traceable traceable) - : visitor_(visitor), old_parent_(visitor->current_parent_) { - visitor->current_parent_ = traceable; - } - ~ParentScope() { visitor_->current_parent_ = old_parent_; } - - ParentScope(const ParentScope&) = delete; - ParentScope& operator=(const ParentScope&) = delete; - - private: - V8EmbedderGraphBuilder* const visitor_; - Traceable old_parent_; - }; - - class State final { - USING_FAST_MALLOC(State); - - public: - State(Traceable traceable, const char* name, Detachedness detachedness) - : traceable_(traceable), name_(name) {} - explicit State(EmbedderNode* node) : node_(node) {} - - bool IsVisited() const { return visited_; } - void MarkVisited() { visited_ = true; } - - bool IsPending() const { return pending_; } - void MarkPending() { pending_ = true; } - void UnmarkPending() { pending_ = false; } - - bool HasNode() const { return node_; } - EmbedderNode* GetOrCreateNode(NodeBuilder* builder) { - if (!node_) { - DCHECK(name_); - node_ = builder->GraphNode(traceable_, name_, nullptr, - Detachedness::kUnknown); - } - return node_; - } - - void AddEdgeName(State* destination, std::string edge_name) { - auto result = named_edges_.insert(destination, std::move(edge_name)); - DCHECK(result.is_new_entry); - } - - void AddRootEdgeName(State* destination, std::string edge_name) { - // State may represent root groups in which case there may exist multiple - // references to the same |destination|. - named_edges_.insert(destination, std::move(edge_name)); - } - - std::string EdgeName(State* destination) { - auto it = named_edges_.find(destination); - if (it != named_edges_.end()) - return it->value; - return std::string(); - } - - private: - EmbedderNode* node_ = nullptr; - Traceable traceable_ = nullptr; - const char* name_ = nullptr; - HashMap<State* /*destination*/, std::string> named_edges_; - bool visited_ = false; - bool pending_ = false; - }; - - // WorklistItemBase is used for different kinds of items that require - // processing the regular worklist. - class WorklistItemBase { - USING_FAST_MALLOC(WorklistItemBase); - - public: - explicit WorklistItemBase(State* parent, State* to_process) - : parent_(parent), to_process_(to_process) {} - virtual ~WorklistItemBase() = default; - virtual void Process(V8EmbedderGraphBuilder*) = 0; - - State* to_process() const { return to_process_; } - State* parent() const { return parent_; } - - private: - State* const parent_; - State* const to_process_; - }; - - // A VisitationItem processes a given object and visits all its children. - class VisitationItem final : public WorklistItemBase { - public: - VisitationItem(State* parent, - State* to_process, - Traceable traceable, - TraceCallback trace_callback) - : WorklistItemBase(parent, to_process), - traceable_(traceable), - trace_callback_(trace_callback) {} - - void Process(V8EmbedderGraphBuilder* builder) final { - // Post-order traversal as parent needs the full information on child. - builder->worklist_.push_back(std::unique_ptr<WorklistItemBase>{ - new VisitationDoneItem(parent(), to_process())}); - to_process()->MarkPending(); - DCHECK(to_process()->IsPending()); - DCHECK(to_process()->IsVisited()); - ParentScope parent_scope(builder, traceable_); - trace_callback_(builder, const_cast<void*>(traceable_)); - } - - private: - Traceable traceable_; - TraceCallback trace_callback_; - }; - - // A VisitationDoneItem unmarks the pending state of an object and creates - // an edge from a parent in case there is one. - class VisitationDoneItem final : public WorklistItemBase { - public: - VisitationDoneItem(State* parent, State* to_process) - : WorklistItemBase(parent, to_process) {} - - void Process(V8EmbedderGraphBuilder* builder) final { - if (parent() && to_process()->HasNode()) { - builder->AddEdge(parent(), to_process()); - } - to_process()->UnmarkPending(); - } - }; - - class EphemeronItem final { - public: - EphemeronItem(Traceable backing, - Traceable key, - Traceable value, - TraceCallback value_tracing_callback) - : backing_(backing), - key_(key), - value_(value), - value_tracing_callback_(value_tracing_callback) {} - - bool Process(V8EmbedderGraphBuilder* builder) { - if (!key_) { - // Don't trace the value if the key is nullptr. - return true; - } - if (!builder->StateExists(key_)) - return false; - { - ParentScope scope(builder, key_); - builder->current_ephemeron_backing_ = backing_; - value_tracing_callback_(builder, const_cast<void*>(value_)); - builder->current_ephemeron_backing_ = nullptr; - } - return true; - } - - private: - Traceable backing_; - Traceable key_; - Traceable value_; - TraceCallback value_tracing_callback_; - }; - - State* GetOrCreateState(Traceable traceable, - const char* name, - Detachedness detachedness) { - if (!states_.Contains(traceable)) { - states_.insert(traceable, new State(traceable, name, detachedness)); - } - return states_.at(traceable); - } - - bool StateExists(Traceable traceable) const { - return states_.Contains(traceable); - } - - State* GetStateNotNull(Traceable traceable) { - CHECK(states_.Contains(traceable)); - return states_.at(traceable); - } - - State* EnsureState(Traceable traceable, EmbedderNode* node) { - if (!states_.Contains(traceable)) { - states_.insert(traceable, new State(node)); - } - return states_.at(traceable); - } - - void EnsureRootState(EmbedderNode* node) { - CHECK(!states_.Contains(node)); - states_.insert(node, new State(node)); - } - - void AddEdge(State*, State*); - void AddEphemeronEdgeName(Traceable backing, State* parent, State* current); - - void VisitPersistentHandleInternal(v8::Local<v8::Object>, uint16_t); - void VisitBlinkRoots(); - void VisitTransitiveClosure(); - - // Push a VisitatonItem to the main worklist in case the State has not been - // already visited. - void CreateAndPushVisitationItem(State* parent, - State* to_process, - Traceable traceable, - TraceCallback trace_callback) { - DCHECK(!to_process->IsVisited()); - to_process->MarkVisited(); - worklist_.push_back(std::unique_ptr<WorklistItemBase>{ - new VisitationItem(parent, to_process, traceable, trace_callback)}); - } - - void PushVisitationItem(std::unique_ptr<VisitationItem> item) { - if (!item->to_process()->IsVisited()) { - item->to_process()->MarkVisited(); - worklist_.push_back(std::move(item)); - } - } - - v8::Isolate* const isolate_; - Graph* const graph_; - NodeBuilder* const node_builder_; - - Traceable current_parent_ = nullptr; - Traceable current_ephemeron_backing_ = nullptr; - HashMap<Traceable, State*> states_; - // Worklist that is used to visit transitive closure. - Deque<std::unique_ptr<WorklistItemBase>> worklist_; - // The worklist that collects Ephemeron entries for later processing. - Deque<std::unique_ptr<EphemeronItem>> ephemeron_worklist_; -}; - -V8EmbedderGraphBuilder::V8EmbedderGraphBuilder(v8::Isolate* isolate, - Graph* graph, - NodeBuilder* node_builder) - : Visitor(ThreadState::Current()), - isolate_(isolate), - graph_(graph), - node_builder_(node_builder) { - CHECK(isolate); - CHECK(graph); - CHECK_EQ(isolate, ThreadState::Current()->GetIsolate()); -} - -V8EmbedderGraphBuilder::~V8EmbedderGraphBuilder() { - for (const auto& kvp : states_) { - delete kvp.value; - } -} - -void V8EmbedderGraphBuilder::BuildEmbedderGraph() { - isolate_->VisitHandlesWithClassIds(this); - v8::EmbedderHeapTracer* const tracer = static_cast<v8::EmbedderHeapTracer*>( - ThreadState::Current()->unified_heap_controller()); - tracer->IterateTracedGlobalHandles(this); - VisitBlinkRoots(); - VisitTransitiveClosure(); - DCHECK(worklist_.empty()); - // ephemeron_worklist_ might not be empty. We might have an ephemeron whose - // key is alive but was never observed by the snapshot (e.g. objects pointed - // to by the stack). Such entries will remain in the worklist. - // - // TODO(omerkatz): add DCHECK(ephemeron_worklist_.empty()) when heap snapshot - // covers all live objects. -} - -void V8EmbedderGraphBuilder::VisitPersistentHandleInternal( - v8::Local<v8::Object> v8_value, - uint16_t class_id) { - const ScriptWrappable* traceable = ToScriptWrappable(v8_value); - if (!traceable) - return; - Graph::Node* wrapper = node_builder_->GraphNode(v8_value); - auto detachedness = V8GCController::DetachednessFromWrapper( - isolate_, v8_value.As<v8::Value>(), class_id, nullptr); - EmbedderNode* graph_node = node_builder_->GraphNode( - traceable, traceable->NameInHeapSnapshot(), wrapper, detachedness); - State* const to_process_state = EnsureState(traceable, graph_node); - if (to_process_state->IsVisited()) { - return; - } - const TraceDescriptor& descriptor = - TraceDescriptorFor<ScriptWrappable>(traceable); - CreateAndPushVisitationItem(nullptr, to_process_state, traceable, - descriptor.callback); -} - -void V8EmbedderGraphBuilder::VisitTracedReference( - const v8::TracedReference<v8::Value>& value) { - const uint16_t class_id = value.WrapperClassId(); - if (class_id != WrapperTypeInfo::kNodeClassId && - class_id != WrapperTypeInfo::kObjectClassId) - return; - VisitPersistentHandleInternal(value.As<v8::Object>().Get(isolate_), class_id); -} - -void V8EmbedderGraphBuilder::VisitTracedGlobalHandle( - const v8::TracedGlobal<v8::Value>&) { - CHECK(false) << "Blink does not use v8::TracedGlobal."; -} - -void V8EmbedderGraphBuilder::VisitPersistentHandle( - v8::Persistent<v8::Value>* value, - uint16_t class_id) { - if (class_id != WrapperTypeInfo::kNodeClassId && - class_id != WrapperTypeInfo::kObjectClassId) - return; - v8::Local<v8::Object> v8_value = v8::Local<v8::Object>::New( - isolate_, v8::Persistent<v8::Object>::Cast(*value)); - VisitPersistentHandleInternal(v8_value, class_id); -} - -void V8EmbedderGraphBuilder::Visit( - const TraceWrapperV8Reference<v8::Value>& traced_wrapper) { - // Add an edge from the current parent to the V8 object. - v8::Local<v8::Value> v8_value = traced_wrapper.NewLocal(isolate_); - if (!v8_value.IsEmpty()) { - State* parent = GetStateNotNull(current_parent_); - graph_->AddEdge(parent->GetOrCreateNode(node_builder_), - node_builder_->GraphNode(v8_value)); - } -} - -void V8EmbedderGraphBuilder::VisitRoot(const void* object, - TraceDescriptor wrapper_descriptor, - const base::Location& location) { - // Extract edge name if |location| is set. - if (location.has_source_info()) { - const void* traceable = wrapper_descriptor.base_object_payload; - State* const parent = GetStateNotNull(current_parent_); - State* const current = GetOrCreateState( - traceable, HeapObjectHeader::FromPayload(traceable)->Name(), - Detachedness::kUnknown); - parent->AddRootEdgeName(current, location.ToString()); - } - Visit(object, wrapper_descriptor); -} - -void V8EmbedderGraphBuilder::AddEphemeronEdgeName(Traceable backing, - State* parent, - State* current) { - const GCInfo& backing_info = GCInfo::From( - HeapObjectHeader::FromPayload(current_ephemeron_backing_)->GcInfoIndex()); - HeapObjectName backing_name = backing_info.name(current_ephemeron_backing_); - std::stringstream ss; - ss << "part of key -> value pair in ephemeron table"; - if (!backing_name.name_is_hidden) { - const std::string backing_name_str(backing_name.value); - const auto kvp_pos = backing_name_str.find("WTF::KeyValuePair"); - // Ephemerons are defined through WTF::KeyValuePair. - CHECK_NE(std::string::npos, kvp_pos); - // Extracting the pair TYPE from for WTF::KeyValuePair<TYPE>. - ss << " (<"; - size_t current_pos = kvp_pos + sizeof("WTF::KeyValuePair"); - CHECK_EQ('<', backing_name_str[current_pos - 1]); - size_t nesting = 0; - while (backing_name_str[current_pos] != '>' || (nesting > 0)) { - if (backing_name_str[current_pos] == '<') - nesting++; - if (backing_name_str[current_pos] == '>') - nesting--; - ss << backing_name_str[current_pos]; - current_pos++; - } - ss << ">)"; - } - parent->AddEdgeName(current, ss.str()); -} - -void V8EmbedderGraphBuilder::Visit(const void* object, - TraceDescriptor wrapper_descriptor) { - const void* traceable = wrapper_descriptor.base_object_payload; - const GCInfo& info = - GCInfo::From(HeapObjectHeader::FromPayload(traceable)->GcInfoIndex()); - HeapObjectName name = info.name(traceable); - - State* const parent = GetStateNotNull(current_parent_); - State* const current = - GetOrCreateState(traceable, name.value, Detachedness::kUnknown); - if (current_ephemeron_backing_) { - // Just records an edge name in case the state gets later on materialized. - AddEphemeronEdgeName(current_ephemeron_backing_, parent, current); - } - if (current->IsPending()) { - if (parent->HasNode()) { - // Backedge in currently processed graph. - AddEdge(parent, current); - } - return; - } - - // Immediately materialize the node if it is not hidden. - if (!name.name_is_hidden) { - current->GetOrCreateNode(node_builder_); - } - - if (!current->IsVisited()) { - CreateAndPushVisitationItem(parent, current, traceable, info.trace); - } else { - // Edge into an already processed subgraph. - if (current->HasNode()) { - // Create an edge in case the current node has already been visited. - AddEdge(parent, current); - } - } -} - -void V8EmbedderGraphBuilder::AddEdge(State* parent, State* current) { - EmbedderNode* parent_node = parent->GetOrCreateNode(node_builder_); - EmbedderNode* current_node = current->GetOrCreateNode(node_builder_); - if (!parent->EdgeName(current).empty()) { - std::string edge_name = parent->EdgeName(current); - // V8's API is based on raw C strings. Allocate and temporarily keep the - // edge name alive from the corresponding node. - const size_t len = edge_name.length(); - auto holder = std::make_unique<char[]>(len + 1); - strncpy(holder.get(), edge_name.c_str(), len); - holder[len] = 0; - graph_->AddEdge(parent_node, current_node, holder.get()); - parent_node->AddEdgeName(std::move(holder)); - return; - } - graph_->AddEdge(parent_node, current_node); -} - -void V8EmbedderGraphBuilder::VisitWeakContainer( - const void* object, - const void* const* slot, - TraceDescriptor strong_desc, - TraceDescriptor ephemeron_iteration, - WeakCallback weak_callback, - const void* weak_callback_parameter) { - // Only ephemerons have weak callbacks. - if (ephemeron_iteration.callback) { - // Heap snapshot is always run after a GC so we know there are no dead - // entries in the backing store. Using the weak descriptor here ensures that - // the key is not held alive from the backing store but rather from the - // object. A named edge ensures that we make the fact that value was held - // alive via ephemeron visible. - if (object) { - ParentScope parent(this, ephemeron_iteration.base_object_payload); - ephemeron_iteration.callback(this, - ephemeron_iteration.base_object_payload); - } - } -} - -void V8EmbedderGraphBuilder::VisitEphemeron( - const void* key, - TraceDescriptor value_trace_descriptor) { - // During regular visitation of ephemerons, current_parent_ refers to the - // backing store. - ephemeron_worklist_.push_back(std::make_unique<EphemeronItem>( - current_parent_, key, value_trace_descriptor.base_object_payload, - value_trace_descriptor.callback)); -} - -void V8EmbedderGraphBuilder::VisitBlinkRoots() { - { - EmbedderNode* root = static_cast<EmbedderNode*>(graph_->AddNode( - std::unique_ptr<Graph::Node>(new EmbedderRootNode("Blink roots")))); - EnsureRootState(root); - ParentScope parent(this, root); - ThreadState::Current()->GetPersistentRegion()->TraceNodes(this); - } - { - EmbedderNode* root = - static_cast<EmbedderNode*>(graph_->AddNode(std::unique_ptr<Graph::Node>( - new EmbedderRootNode("Blink cross-thread roots")))); - EnsureRootState(root); - ParentScope parent(this, root); - MutexLocker persistent_lock(ProcessHeap::CrossThreadPersistentMutex()); - ProcessHeap::GetCrossThreadPersistentRegion().TraceNodes(this); - } -} - -void V8EmbedderGraphBuilder::VisitTransitiveClosure() { - // The following loop process the worklist and ephemerons. Since regular - // tracing can record new ephemerons, and tracing an ephemeron can add - // items to the regular worklist, we need to repeatedly process the worklist - // until a fixed point is reached. - - // Because snapshots are processed in stages, there may be ephemerons that - // where key's do not have yet a state associated with them which prohibits - // them from being processed. Such ephemerons are stashed for later - // processing. - bool processed_ephemerons; - do { - // Step 1: Go through all items in the worklist using depth-first search. - while (!worklist_.empty()) { - std::unique_ptr<WorklistItemBase> item = std::move(worklist_.back()); - worklist_.pop_back(); - item->Process(this); - } - - // Step 2: Go through ephemeron items. - processed_ephemerons = false; - Deque<std::unique_ptr<EphemeronItem>> unprocessed_ephemerons_; - // Only process an ephemeron item if its key was already observed. - while (!ephemeron_worklist_.empty()) { - std::unique_ptr<EphemeronItem> item = - std::move(ephemeron_worklist_.front()); - ephemeron_worklist_.pop_front(); - if (!item->Process(this)) { - unprocessed_ephemerons_.push_back(std::move(item)); - } else { - processed_ephemerons = true; - } - } - ephemeron_worklist_.Swap(unprocessed_ephemerons_); - } while (!worklist_.empty() || processed_ephemerons); -} - -} // namespace - -void EmbedderGraphBuilder::BuildEmbedderGraphCallback(v8::Isolate* isolate, - v8::EmbedderGraph* graph, - void*) { - // Synchronize with concurrent sweepers before taking a snapshot. - ThreadState::Current()->CompleteSweep(); - - NodeBuilder node_builder(graph); - V8EmbedderGraphBuilder builder(isolate, graph, &node_builder); - builder.BuildEmbedderGraph(); -} - -} // namespace blink - -#endif // !USE_V8_OILPAN
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_gc_controller.cc b/third_party/blink/renderer/bindings/core/v8/v8_gc_controller.cc index 69256e7..91dcbaaf 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_gc_controller.cc +++ b/third_party/blink/renderer/bindings/core/v8/v8_gc_controller.cc
@@ -52,7 +52,6 @@ #include "third_party/blink/renderer/platform/instrumentation/histogram.h" #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h" #include "third_party/blink/renderer/platform/wtf/allocator/partitions.h" -#include "third_party/blink/renderer/platform/wtf/buildflags.h" #include "third_party/blink/renderer/platform/wtf/text/string_builder.h" namespace blink { @@ -94,26 +93,10 @@ return v8::EmbedderGraph::Node::Detachedness::kDetached; } -#if !BUILDFLAG(USE_V8_OILPAN) -namespace { -bool IsNestedInV8GC(ThreadState* thread_state, v8::GCType type) { - return thread_state && (type == v8::kGCTypeMarkSweepCompact || - type == v8::kGCTypeIncrementalMarking); -} -} // namespace -#endif // !USE_V8_OILPAN - void V8GCController::GcPrologue(v8::Isolate* isolate, v8::GCType type, v8::GCCallbackFlags flags) { RUNTIME_CALL_TIMER_SCOPE(isolate, RuntimeCallStats::CounterId::kGcPrologue); -#if !BUILDFLAG(USE_V8_OILPAN) - ThreadHeapStatsCollector::BlinkGCInV8Scope nested_scope( - IsNestedInV8GC(ThreadState::Current(), type) - ? ThreadState::Current()->Heap().stats_collector() - : nullptr); -#endif // !USE_V8_OILPAN - auto* per_isolate_data = V8PerIsolateData::From(isolate); per_isolate_data->EnterGC(); @@ -152,12 +135,6 @@ v8::GCType type, v8::GCCallbackFlags flags) { RUNTIME_CALL_TIMER_SCOPE(isolate, RuntimeCallStats::CounterId::kGcEpilogue); -#if !BUILDFLAG(USE_V8_OILPAN) - ThreadHeapStatsCollector::BlinkGCInV8Scope nested_scope( - IsNestedInV8GC(ThreadState::Current(), type) - ? ThreadState::Current()->Heap().stats_collector() - : nullptr); -#endif // !USE_V8_OILPAN V8PerIsolateData::From(isolate)->LeaveGC();
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_metrics.cc b/third_party/blink/renderer/bindings/core/v8/v8_metrics.cc index 3a1cf177..9f78bd5 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_metrics.cc +++ b/third_party/blink/renderer/bindings/core/v8/v8_metrics.cc
@@ -85,7 +85,6 @@ namespace { -#if BUILDFLAG(USE_V8_OILPAN) // Helper function to convert a byte count to a KB count, capping at // INT_MAX if the number is larger than that. constexpr int32_t CappedSizeInKB(int64_t size_in_bytes) { @@ -120,15 +119,12 @@ DCHECK_NE(-1, event.main_thread_efficiency_cpp_in_bytes_per_us); DCHECK_NE(-1, event.collection_rate_cpp_in_percent); } -#endif // USE_V8_OILPAN } // namespace void V8MetricsRecorder::AddMainThreadEvent( const v8::metrics::GarbageCollectionFullCycle& event, ContextId context_id) { -#if BUILDFLAG(USE_V8_OILPAN) - // Cpp events should always be populated when building with USE_V8_OILPAN. CheckCppEvents(event); // Report throughput metrics: UMA_HISTOGRAM_TIMES("V8.GC.Cycle.Full.Cpp", @@ -245,7 +241,6 @@ ("V8.GC.Cycle.CollectionRate.Full.Cpp", 0, 100, 20)); collection_rate_histogram.Count(base::saturated_cast<base::Histogram::Sample>( 100 * event.collection_rate_cpp_in_percent)); -#endif // USE_V8_OILPAN } namespace {
diff --git a/third_party/blink/renderer/bindings/generated_in_core.gni b/third_party/blink/renderer/bindings/generated_in_core.gni index cd75056..aa6c44f3 100644 --- a/third_party/blink/renderer/bindings/generated_in_core.gni +++ b/third_party/blink/renderer/bindings/generated_in_core.gni
@@ -85,6 +85,8 @@ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_animation_event_init.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_animation_playback_event_init.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_animation_playback_event_init.h", + "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_app_history_current_change_event_init.cc", + "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_app_history_current_change_event_init.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_app_history_navigate_event_init.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_app_history_navigate_event_init.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_app_history_navigate_options.cc", @@ -535,6 +537,8 @@ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_animation_timeline.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_app_history.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_app_history.h", + "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_app_history_current_change_event.cc", + "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_app_history_current_change_event.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_app_history_destination.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_app_history_destination.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_app_history_entry.cc",
diff --git a/third_party/blink/renderer/bindings/idl_in_core.gni b/third_party/blink/renderer/bindings/idl_in_core.gni index a5f17d79..73a3f24 100644 --- a/third_party/blink/renderer/bindings/idl_in_core.gni +++ b/third_party/blink/renderer/bindings/idl_in_core.gni
@@ -37,6 +37,8 @@ "//third_party/blink/renderer/core/app_history/app_history.idl", "//third_party/blink/renderer/core/app_history/app_history_destination.idl", "//third_party/blink/renderer/core/app_history/app_history_entry.idl", + "//third_party/blink/renderer/core/app_history/app_history_current_change_event.idl", + "//third_party/blink/renderer/core/app_history/app_history_current_change_event_init.idl", "//third_party/blink/renderer/core/app_history/app_history_navigate_event.idl", "//third_party/blink/renderer/core/app_history/app_history_navigate_event_init.idl", "//third_party/blink/renderer/core/app_history/app_history_navigate_options.idl",
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn index ae36d9d..8d33ed0 100644 --- a/third_party/blink/renderer/core/BUILD.gn +++ b/third_party/blink/renderer/core/BUILD.gn
@@ -462,6 +462,7 @@ generate_event_interfaces("core_event_interfaces") { sources = [ + "app_history/app_history_current_change_event.idl", "app_history/app_history_navigate_event.idl", "css/font_face_set_load_event.idl", "css/media_query_list_event.idl",
diff --git a/third_party/blink/renderer/core/app_history/app_history.cc b/third_party/blink/renderer/core/app_history/app_history.cc index d818d76..159bb84f 100644 --- a/third_party/blink/renderer/core/app_history/app_history.cc +++ b/third_party/blink/renderer/core/app_history/app_history.cc
@@ -11,6 +11,7 @@ #include "third_party/blink/renderer/bindings/core/v8/script_function.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise.h" #include "third_party/blink/renderer/bindings/core/v8/script_value.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_app_history_current_change_event_init.h" #include "third_party/blink/renderer/bindings/core/v8/v8_app_history_navigate_event_init.h" #include "third_party/blink/renderer/bindings/core/v8/v8_app_history_navigate_options.h" #include "third_party/blink/renderer/bindings/core/v8/v8_app_history_reload_options.h" @@ -19,6 +20,7 @@ #include "third_party/blink/renderer/bindings/core/v8/v8_app_history_update_current_options.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h" #include "third_party/blink/renderer/core/app_history/app_history_api_navigation.h" +#include "third_party/blink/renderer/core/app_history/app_history_current_change_event.h" #include "third_party/blink/renderer/core/app_history/app_history_destination.h" #include "third_party/blink/renderer/core/app_history/app_history_entry.h" #include "third_party/blink/renderer/core/app_history/app_history_navigate_event.h" @@ -152,6 +154,22 @@ return result; } +String DetermineNavigationType(WebFrameLoadType type) { + switch (type) { + case WebFrameLoadType::kStandard: + return "push"; + case WebFrameLoadType::kBackForward: + return "traverse"; + case WebFrameLoadType::kReload: + case WebFrameLoadType::kReloadBypassingCache: + return "reload"; + case WebFrameLoadType::kReplaceCurrentItem: + return "replace"; + } + NOTREACHED(); + return String(); +} + const char AppHistory::kSupplementName[] = "AppHistory"; AppHistory* AppHistory::appHistory(LocalDOMWindow& window) { @@ -229,6 +247,8 @@ if (entries_.IsEmpty()) return; + AppHistoryEntry* old_current = current(); + HeapVector<Member<AppHistoryEntry>> disposed_entries; if (type == WebFrameLoadType::kBackForward) { // If this is a same-document back/forward navigation, the new current @@ -259,6 +279,12 @@ keys_to_indices_.insert(entries_[current_index_]->key(), current_index_); } + auto* init = AppHistoryCurrentChangeEventInit::Create(); + init->setNavigationType(DetermineNavigationType(type)); + init->setFrom(old_current); + DispatchEvent(*AppHistoryCurrentChangeEvent::Create( + event_type_names::kCurrentchange, init)); + // It's important to do this before firing dispose events, since dispose // events could start another navigation or otherwise mess with // ongoing_navigation_. @@ -305,6 +331,11 @@ return; current_entry->GetItem()->SetAppHistoryState(std::move(serialized_state)); + + auto* init = AppHistoryCurrentChangeEventInit::Create(); + init->setFrom(current_entry); + DispatchEvent(*AppHistoryCurrentChangeEvent::Create( + event_type_names::kCurrentchange, init)); } AppHistoryResult* AppHistory::navigate(ScriptState* script_state, @@ -513,22 +544,6 @@ exception_state); } -String DetermineNavigationType(WebFrameLoadType type) { - switch (type) { - case WebFrameLoadType::kStandard: - return "push"; - case WebFrameLoadType::kBackForward: - return "traverse"; - case WebFrameLoadType::kReload: - case WebFrameLoadType::kReloadBypassingCache: - return "reload"; - case WebFrameLoadType::kReplaceCurrentItem: - return "replace"; - } - NOTREACHED(); - return String(); -} - void AppHistory::PromoteUpcomingNavigationToOngoing(const String& key) { DCHECK(!ongoing_navigation_); if (!key.IsNull()) {
diff --git a/third_party/blink/renderer/core/app_history/app_history.h b/third_party/blink/renderer/core/app_history/app_history.h index e81cf3c..16287a36 100644 --- a/third_party/blink/renderer/core/app_history/app_history.h +++ b/third_party/blink/renderer/core/app_history/app_history.h
@@ -80,6 +80,7 @@ DEFINE_ATTRIBUTE_EVENT_LISTENER(navigate, kNavigate) DEFINE_ATTRIBUTE_EVENT_LISTENER(navigatesuccess, kNavigatesuccess) DEFINE_ATTRIBUTE_EVENT_LISTENER(navigateerror, kNavigateerror) + DEFINE_ATTRIBUTE_EVENT_LISTENER(currentchange, kCurrentchange) enum class DispatchResult { kContinue, kAbort, kTransitionWhile }; DispatchResult DispatchNavigateEvent(const KURL& url,
diff --git a/third_party/blink/renderer/core/app_history/app_history.idl b/third_party/blink/renderer/core/app_history/app_history.idl index 67b6a0a..3b091ca 100644 --- a/third_party/blink/renderer/core/app_history/app_history.idl +++ b/third_party/blink/renderer/core/app_history/app_history.idl
@@ -25,4 +25,5 @@ attribute EventHandler onnavigate; attribute EventHandler onnavigatesuccess; attribute EventHandler onnavigateerror; + attribute EventHandler oncurrentchange; };
diff --git a/third_party/blink/renderer/core/app_history/app_history_current_change_event.cc b/third_party/blink/renderer/core/app_history/app_history_current_change_event.cc new file mode 100644 index 0000000..7708ed1f --- /dev/null +++ b/third_party/blink/renderer/core/app_history/app_history_current_change_event.cc
@@ -0,0 +1,30 @@ +// Copyright 2021 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/core/app_history/app_history_current_change_event.h" + +#include "third_party/blink/renderer/bindings/core/v8/v8_app_history_current_change_event_init.h" +#include "third_party/blink/renderer/core/app_history/app_history_entry.h" +#include "third_party/blink/renderer/core/event_interface_names.h" + +namespace blink { + +AppHistoryCurrentChangeEvent::AppHistoryCurrentChangeEvent( + const AtomicString& type, + AppHistoryCurrentChangeEventInit* init) + : Event(type, init), from_(init->from()) { + if (init->navigationType()) + navigation_type_ = *init->navigationType(); +} + +const AtomicString& AppHistoryCurrentChangeEvent::InterfaceName() const { + return event_interface_names::kAppHistoryCurrentChangeEvent; +} + +void AppHistoryCurrentChangeEvent::Trace(Visitor* visitor) const { + Event::Trace(visitor); + visitor->Trace(from_); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/app_history/app_history_current_change_event.h b/third_party/blink/renderer/core/app_history/app_history_current_change_event.h new file mode 100644 index 0000000..ddcf2a7 --- /dev/null +++ b/third_party/blink/renderer/core/app_history/app_history_current_change_event.h
@@ -0,0 +1,43 @@ +// Copyright 2021 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. + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_APP_HISTORY_APP_HISTORY_CURRENT_CHANGE_EVENT_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_APP_HISTORY_APP_HISTORY_CURRENT_CHANGE_EVENT_H_ + +#include "third_party/blink/renderer/core/dom/events/event.h" +#include "third_party/blink/renderer/platform/heap/heap_allocator.h" +#include "third_party/blink/renderer/platform/heap/member.h" +#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" + +namespace blink { +class AppHistoryCurrentChangeEventInit; +class AppHistoryEntry; + +class AppHistoryCurrentChangeEvent final : public Event { + DEFINE_WRAPPERTYPEINFO(); + + public: + static AppHistoryCurrentChangeEvent* Create( + const AtomicString& type, + AppHistoryCurrentChangeEventInit* init) { + return MakeGarbageCollected<AppHistoryCurrentChangeEvent>(type, init); + } + + AppHistoryCurrentChangeEvent(const AtomicString& type, + AppHistoryCurrentChangeEventInit* init); + + String navigationType() { return navigation_type_; } + AppHistoryEntry* from() { return from_; } + + const AtomicString& InterfaceName() const final; + void Trace(Visitor* visitor) const final; + + private: + String navigation_type_; + Member<AppHistoryEntry> from_; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_APP_HISTORY_APP_HISTORY_CURRENT_CHANGE_EVENT_H_
diff --git a/third_party/blink/renderer/core/app_history/app_history_current_change_event.idl b/third_party/blink/renderer/core/app_history/app_history_current_change_event.idl new file mode 100644 index 0000000..6f75e67 --- /dev/null +++ b/third_party/blink/renderer/core/app_history/app_history_current_change_event.idl
@@ -0,0 +1,13 @@ +// Copyright 2021 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. + +// https://github.com/WICG/app-history/ +[ + Exposed=Window, + RuntimeEnabled=AppHistory +] interface AppHistoryCurrentChangeEvent : Event { + constructor(DOMString type, AppHistoryCurrentChangeEventInit eventInit); + readonly attribute AppHistoryNavigationType? navigationType; + readonly attribute AppHistoryEntry from; +};
diff --git a/third_party/blink/renderer/core/app_history/app_history_current_change_event_init.idl b/third_party/blink/renderer/core/app_history/app_history_current_change_event_init.idl new file mode 100644 index 0000000..eb3fa51 --- /dev/null +++ b/third_party/blink/renderer/core/app_history/app_history_current_change_event_init.idl
@@ -0,0 +1,9 @@ +// Copyright 2021 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. + +// https://github.com/WICG/app-history/ +dictionary AppHistoryCurrentChangeEventInit : EventInit { + AppHistoryNavigationType? navigationType = null; + required AppHistoryEntry from; +};
diff --git a/third_party/blink/renderer/core/app_history/build.gni b/third_party/blink/renderer/core/app_history/build.gni index 2487b07..918b64c 100644 --- a/third_party/blink/renderer/core/app_history/build.gni +++ b/third_party/blink/renderer/core/app_history/build.gni
@@ -7,6 +7,8 @@ "app_history.h", "app_history_api_navigation.cc", "app_history_api_navigation.h", + "app_history_current_change_event.cc", + "app_history_current_change_event.h", "app_history_destination.h", "app_history_entry.cc", "app_history_entry.h",
diff --git a/third_party/blink/renderer/core/css/css_value.h b/third_party/blink/renderer/core/css/css_value.h index 431bc266..08c7f06 100644 --- a/third_party/blink/renderer/core/css/css_value.h +++ b/third_party/blink/renderer/core/css/css_value.h
@@ -33,18 +33,6 @@ class CORE_EXPORT CSSValue : public GarbageCollected<CSSValue> { public: -#if !BUILDFLAG(USE_V8_OILPAN) - template <typename T> - static void* AllocateObject(size_t size) { - ThreadState* state = - ThreadStateFor<ThreadingTrait<CSSValue>::kAffinity>::GetState(); - const char* type_name = "blink::CSSValue"; - return state->Heap().AllocateOnArenaIndex( - state, size, BlinkGC::kCSSValueArenaIndex, - GCInfoTrait<GCInfoFoldedType<CSSValue>>::Index(), type_name); - } -#endif // !USE_V8_OILPAN - // TODO(sashab): Remove this method and move logic to the caller. static CSSValue* Create(const Length& value, float zoom); @@ -351,7 +339,6 @@ } // namespace blink -#if BUILDFLAG(USE_V8_OILPAN) namespace cppgc { // Assign CSSValue to be allocated on custom CSSValueSpace. template <typename T> @@ -361,6 +348,5 @@ using Space = blink::CSSValueSpace; }; } // namespace cppgc -#endif // !USE_V8_OILPAN #endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_VALUE_H_
diff --git a/third_party/blink/renderer/core/dom/node.h b/third_party/blink/renderer/core/dom/node.h index 52b1e3a..58df078e 100644 --- a/third_party/blink/renderer/core/dom/node.h +++ b/third_party/blink/renderer/core/dom/node.h
@@ -38,7 +38,6 @@ #include "third_party/blink/renderer/core/style/computed_style_constants.h" #include "third_party/blink/renderer/platform/heap/custom_spaces.h" #include "third_party/blink/renderer/platform/text/text_direction.h" -#include "third_party/blink/renderer/platform/wtf/buildflags.h" // This needs to be here because element.cc also depends on it. #define DUMP_NODE_STATISTICS 0 @@ -179,18 +178,6 @@ kDocumentPositionImplementationSpecific = 0x20, }; -#if !BUILDFLAG(USE_V8_OILPAN) - template <typename T> - static void* AllocateObject(size_t size) { - ThreadState* state = - ThreadStateFor<ThreadingTrait<Node>::kAffinity>::GetState(); - const char* type_name = "blink::Node"; - return state->Heap().AllocateOnArenaIndex( - state, size, BlinkGC::kNodeArenaIndex, - GCInfoTrait<GCInfoFoldedType<T>>::Index(), type_name); - } -#endif // !BUILDFLAG(USE_V8_OILPAN) - static void DumpStatistics(); ~Node() override; @@ -1197,7 +1184,6 @@ void showNodePath(const blink::Node*); #endif -#if BUILDFLAG(USE_V8_OILPAN) namespace cppgc { // Assign Node to be allocated on custom NodeSpace. template <typename T> @@ -1215,6 +1201,4 @@ }; } // namespace blink -#endif // USE_V8_OILPAN - #endif // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_NODE_H_
diff --git a/third_party/blink/renderer/core/dom/node_list.h b/third_party/blink/renderer/core/dom/node_list.h index f3487ad..9e3fa27d 100644 --- a/third_party/blink/renderer/core/dom/node_list.h +++ b/third_party/blink/renderer/core/dom/node_list.h
@@ -27,7 +27,6 @@ #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" #include "third_party/blink/renderer/platform/heap/thread_state.h" -#include "third_party/blink/renderer/platform/wtf/buildflags.h" namespace blink { @@ -53,14 +52,12 @@ NodeList() = default; }; -#if BUILDFLAG(USE_V8_OILPAN) template <typename T> struct ThreadingTrait< T, std::enable_if_t<std::is_base_of<blink::NodeList, T>::value>> { static constexpr ThreadAffinity kAffinity = kMainThreadOnly; }; -#endif // USE_V8_OILPAN } // namespace blink
diff --git a/third_party/blink/renderer/core/dom/node_rare_data.h b/third_party/blink/renderer/core/dom/node_rare_data.h index a64ec61..97c9a47 100644 --- a/third_party/blink/renderer/core/dom/node_rare_data.h +++ b/third_party/blink/renderer/core/dom/node_rare_data.h
@@ -26,7 +26,6 @@ #include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/heap/thread_state.h" #include "third_party/blink/renderer/platform/wtf/bit_field.h" -#include "third_party/blink/renderer/platform/wtf/buildflags.h" #include "third_party/blink/renderer/platform/wtf/casting.h" #include "third_party/blink/renderer/platform/wtf/hash_set.h" @@ -262,14 +261,12 @@ Member<HeapHashSet<Member<ScrollTimeline>>> scroll_timelines_; }; -#if BUILDFLAG(USE_V8_OILPAN) template <typename T> struct ThreadingTrait< T, std::enable_if_t<std::is_base_of<blink::NodeRareData, T>::value>> { static constexpr ThreadAffinity kAffinity = kMainThreadOnly; }; -#endif // USE_V8_OILPAN } // namespace blink
diff --git a/third_party/blink/renderer/core/events/event_type_names.json5 b/third_party/blink/renderer/core/events/event_type_names.json5 index f44f743..d1ed1f9 100644 --- a/third_party/blink/renderer/core/events/event_type_names.json5 +++ b/third_party/blink/renderer/core/events/event_type_names.json5
@@ -91,6 +91,7 @@ "crossoriginmessage", "currentscreenchange", "cuechange", + "currentchange", "cut", "datachannel", "dblclick",
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h index d3560b5..9abef249 100644 --- a/third_party/blink/renderer/core/layout/layout_object.h +++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -300,19 +300,6 @@ friend class VisualRectMappingTest; public: -#if !BUILDFLAG(USE_V8_OILPAN) - // Use a type specific arena for LayoutObject - template <typename T> - static void* AllocateObject(size_t size) { - ThreadState* state = - ThreadStateFor<ThreadingTrait<LayoutObject>::kAffinity>::GetState(); - const char* type_name = "blink::LayoutObject"; - return state->Heap().AllocateOnArenaIndex( - state, size, BlinkGC::kLayoutObjectArenaIndex, - GCInfoTrait<GCInfoFoldedType<LayoutObject>>::Index(), type_name); - } -#endif // !BUILDFLAG(USE_V8_OILPAN) - // Anonymous objects should pass the document as their node, and they will // then automatically be marked as anonymous in the constructor. explicit LayoutObject(Node*); @@ -4632,7 +4619,6 @@ #endif -#if BUILDFLAG(USE_V8_OILPAN) namespace cppgc { // Assign LayoutObject to be allocated on custom LayoutObjectSpace. template <typename T> @@ -4642,6 +4628,5 @@ using Space = blink::LayoutObjectSpace; }; } // namespace cppgc -#endif // USE_V8_OILPAN #endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_OBJECT_H_
diff --git a/third_party/blink/renderer/core/layout/line/inline_box.h b/third_party/blink/renderer/core/layout/line/inline_box.h index 62a2fe37..285eaca2 100644 --- a/third_party/blink/renderer/core/layout/line/inline_box.h +++ b/third_party/blink/renderer/core/layout/line/inline_box.h
@@ -45,19 +45,6 @@ class CORE_EXPORT InlineBox : public GarbageCollected<InlineBox>, public DisplayItemClient { public: -#if !BUILDFLAG(USE_V8_OILPAN) - // Use a type specific arena - template <typename T> - static void* AllocateObject(size_t size) { - ThreadState* state = - ThreadStateFor<ThreadingTrait<InlineBox>::kAffinity>::GetState(); - const char* type_name = "blink::InlineBox"; - return state->Heap().AllocateOnArenaIndex( - state, size, BlinkGC::kLayoutObjectArenaIndex, - GCInfoTrait<GCInfoFoldedType<InlineBox>>::Index(), type_name); - } -#endif // !BUILDFLAG(USE_V8_OILPAN) - explicit InlineBox(LineLayoutItem obj) : next_(nullptr), prev_(nullptr), @@ -531,7 +518,6 @@ void showLineTree(const blink::InlineBox*); #endif -#if BUILDFLAG(USE_V8_OILPAN) namespace cppgc { // Assign InlineBox to be allocated on custom LayoutObjectSpace. template <typename T> @@ -541,6 +527,5 @@ using Space = blink::LayoutObjectSpace; }; } // namespace cppgc -#endif // USE_V8_OILPAN #endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LINE_INLINE_BOX_H_
diff --git a/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc index 39b11ff..a42b31b 100644 --- a/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc
@@ -133,11 +133,6 @@ return AxisEdge::kStart; } -LayoutUnit ComputeSizeFromAspectRatio(LayoutUnit extent, - const LogicalSize& aspect_ratio) { - return extent.MulDiv(aspect_ratio.inline_size, aspect_ratio.block_size); -} - } // namespace void NGFlexLayoutAlgorithm::HandleOutOfFlowPositioned(NGBlockNode child) { @@ -285,23 +280,6 @@ DoesItemStretch(child); } -LogicalSize NGFlexLayoutAlgorithm::GetMainOverCrossAspectRatio( - const NGBlockNode& child) const { - DCHECK(child.HasAspectRatio()); - LogicalSize aspect_ratio = child.GetAspectRatio(); - - DCHECK_GT(aspect_ratio.inline_size, 0); - DCHECK_GT(aspect_ratio.block_size, 0); - - // Multiplying by ratio will take something in the item's block axis and - // convert it to the inline axis. We want to convert from cross size to main - // size. If block axis and cross axis are the same, then we already have what - // we need. Otherwise we need to use the reciprocal. - if (!MainAxisIsInlineAxis(child)) - aspect_ratio.Transpose(); - return aspect_ratio; -} - NGConstraintSpace NGFlexLayoutAlgorithm::BuildSpaceForIntrinsicBlockSize( const NGBlockNode& flex_item) const { const ComputedStyle& child_style = flex_item.Style(); @@ -449,12 +427,14 @@ DCHECK_GE(cross_size, LayoutUnit()); cross_size = min_max_sizes_in_cross_axis_direction.ClampSizeToMinAndMax( cross_size); - // TODO(dgrogan): This isn't right for non-replaced aspect-ratio items - // with box-sizing: border-box, but it's what existing code does. Fix in a - // follow-up CL by reusing something from ng_length_utils. - return ComputeSizeFromAspectRatio(cross_size - cross_axis_border_padding, - GetMainOverCrossAspectRatio(child)) + - main_axis_border_padding; + if (MainAxisIsInlineAxis(child)) { + return InlineSizeFromAspectRatio( + border_padding_in_child_writing_mode, child.GetAspectRatio(), + child_style.BoxSizingForAspectRatio(), cross_size); + } + return BlockSizeFromAspectRatio( + border_padding_in_child_writing_mode, child.GetAspectRatio(), + child_style.BoxSizingForAspectRatio(), cross_size); }; // The logic that calculates flex_base_border_box assumes that the used @@ -550,13 +530,18 @@ } DCHECK_GE(content_size_suggestion, main_axis_border_padding); - if (child.HasAspectRatio()) { + // TODO(crbug.com/1252693): + // This code block is needed because + // IntrinsicBlockSizeFunc incorrectly ignores the inline min/max + // constraints for aspect-ratio items. So we apply those constraints here + // in AdjustChildSizeForAspectRatioCrossAxisMinAndMax. Once 1252693 is + // fixed, we can delete this entire code block. + if (child.HasAspectRatio() && !MainAxisIsInlineAxis(child)) { content_size_suggestion = AdjustChildSizeForAspectRatioCrossAxisMinAndMax( child, content_size_suggestion, - min_max_sizes_in_cross_axis_direction.min_size, - min_max_sizes_in_cross_axis_direction.max_size, - main_axis_border_padding, cross_axis_border_padding); + min_max_sizes_in_cross_axis_direction, + border_padding_in_child_writing_mode); } LayoutUnit specified_size_suggestion = LayoutUnit::Max(); @@ -640,45 +625,24 @@ NGFlexLayoutAlgorithm::AdjustChildSizeForAspectRatioCrossAxisMinAndMax( const NGBlockNode& child, LayoutUnit content_size_suggestion, - LayoutUnit cross_min, - LayoutUnit cross_max, - LayoutUnit main_axis_border_padding, - LayoutUnit cross_axis_border_padding) { + const MinMaxSizes& cross_min_max, + const NGBoxStrut& border_padding_in_child_writing_mode) { DCHECK(child.HasAspectRatio()); - const LogicalSize ratio = GetMainOverCrossAspectRatio(child); // Clamp content_suggestion by any definite min and max cross size properties // converted through the aspect ratio. - const Length& cross_max_length = is_horizontal_flow_ - ? child.Style().MaxHeight() - : child.Style().MaxWidth(); - DCHECK_GE(cross_max, cross_axis_border_padding); - // TODO(dgrogan): No tests fail if we unconditionally apply max_main_length. - // Either add a test that needs it or remove it. - if (IsItemCrossAxisLengthDefinite(child, cross_max_length)) { - LayoutUnit max_main_length = - main_axis_border_padding + - ComputeSizeFromAspectRatio(cross_max - cross_axis_border_padding, - ratio); - content_size_suggestion = - std::min(max_main_length, content_size_suggestion); + if (MainAxisIsInlineAxis(child)) { + auto min_max = ComputeTransferredMinMaxInlineSizes( + child.GetAspectRatio(), cross_min_max, + border_padding_in_child_writing_mode, + child.Style().BoxSizingForAspectRatio()); + return min_max.ClampSizeToMinAndMax(content_size_suggestion); } - - const Length& cross_min_length = is_horizontal_flow_ - ? child.Style().MinHeight() - : child.Style().MinWidth(); - DCHECK_GE(cross_min, cross_axis_border_padding); - // TODO(dgrogan): Same as above with min_main_length here -- it may be - // unneeded or untested. - if (IsItemCrossAxisLengthDefinite(child, cross_min_length)) { - LayoutUnit min_main_length = - main_axis_border_padding + - ComputeSizeFromAspectRatio(cross_min - cross_axis_border_padding, - ratio); - content_size_suggestion = - std::max(min_main_length, content_size_suggestion); - } - return content_size_suggestion; + auto min_max = ComputeTransferredMinMaxBlockSizes( + child.GetAspectRatio(), cross_min_max, + border_padding_in_child_writing_mode, + child.Style().BoxSizingForAspectRatio()); + return min_max.ClampSizeToMinAndMax(content_size_suggestion); } scoped_refptr<const NGLayoutResult> NGFlexLayoutAlgorithm::Layout() {
diff --git a/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.h index 478eef3..2f0704f 100644 --- a/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.h +++ b/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.h
@@ -40,7 +40,6 @@ const Length& length) const; bool AspectRatioProvidesMainSize(const NGBlockNode& child, const Length& cross_axis_length) const; - LogicalSize GetMainOverCrossAspectRatio(const NGBlockNode& child) const; bool DoesItemStretch(const NGBlockNode& child) const; // This implements the first of the additional scenarios where a flex item // has definite sizes when it would not if it weren't a flex item. @@ -49,10 +48,8 @@ LayoutUnit AdjustChildSizeForAspectRatioCrossAxisMinAndMax( const NGBlockNode& child, LayoutUnit content_suggestion, - LayoutUnit cross_min, - LayoutUnit cross_max, - LayoutUnit main_axis_border_padding, - LayoutUnit cross_axis_border_padding); + const MinMaxSizes& cross_min_max, + const NGBoxStrut& border_padding_in_child_writing_mode); bool IsColumnContainerMainSizeDefinite() const; bool IsContainerCrossSizeDefinite() const;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc index 8d19bf0..d864ad2 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc
@@ -614,6 +614,26 @@ return transferred_min_max; } +MinMaxSizes ComputeTransferredMinMaxBlockSizes( + const LogicalSize& ratio, + const MinMaxSizes& inline_min_max, + const NGBoxStrut& border_padding, + const EBoxSizing sizing) { + MinMaxSizes transferred_min_max = {LayoutUnit(), LayoutUnit::Max()}; + if (inline_min_max.min_size > LayoutUnit()) { + transferred_min_max.min_size = BlockSizeFromAspectRatio( + border_padding, ratio, sizing, inline_min_max.min_size); + } + if (inline_min_max.max_size != LayoutUnit::Max()) { + transferred_min_max.max_size = BlockSizeFromAspectRatio( + border_padding, ratio, sizing, inline_min_max.max_size); + } + // Minimum size wins over maximum size. + transferred_min_max.max_size = + std::max(transferred_min_max.max_size, transferred_min_max.min_size); + return transferred_min_max; +} + MinMaxSizes ComputeMinMaxInlineSizesFromAspectRatio( const NGConstraintSpace& constraint_space, const ComputedStyle& style,
diff --git a/third_party/blink/renderer/core/layout/ng/ng_length_utils.h b/third_party/blink/renderer/core/layout/ng/ng_length_utils.h index e462429a..ae1e9ea 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_length_utils.h +++ b/third_party/blink/renderer/core/layout/ng/ng_length_utils.h
@@ -297,6 +297,10 @@ const MinMaxSizes& block_min_max, const NGBoxStrut& border_padding, const EBoxSizing sizing); +MinMaxSizes ComputeTransferredMinMaxBlockSizes(const LogicalSize& ratio, + const MinMaxSizes& block_min_max, + const NGBoxStrut& border_padding, + const EBoxSizing sizing); // Computes the transferred min/max inline sizes from the min/max block // sizes and the aspect ratio.
diff --git a/third_party/blink/renderer/core/messaging/blink_transferable_message.cc b/third_party/blink/renderer/core/messaging/blink_transferable_message.cc index bfbf961..c4b6284 100644 --- a/third_party/blink/renderer/core/messaging/blink_transferable_message.cc +++ b/third_party/blink/renderer/core/messaging/blink_transferable_message.cc
@@ -116,16 +116,4 @@ return UnacceleratedStaticBitmapImage::Create(std::move(image)); } -absl::optional<SkBitmap> ToSkBitmap( - const scoped_refptr<blink::StaticBitmapImage>& static_bitmap_image) { - const sk_sp<SkImage> image = - static_bitmap_image->PaintImageForCurrentFrame().GetSwSkImage(); - SkBitmap result; - if (image && image->asLegacyBitmap( - &result, SkImage::LegacyBitmapMode::kRO_LegacyBitmapMode)) { - return result; - } - return absl::nullopt; -} - } // namespace blink
diff --git a/third_party/blink/renderer/core/messaging/blink_transferable_message.h b/third_party/blink/renderer/core/messaging/blink_transferable_message.h index c1140c07a..11549f9 100644 --- a/third_party/blink/renderer/core/messaging/blink_transferable_message.h +++ b/third_party/blink/renderer/core/messaging/blink_transferable_message.h
@@ -39,9 +39,6 @@ CORE_EXPORT scoped_refptr<blink::StaticBitmapImage> ToStaticBitmapImage( const SkBitmap& sk_bitmap); -CORE_EXPORT absl::optional<SkBitmap> ToSkBitmap( - const scoped_refptr<blink::StaticBitmapImage>& static_bitmap_image); - } // namespace blink namespace WTF {
diff --git a/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits.cc b/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits.cc index c3cc5c5..de1c4cb 100644 --- a/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits.cc +++ b/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits.cc
@@ -5,12 +5,38 @@ #include "third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits.h" #include "mojo/public/cpp/base/big_buffer_mojom_traits.h" +#include "skia/ext/skia_utils_base.h" #include "third_party/blink/public/mojom/messaging/transferable_message.mojom-blink.h" #include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h" #include "third_party/skia/include/core/SkBitmap.h" namespace mojo { +namespace { + +absl::optional<SkBitmap> ToSkBitmapN32( + const scoped_refptr<blink::StaticBitmapImage>& static_bitmap_image) { + const sk_sp<SkImage> image = + static_bitmap_image->PaintImageForCurrentFrame().GetSwSkImage(); + if (!image) + return absl::nullopt; + + SkBitmap sk_bitmap; + if (!image->asLegacyBitmap(&sk_bitmap, + SkImage::LegacyBitmapMode::kRO_LegacyBitmapMode)) { + return absl::nullopt; + } + + SkBitmap sk_bitmap_n32; + if (!skia::SkBitmapToN32OpaqueOrPremul(sk_bitmap, &sk_bitmap_n32)) { + return absl::nullopt; + } + + return sk_bitmap_n32; +} + +} // namespace + Vector<SkBitmap> StructTraits<blink::mojom::blink::TransferableMessage::DataView, blink::BlinkTransferableMessage>:: @@ -19,11 +45,13 @@ out.ReserveInitialCapacity( input.message->GetImageBitmapContentsArray().size()); for (auto& bitmap_contents : input.message->GetImageBitmapContentsArray()) { - absl::optional<SkBitmap> bitmap = blink::ToSkBitmap(bitmap_contents); - if (!bitmap) { + // TransferableMessage::image_bitmap_contents_array is an array of + // skia.mojom.BitmapN32, so SkBitmap should be in N32 format. + auto bitmap_n32 = ToSkBitmapN32(bitmap_contents); + if (!bitmap_n32) { return Vector<SkBitmap>(); } - out.push_back(std::move(bitmap.value())); + out.push_back(std::move(bitmap_n32.value())); } return out; }
diff --git a/third_party/blink/renderer/core/paint/paint_layer.h b/third_party/blink/renderer/core/paint/paint_layer.h index ab91cf4..4e6429e 100644 --- a/third_party/blink/renderer/core/paint/paint_layer.h +++ b/third_party/blink/renderer/core/paint/paint_layer.h
@@ -250,19 +250,6 @@ class CORE_EXPORT PaintLayer : public GarbageCollected<PaintLayer>, public DisplayItemClient { public: -#if !BUILDFLAG(USE_V8_OILPAN) - // Use a type specific arena - template <typename T> - static void* AllocateObject(size_t size) { - ThreadState* state = - ThreadStateFor<ThreadingTrait<PaintLayer>::kAffinity>::GetState(); - const char* type_name = "blink::PaintLayer"; - return state->Heap().AllocateOnArenaIndex( - state, size, BlinkGC::kLayoutObjectArenaIndex, - GCInfoTrait<GCInfoFoldedType<PaintLayer>>::Index(), type_name); - } -#endif // !BUILDFLAG(USE_V8_OILPAN) - explicit PaintLayer(LayoutBoxModelObject*); PaintLayer(const PaintLayer&) = delete; PaintLayer& operator=(const PaintLayer&) = delete; @@ -1558,7 +1545,6 @@ CORE_EXPORT void showLayerTree(const blink::LayoutObject*); #endif -#if BUILDFLAG(USE_V8_OILPAN) namespace cppgc { // Assign PaintLayer to be allocated on custom LayoutObjectSpace. template <typename T> @@ -1568,6 +1554,5 @@ using Space = blink::LayoutObjectSpace; }; } // namespace cppgc -#endif // USE_V8_OILPAN #endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_LAYER_H_
diff --git a/third_party/blink/renderer/modules/credentialmanager/public_key_credential.cc b/third_party/blink/renderer/modules/credentialmanager/public_key_credential.cc index c66341f..44378a4 100644 --- a/third_party/blink/renderer/modules/credentialmanager/public_key_credential.cc +++ b/third_party/blink/renderer/modules/credentialmanager/public_key_credential.cc
@@ -40,22 +40,13 @@ : Credential(id, type.IsEmpty() ? kPublicKeyCredentialType : type), raw_id_(raw_id), response_(response), - authenticatorAttachment_( - GetAuthenticatorAttachment(has_transport, transport)), + authenticator_attachment_( + has_transport ? (transport == mojom::AuthenticatorTransport::INTERNAL + ? absl::make_optional("platform") + : absl::make_optional("cross-platform")) + : absl::nullopt), extension_outputs_(extension_outputs) {} -absl::optional<String> PublicKeyCredential::GetAuthenticatorAttachment( - bool has_transport, - mojom::AuthenticatorTransport transport) { - absl::optional<String> authenticatorAttachment; - if (has_transport) { - authenticatorAttachment = - transport == mojom::AuthenticatorTransport::INTERNAL ? "platform" - : "cross-platform"; - } - return authenticatorAttachment; -} - ScriptPromise PublicKeyCredential::isUserVerifyingPlatformAuthenticatorAvailable( ScriptState* script_state) {
diff --git a/third_party/blink/renderer/modules/credentialmanager/public_key_credential.h b/third_party/blink/renderer/modules/credentialmanager/public_key_credential.h index 028a493..55b44cd 100644 --- a/third_party/blink/renderer/modules/credentialmanager/public_key_credential.h +++ b/third_party/blink/renderer/modules/credentialmanager/public_key_credential.h
@@ -38,11 +38,8 @@ DOMArrayBuffer* rawId() const { return raw_id_.Get(); } AuthenticatorResponse* response() const { return response_.Get(); } absl::optional<String> authenticatorAttachment() const { - return authenticatorAttachment_; + return authenticator_attachment_; } - absl::optional<String> GetAuthenticatorAttachment( - bool has_transport, - mojom::AuthenticatorTransport transport); static ScriptPromise isUserVerifyingPlatformAuthenticatorAvailable( ScriptState*); AuthenticationExtensionsClientOutputs* getClientExtensionResults() const; @@ -54,7 +51,7 @@ private: const Member<DOMArrayBuffer> raw_id_; const Member<AuthenticatorResponse> response_; - const absl::optional<String> authenticatorAttachment_; + const absl::optional<String> authenticator_attachment_; Member<const AuthenticationExtensionsClientOutputs> extension_outputs_; };
diff --git a/third_party/blink/renderer/modules/mediastream/focusable_media_stream_track.idl b/third_party/blink/renderer/modules/mediastream/focusable_media_stream_track.idl index 34768ec..ce69ada9 100644 --- a/third_party/blink/renderer/modules/mediastream/focusable_media_stream_track.idl +++ b/third_party/blink/renderer/modules/mediastream/focusable_media_stream_track.idl
@@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// TODO(crbug.com/1215480): Link to spec once produced. +// https://wicg.github.io/conditional-focus/ enum CaptureStartFocusBehavior { "focus-captured-surface", "no-focus-change" }; -// TODO(crbug.com/1215480): Link to spec once produced. +// https://wicg.github.io/conditional-focus/ [ Exposed = Window, RuntimeEnabled = ConditionalFocus @@ -23,7 +23,6 @@ // Promise<MediaStream> is resolved, or if the call comes too late due // to processing delays, the user agent assumes an implicit call with |focus| // set to a value decided by the user agent itself. - // TODO(crbug.com/1215480): Link to WICG spec once produced. [CallWith = ExecutionContext, RaisesException] void focus(CaptureStartFocusBehavior focus_behavior); };
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn index aa9130f..04bc65ba 100644 --- a/third_party/blink/renderer/platform/BUILD.gn +++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -1670,7 +1670,6 @@ "//third_party/blink/renderer/platform/loader", "//third_party/blink/renderer/platform/network", "//third_party/blink/renderer/platform/scheduler", - "//third_party/blink/renderer/platform/wtf:buildflags", "//third_party/fdlibm", "//third_party/pffft:pffft", "//ui/gfx", @@ -1985,7 +1984,7 @@ test("blink_platform_unittests") { deps = [ ":blink_platform_unittests_sources" ] - if (is_fuchsia && enable_blink_heap_use_v8_oilpan) { + if (is_fuchsia) { # Oilpan reuses V8's v8::PageAllocator which generally requires JIT # permissions. additional_manifest_fragments =
diff --git a/third_party/blink/renderer/platform/bindings/active_script_wrappable_base.h b/third_party/blink/renderer/platform/bindings/active_script_wrappable_base.h index 24b700d..0af0d66 100644 --- a/third_party/blink/renderer/platform/bindings/active_script_wrappable_base.h +++ b/third_party/blink/renderer/platform/bindings/active_script_wrappable_base.h
@@ -42,8 +42,6 @@ } // namespace blink -#if BUILDFLAG(USE_V8_OILPAN) - namespace cppgc { template <typename T, typename Unused> struct PostConstructionCallbackTrait; @@ -62,24 +60,4 @@ }; } // namespace cppgc -#else // !USE_V8_OILPAN - -namespace blink { -template <typename T> -struct PostConstructionHookTrait< - T, - base::void_t<decltype( - std::declval<T>().ActiveScriptWrappableBaseConstructed())>> { - static void Call(T* object) { - static_assert(std::is_base_of<ActiveScriptWrappableBase, T>::value, - "Only ActiveScriptWrappableBase should use the " - "post-construction hook."); - object->ActiveScriptWrappableBaseConstructed(); - } -}; - -} // namespace blink - -#endif // !USE_V8_OILPAN - #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_ACTIVE_SCRIPT_WRAPPABLE_BASE_H_
diff --git a/third_party/blink/renderer/platform/bindings/name_client.h b/third_party/blink/renderer/platform/bindings/name_client.h index f6e4cfb..83d70fb 100644 --- a/third_party/blink/renderer/platform/bindings/name_client.h +++ b/third_party/blink/renderer/platform/bindings/name_client.h
@@ -7,11 +7,7 @@ #include "third_party/blink/renderer/platform/bindings/buildflags.h" #include "third_party/blink/renderer/platform/platform_export.h" -#include "third_party/blink/renderer/platform/wtf/buildflags.h" - -#if BUILDFLAG(USE_V8_OILPAN) #include "v8/include/cppgc/name-provider.h" -#endif // BUILDFLAG(USE_V8_OILPAN) namespace blink { @@ -40,8 +36,6 @@ // Don't: // class Bar : public GarbageCollected<Bar> {...}; // class Baz : public Bar, public NameClient {...}; -#if BUILDFLAG(USE_V8_OILPAN) - class PLATFORM_EXPORT NameClient : public cppgc::NameProvider { public: NameClient() = default; @@ -58,31 +52,6 @@ } }; -#else // !USE_V8_OILPAN - -class PLATFORM_EXPORT NameClient { - public: - static constexpr bool HideInternalName() { -#if BUILDFLAG(RAW_HEAP_SNAPSHOTS) && \ - (defined(COMPILER_GCC) || defined(__clang__)) - return false; -#else - return true; -#endif // BUILDFLAG(RAW_HEAP_SNAPSHOTS) - } - - NameClient() = default; - NameClient(const NameClient&) = delete; - NameClient& operator=(const NameClient&) = delete; - virtual ~NameClient() = default; - - // Human-readable name of this object. The DevTools heap snapshot uses - // this method to show the object. - virtual const char* NameInHeapSnapshot() const = 0; -}; - -#endif // !USE_V8_OILPAN - } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_NAME_CLIENT_H_
diff --git a/third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h b/third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h index 7460e845..12b6702 100644 --- a/third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h +++ b/third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h
@@ -10,14 +10,10 @@ #include "base/compiler_specific.h" #include "third_party/blink/renderer/platform/heap/unified_heap_marking_visitor.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" -#include "third_party/blink/renderer/platform/wtf/buildflags.h" #include "third_party/blink/renderer/platform/wtf/hash_traits.h" #include "third_party/blink/renderer/platform/wtf/vector_traits.h" #include "v8/include/v8.h" - -#if BUILDFLAG(USE_V8_OILPAN) #include "v8/include/cppgc/trace-trait.h" -#endif // USE_V8_OILPAN namespace blink { @@ -121,31 +117,19 @@ protected: ALWAYS_INLINE void InternalSet(v8::Isolate* isolate, v8::Local<T> handle) { handle_.Reset(isolate, handle); -#if BUILDFLAG(USE_V8_OILPAN) UnifiedHeapMarkingVisitor::WriteBarrier(UnsafeCast<v8::Value>().Get()); -#else // !USE_V8_OILPAN - UnifiedHeapMarkingVisitor::WriteBarrier(UnsafeCast<v8::Value>()); -#endif // !USE_V8_OILPAN } ALWAYS_INLINE void WriteBarrier() const { -#if BUILDFLAG(USE_V8_OILPAN) UnifiedHeapMarkingVisitor::WriteBarrier(UnsafeCast<v8::Value>().Get()); -#else // !USE_V8_OILPAN - UnifiedHeapMarkingVisitor::WriteBarrier(UnsafeCast<v8::Value>()); -#endif // !USE_V8_OILPAN } v8::TracedReference<T> handle_; -#if BUILDFLAG(USE_V8_OILPAN) friend struct cppgc::TraceTrait<TraceWrapperV8Reference<T>>; -#endif // USE_V8_OILPAN }; } // namespace blink -#if BUILDFLAG(USE_V8_OILPAN) - namespace cppgc { template <typename T> struct TraceTrait<blink::TraceWrapperV8Reference<T>> { @@ -163,26 +147,6 @@ }; } // namespace cppgc -#else // !USE_V8_OILPAN - -namespace blink { -template <typename T> -struct TraceTrait<TraceWrapperV8Reference<T>> { - STATIC_ONLY(TraceTrait); - - static TraceDescriptor GetTraceDescriptor( - const TraceWrapperV8Reference<T>* ref) { - return {ref, TraceTrait<TraceWrapperV8Reference<T>>::Trace}; - } - - static void Trace(Visitor* visitor, const void* ref) { - visitor->Trace(*static_cast<const TraceWrapperV8Reference<T>*>(ref)); - } -}; -} // namespace blink - -#endif // !USE_V8_OILPAN - namespace WTF { template <typename T>
diff --git a/third_party/blink/renderer/platform/heap/BUILD.gn b/third_party/blink/renderer/platform/heap/BUILD.gn index 3a498b9..3110172 100644 --- a/third_party/blink/renderer/platform/heap/BUILD.gn +++ b/third_party/blink/renderer/platform/heap/BUILD.gn
@@ -33,14 +33,7 @@ configs -= [ "//build/config/compiler:afdo_optimize_size" ] } - if (!enable_blink_heap_use_v8_oilpan) { - sources = [ - "impl/unsanitized_atomic.cc", - "impl/unsanitized_atomic.h", - ] - } else { - sources = [] - } + sources = [] deps = [ "//base", @@ -90,100 +83,41 @@ "//base", "//third_party/blink/renderer/platform:make_platform_generated", "//third_party/blink/renderer/platform/heap:heap_unsanitized", - "//third_party/blink/renderer/platform/heap/asm", - "//third_party/blink/renderer/platform/wtf:buildflags", "//third_party/icu", "//v8", ] - if (enable_blink_heap_use_v8_oilpan) { - sources += [ - "v8_wrapper/blink_gc.h", - "v8_wrapper/blink_gc_memory_dump_provider.cc", - "v8_wrapper/blink_gc_memory_dump_provider.h", - "v8_wrapper/collection_support/heap_hash_table_backing.h", - "v8_wrapper/collection_support/heap_vector_backing.h", - "v8_wrapper/custom_spaces.cc", - "v8_wrapper/custom_spaces.h", - "v8_wrapper/garbage_collected.h", - "v8_wrapper/heap.h", - "v8_wrapper/heap_allocator_impl.h", - "v8_wrapper/member.h", - "v8_wrapper/persistent.h", - "v8_wrapper/process_heap.h", - "v8_wrapper/thread_local.h", - "v8_wrapper/thread_state.cc", - "v8_wrapper/thread_state.h", - "v8_wrapper/thread_state_scopes.h", - "v8_wrapper/trace_traits.h", - "v8_wrapper/unified_heap_marking_visitor.h", - "v8_wrapper/visitor.h", - "v8_wrapper/write_barrier.h", - ] + sources += [ + "v8_wrapper/blink_gc.h", + "v8_wrapper/blink_gc_memory_dump_provider.cc", + "v8_wrapper/blink_gc_memory_dump_provider.h", + "v8_wrapper/collection_support/heap_hash_table_backing.h", + "v8_wrapper/collection_support/heap_vector_backing.h", + "v8_wrapper/custom_spaces.cc", + "v8_wrapper/custom_spaces.h", + "v8_wrapper/garbage_collected.h", + "v8_wrapper/heap.h", + "v8_wrapper/heap_allocator_impl.h", + "v8_wrapper/member.h", + "v8_wrapper/persistent.h", + "v8_wrapper/process_heap.h", + "v8_wrapper/thread_local.h", + "v8_wrapper/thread_state.cc", + "v8_wrapper/thread_state.h", + "v8_wrapper/thread_state_scopes.h", + "v8_wrapper/trace_traits.h", + "v8_wrapper/unified_heap_marking_visitor.h", + "v8_wrapper/visitor.h", + "v8_wrapper/write_barrier.h", + ] - deps += [ - "//gin:gin", + deps += [ + "//gin:gin", - # Dependency on V8 which transitively depends on cppgc but exposes - # JS-related C++ heap through V8's Isolate. - "//v8", - ] - } else { - sources += [ - "impl/atomic_entry_flag.h", - "impl/blink_gc.cc", - "impl/blink_gc.h", - "impl/blink_gc_memory_dump_provider.cc", - "impl/blink_gc_memory_dump_provider.h", - "impl/collection_support/heap_hash_table_backing.h", - "impl/collection_support/heap_vector_backing.h", - "impl/finalizer_traits.h", - "impl/garbage_collected.h", - "impl/gc_info.cc", - "impl/gc_info.h", - "impl/heap.cc", - "impl/heap.h", - "impl/heap_allocator_impl.cc", - "impl/heap_allocator_impl.h", - "impl/heap_compact.cc", - "impl/heap_compact.h", - "impl/heap_page.cc", - "impl/heap_page.h", - "impl/heap_stats_collector.cc", - "impl/heap_stats_collector.h", - "impl/marking_scheduling_oracle.cc", - "impl/marking_scheduling_oracle.h", - "impl/marking_verifier.cc", - "impl/marking_verifier.h", - "impl/marking_visitor.cc", - "impl/marking_visitor.h", - "impl/member.h", - "impl/name_traits.h", - "impl/page_bloom_filter.h", - "impl/page_memory.cc", - "impl/page_memory.h", - "impl/page_pool.cc", - "impl/page_pool.h", - "impl/persistent.h", - "impl/persistent_node.cc", - "impl/persistent_node.h", - "impl/process_heap.cc", - "impl/process_heap.h", - "impl/thread_state.cc", - "impl/thread_state.h", - "impl/thread_state_scopes.h", - "impl/thread_state_statistics.cc", - "impl/thread_state_statistics.h", - "impl/threading_traits.h", - "impl/trace_traits.h", - "impl/unified_heap_controller.cc", - "impl/unified_heap_controller.h", - "impl/unified_heap_marking_visitor.cc", - "impl/unified_heap_marking_visitor.h", - "impl/visitor.h", - "impl/worklist.h", - ] - } + # Dependency on V8 which transitively depends on cppgc but exposes + # JS-related C++ heap through V8's Isolate. + "//v8", + ] if (!is_debug && !optimize_for_size) { configs -= [ "//build/config/compiler:default_optimization" ] @@ -210,17 +144,10 @@ "heap_test_utilities.h", ] - if (enable_blink_heap_use_v8_oilpan) { - sources += [ - "v8_wrapper/heap_test_utilities.cc", - "v8_wrapper/heap_test_utilities.h", - ] - } else { - sources += [ - "impl/heap_test_utilities.cc", - "impl/heap_test_utilities.h", - ] - } + sources += [ + "v8_wrapper/heap_test_utilities.cc", + "v8_wrapper/heap_test_utilities.h", + ] deps = [ ":blink_heap_buildflags", @@ -228,15 +155,12 @@ "//third_party/blink/public/mojom:mojom_platform_blink_headers", "//third_party/blink/renderer/platform:bindings_buildflags", "//third_party/blink/renderer/platform:platform", - "//third_party/blink/renderer/platform/wtf:buildflags", ] # TODO(v8:11952): Switch to `//v8:v8_for_testing` as target once it properly # depends on v8 without duplicating the whole library which causes ODR # violations when `//v8:v8` is also pulled in otherwise. - if (enable_blink_heap_use_v8_oilpan) { - deps += [ "//v8:v8" ] - } + deps += [ "//v8:v8" ] public_deps = [ "//base/test:test_support" ] } @@ -253,7 +177,7 @@ ] } - if (is_fuchsia && enable_blink_heap_use_v8_oilpan) { + if (is_fuchsia) { # Oilpan reuses V8's v8::PageAllocator which generally requires JIT # permissions. additional_manifest_fragments = @@ -280,23 +204,6 @@ "test/write_barrier_perftest.cc", ] - if (!enable_blink_heap_use_v8_oilpan) { - sources += [ - "impl/test/card_table_test.cc", - "impl/test/gc_info_test.cc", - "impl/test/heap_internals_test.cc", - "impl/test/heap_stats_collector_test.cc", - "impl/test/heap_thread_test.cc", - "impl/test/incremental_marking_internals_test.cc", - "impl/test/marking_scheduling_oracle_test.cc", - "impl/test/marking_verifier_test.cc", - "impl/test/name_trait_test.cc", - "impl/test/object_start_bitmap_test.cc", - "impl/test/thread_state_scheduling_test.cc", - "impl/test/worklist_test.cc", - ] - } - if (enable_blink_heap_young_generation) { sources += [ "test/minor_gc_test.cc" ] }
diff --git a/third_party/blink/renderer/platform/heap/asm/BUILD.gn b/third_party/blink/renderer/platform/heap/asm/BUILD.gn deleted file mode 100644 index fe44daf..0000000 --- a/third_party/blink/renderer/platform/heap/asm/BUILD.gn +++ /dev/null
@@ -1,47 +0,0 @@ -# Copyright 2014 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. - -if (current_cpu == "x86" || current_cpu == "x64") { - import("//third_party/nasm/nasm_assemble.gni") - - nasm_assemble("asm") { - assert(current_cpu == "x86" || current_cpu == "x64") - - sources = [ "SaveRegisters_x86.asm" ] - - defines = [] - if (is_mac) { - # Necessary to ensure symbols end up with a _ prefix; added by - # yasm_compile.gypi for Windows, but not Mac. - defines += [ "PREFIX" ] - } - if (current_cpu == "x64") { - if (is_win) { - defines += [ "X64WIN=1" ] - } else { - defines += [ "X64POSIX=1" ] - } - } else { # current_cpu == "x86" - defines += [ "IA32=1" ] - } - } -} else { # current_cpu == "x86" || current_cpu == "x64" - source_set("asm") { - if (current_cpu == "arm") { - sources = [ "SaveRegisters_arm.S" ] - } else if (current_cpu == "arm64") { - sources = [ "SaveRegisters_arm64.S" ] - } else if (current_cpu == "mipsel") { - sources = [ "SaveRegisters_mips.S" ] - } else if (current_cpu == "mips64el") { - sources = [ "SaveRegisters_mips64.S" ] - } else if (current_cpu == "ppc64") { - sources = [ "SaveRegisters_ppc64.S" ] - } - - if (current_cpu == "arm") { - defines = [ "ARM=1" ] - } - } -} # current_cpu == "x86" || current_cpu == "x64"
diff --git a/third_party/blink/renderer/platform/heap/asm/SaveRegisters_arm.S b/third_party/blink/renderer/platform/heap/asm/SaveRegisters_arm.S deleted file mode 100644 index a869228..0000000 --- a/third_party/blink/renderer/platform/heap/asm/SaveRegisters_arm.S +++ /dev/null
@@ -1,77 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - - -/* - * typedef void (*PushAllRegistersCallback)(ThreadState*, intptr_t*); - * extern "C" void PushAllRegisters(ThreadState*, PushAllRegistersCallback) - */ - -.type PushAllRegisters, %function -.global PushAllRegisters -.hidden PushAllRegisters -#ifdef __thumb__ -/* In THUMB Mode jump to ARM stub via bx to ensure CPU mode switch. - * FIXME: This trampoline is provided to workaround bugs in - * the THUMB/ARM interworking that appear in the component build. - * When these issues are resolved this stub can be removed. - */ -.align 2 -.code 16 -.thumb_func -PushAllRegisters: - adr r3, pushAllRegistersARM - bx r3 - -.type pushAllRegistersARM, %function -.hidden pushAllRegistersARM -.align 4 -.code 32 -pushAllRegistersARM: -#else -/* ARM Mode */ -.align 4 -.code 32 -PushAllRegisters: -#endif - /* Push all callee-saved registers and save return address. */ - push {r4-r11, lr} - /* Pass the first argument unchanged (r0) - * and pass the stack pointer after pushing callee-saved - * registers to the callback function. - */ - mov r2, r1 - mov r1, sp - blx r2 - /* Discard all the registers, and pop lr into pc which returns - * and switches mode if needed. - */ - add sp, sp, #32 - pop {pc}
diff --git a/third_party/blink/renderer/platform/heap/asm/SaveRegisters_arm64.S b/third_party/blink/renderer/platform/heap/asm/SaveRegisters_arm64.S deleted file mode 100644 index db13c5d..0000000 --- a/third_party/blink/renderer/platform/heap/asm/SaveRegisters_arm64.S +++ /dev/null
@@ -1,141 +0,0 @@ -/* - * Copyright (C) 2014 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - - -/* - * typedef void (*PushAllRegistersCallback)(ThreadState*, intptr_t*); - * extern "C" void PushAllRegisters(ThreadState*, PushAllRegistersCallback) - */ - -/* Supplementary macro for setting function attributes */ -.macro asm_function fname -#ifdef __APPLE__ - .globl _\fname - .private_extern _\fname -_\fname: -#else - .global \fname -#ifdef __ELF__ - .hidden \fname - .type \fname, %function -#endif -\fname: -#endif -.endm - -#if defined(__ARM_FEATURE_PAC_DEFAULT) && __ARM_FEATURE_PAC_DEFAULT - // ENABLE_PAUTH must be defined to 1 since this value will be used in - // bitwise-shift later! - #define ENABLE_PAUTH 1 - - #if ((__ARM_FEATURE_PAC_DEFAULT&((1<<0)|(1<<1)))==0) - #error Pointer authentication defines no valid key! - #endif -#else - #define ENABLE_PAUTH 0 -#endif - -#if defined(__ARM_FEATURE_BTI_DEFAULT) && (__ARM_FEATURE_BTI_DEFAULT==1) - // ENABLE_BTI must be defined to 1 since this value will be used in - // bitwise-shift later! - #define ENABLE_BTI 1 -#else - #define ENABLE_BTI 0 -#endif - - -// Although Pointer Authentication and Branch Target Instructions are technically -// seperate features they work together, i.e. the paciasp and pacibsp instructions -// serve as BTI landing pads. -// Therefore PA-instructions are enabled when PA _or_ BTI is enabled! -#if ENABLE_PAUTH || ENABLE_BTI - // See section "Pointer Authentication" of - // https://developer.arm.com/documentation/101028/0012/5--Feature-test-macros - // for details how to interpret __ARM_FEATURE_PAC_DEFAULT - #if (__ARM_FEATURE_PAC_DEFAULT & (1<<0)) - #define PAUTH_SIGN_SP paciasp - #define PAUTH_AUTH_SP autiasp - #else - #define PAUTH_SIGN_SP pacibsp - #define PAUTH_AUTH_SP autibsp - #endif -#else - #define PAUTH_SIGN_SP - #define PAUTH_AUTH_SP -#endif - - - -asm_function PushAllRegisters - .p2align 2 - - PAUTH_SIGN_SP - - /* Save return address. */ - sub sp, sp, #96 - stp x19, x20, [sp, #80] - stp x21, x22, [sp, #64] - stp x23, x24, [sp, #48] - stp x25, x26, [sp, #32] - stp x27, x28, [sp, #16] - stp x30, x29, [sp, #0] // x30 is lr. - - /* Pass the first argument unchanged (x0) - * and pass the stack pointer as third argument to the - * callback function. - */ - mov x2, x1 - mov x1, sp - blr x2 - - /* We don't restore all registers since they are callee saved (so - * the callback didn't clobber them) and we didn't modify them either. - */ - ldr x30, [sp], #96 - - PAUTH_AUTH_SP - - ret - -#if ENABLE_PAUTH || ENABLE_BTI -// see -// https://github.com/ARM-software/abi-aa/blob/main/aaelf64/aaelf64.rst#program-property -.pushsection .note.gnu.property, "a"; - .balign 8 - .long 4 - .long 0x10 - .long 0x5 - .asciz "GNU" - .long 0xc0000000 /* GNU_PROPERTY_AARCH64_FEATURE_1_AND */ - .long 4 - .long ((ENABLE_PAUTH)<<1) | ((ENABLE_BTI)<<0) /* PAuth and BTI */ - .long 0 -.popsection -#endif
diff --git a/third_party/blink/renderer/platform/heap/asm/SaveRegisters_mips.S b/third_party/blink/renderer/platform/heap/asm/SaveRegisters_mips.S deleted file mode 100644 index 5c2e717a..0000000 --- a/third_party/blink/renderer/platform/heap/asm/SaveRegisters_mips.S +++ /dev/null
@@ -1,64 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - - -/* - * typedef void (*PushAllRegistersCallback)(ThreadState*, intptr_t*); - * extern "C" void PushAllRegisters(ThreadState*, PushAllRegistersCallback) - */ - -.type PushAllRegisters, %function -.global PushAllRegisters -.hidden PushAllRegisters -PushAllRegisters: - // Reserve space for callee-saved registers, return address, - // as well as for the callee arguments. - addiu $sp,$sp,-56 - // Save the callee-saved registers and the return address. - sw $s0,16($sp) - sw $s1,20($sp) - sw $s2,24($sp) - sw $s3,28($sp) - sw $s4,32($sp) - sw $s5,36($sp) - sw $s6,40($sp) - sw $s7,44($sp) - sw $ra,48($sp) - // Pass the first argument untouched in a0 and the - // stack pointer to the callback. - move $t9,$a1 - move $a1,$sp - jalr $t9 - // Restore return address, adjust stack and return. No - // callee-saved register was changed so we do not have to - // restore callee-saved registers. - lw $ra,48($sp) - addiu $sp,$sp,56 - jr $ra
diff --git a/third_party/blink/renderer/platform/heap/asm/SaveRegisters_mips64.S b/third_party/blink/renderer/platform/heap/asm/SaveRegisters_mips64.S deleted file mode 100644 index 656cfb5..0000000 --- a/third_party/blink/renderer/platform/heap/asm/SaveRegisters_mips64.S +++ /dev/null
@@ -1,41 +0,0 @@ -// Copyright 2014 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. - -/* - * typedef void (*PushAllRegistersCallback)(ThreadState*, intptr_t*); - * extern "C" void PushAllRegisters(ThreadState*, PushAllRegistersCallback) - */ - -.type PushAllRegisters, %function -.global PushAllRegisters -.hidden PushAllRegisters -PushAllRegisters: - // Push all callee-saves registers to get them - // on the stack for conservative stack scanning. - // Reserve space for callee-saved registers and return address. - daddiu $sp,$sp,-80 - // Save the callee-saved registers and the return address. - sd $s0,0($sp) - sd $s1,8($sp) - sd $s2,16($sp) - sd $s3,24($sp) - sd $s4,32($sp) - sd $s5,40($sp) - sd $s6,48($sp) - sd $s7,56($sp) - sd $ra,64($sp) - // Note: the callee-saved floating point registers do not need to be - // copied to the stack, because fp registers never hold heap pointers - // and so do not need to be kept visible to the garbage collector. - // Pass the first argument untouched in a0 and the - // stack pointer to the callback. - move $t9,$a1 - move $a1,$sp - jalr $t9 - // Restore return address, adjust stack and return. - // Note: the copied registers do not need to be reloaded here, - // because they were preserved by the called routine. - ld $ra,64($sp) - daddiu $sp,$sp,80 - jr $ra
diff --git a/third_party/blink/renderer/platform/heap/asm/SaveRegisters_ppc64.S b/third_party/blink/renderer/platform/heap/asm/SaveRegisters_ppc64.S deleted file mode 100644 index ef6c3326e..0000000 --- a/third_party/blink/renderer/platform/heap/asm/SaveRegisters_ppc64.S +++ /dev/null
@@ -1,54 +0,0 @@ -/* - * typedef void (*PushAllRegistersCallback)(ThreadState*, intptr_t*); - * extern "C" void PushAllRegisters(ThreadState*, PushAllRegistersCallback) - */ - -.type PushAllRegisters, %function -.global PushAllRegisters -.hidden PushAllRegisters -PushAllRegisters: - // Push all callee-saves registers to get them - // on the stack for conservative stack scanning. - // Reserve space for callee-saved registers and minimal stack frame. - mflr 0 - std 0,16(1) - stdu 1,-176(1) // 3218*8 = min stack non-volatile registers - - // Save the callee-saved register - std 31,168(1) - std 30,160(1) - std 29,152(1) - std 28,144(1) - std 27,136(1) - std 26,128(1) - std 25,120(1) - std 24,112(1) - std 23,104(1) - std 22,96(1) - std 21,88(1) - std 20,80(1) - std 19,72(1) - std 18,64(1) - std 17,56(1) - std 16,48(1) - std 15,40(1) - std 14,32(1) - // Note: the callee-saved floating point registers do not need to be - // copied to the stack, because fp registers never hold heap pointers - // and so do not need to be kept visible to the garbage collector. - // Pass the first argument untouched in r3 and the - // stack pointer to the callback. - std 2, 24(1) - mtctr 4 - mr 12, 4 - mr 4, 1 - bctrl - ld 2, 24(1) - - // Adjust stack, restore return address and return. - // Note: the copied registers do not need to be reloaded here, - // because they were preserved by the called routine. - addi 1,1,176 - ld 0,16(1) - mtlr 0 - blr
diff --git a/third_party/blink/renderer/platform/heap/asm/SaveRegisters_x86.asm b/third_party/blink/renderer/platform/heap/asm/SaveRegisters_x86.asm deleted file mode 100644 index 9b23c82..0000000 --- a/third_party/blink/renderer/platform/heap/asm/SaveRegisters_x86.asm +++ /dev/null
@@ -1,162 +0,0 @@ -;; Copyright (C) 2013 Google Inc. All rights reserved. -;; -;; Redistribution and use in source and binary forms, with or without -;; modification, are permitted provided that the following conditions are -;; met: -;; -;; * Redistributions of source code must retain the above copyright -;; notice, this list of conditions and the following disclaimer. -;; * Redistributions in binary form must reproduce the above -;; copyright notice, this list of conditions and the following disclaimer -;; in the documentation and/or other materials provided with the -;; distribution. -;; * Neither the name of Google Inc. nor the names of its -;; contributors may be used to endorse or promote products derived from -;; this software without specific prior written permission. -;; -;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -;; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -;; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -;; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -;; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -;; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -;; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -;; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -;; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -;; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -;; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;; - -%ifndef X64POSIX -%define X64POSIX 0 -%endif - -%ifndef X64WIN -%define X64WIN 0 -%endif - -%ifndef IA32 -%define IA32 0 -%endif - -%ifndef ARM -%define ARM 0 -%endif - -;; Prefix symbols by '_' if PREFIX is defined. -%ifdef PREFIX -%define mangle(x) _ %+ x -%else -%define mangle(x) x -%endif - - -; global_private makes a symbol a global but private to this shared library. -%ifidn __OUTPUT_FORMAT__,elf32 - %define global_private(x) global mangle(x) %+ :function hidden -%elifidn __OUTPUT_FORMAT__,elf64 - %define global_private(x) global mangle(x) %+ :function hidden -%elifidn __OUTPUT_FORMAT__,elfx32 - %define global_private(x) global mangle(x) %+ :function hidden -%elifidn __OUTPUT_FORMAT__,macho32 - %define global_private(x) global mangle(x) %+ :private_extern -%elifidn __OUTPUT_FORMAT__,macho64 - %define global_private(x) global mangle(x) %+ :private_extern -%else - %define global_private(x) global mangle(x) -%endif - -section .text - -;; typedef void (*PushAllRegistersCallback)(ThreadState*, intptr_t*); -;; extern "C" void PushAllRegisters(ThreadState*, PushAllRegistersCallback) - - global_private(PushAllRegisters) - -%if X64POSIX - -mangle(PushAllRegisters): - ;; Push all callee-saves registers to get them - ;; on the stack for conservative stack scanning. - ;; We maintain 16-byte alignment at calls (required on Mac). - ;; There is an 8-byte return address on the stack and we push - ;; 56 bytes which maintains 16-byte stack alignment - ;; at the call. - push 0 - push rbx - push rbp - push r12 - push r13 - push r14 - push r15 - ;; Pass the first argument unchanged (rdi) - ;; and the stack pointer after pushing callee-saved - ;; registers to the callback. - mov r8, rsi - mov rsi, rsp - call r8 - ;; Pop the callee-saved registers. None of them were - ;; modified so no restoring is needed. - add rsp, 56 - ret - -%elif X64WIN - -mangle(PushAllRegisters): - ;; Push all callee-saves registers to get them - ;; on the stack for conservative stack scanning. - ;; There is an 8-byte return address on the stack and we push - ;; 72 bytes which maintains the required 16-byte stack alignment - ;; at the call. - push 0 - push rsi - push rdi - push rbx - push rbp - push r12 - push r13 - push r14 - push r15 - ;; Pass the first argument unchanged (rcx) - ;; and the stack pointer after pushing callee-saved - ;; registers to the callback. - mov r9, rdx - mov rdx, rsp - call r9 - ;; Pop the callee-saved registers. None of them were - ;; modified so no restoring is needed. - add rsp, 72 - ret - -%elif IA32 - -mangle(PushAllRegisters): - ;; Push all callee-saves registers to get them - ;; on the stack for conservative stack scanning. - ;; We maintain 16-byte alignment at calls (required on - ;; Mac). There is a 4-byte return address on the stack - ;; and we push 28 bytes which maintains 16-byte alignment - ;; at the call. - push ebx - push ebp - push esi - push edi - ;; Pass the first argument unchanged and the - ;; stack pointer after pushing callee-save registers - ;; to the callback. - mov ecx, [esp + 24] - push esp - push dword [esp + 24] - call ecx - ;; Pop arguments and the callee-saved registers. - ;; None of the callee-saved registers were modified - ;; so we do not need to restore them. - add esp, 24 - ret - - -%elif ARM -%error "NASM does not support arm. Use SaveRegisters_arm.S on arm." -%else -%error "Unsupported platform." -%endif
diff --git a/third_party/blink/renderer/platform/heap/blink_gc.h b/third_party/blink/renderer/platform/heap/blink_gc.h index 227089f..28a94f0 100644 --- a/third_party/blink/renderer/platform/heap/blink_gc.h +++ b/third_party/blink/renderer/platform/heap/blink_gc.h
@@ -5,12 +5,6 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_BLINK_GC_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_BLINK_GC_H_ -#include "third_party/blink/renderer/platform/wtf/buildflags.h" - -#if BUILDFLAG(USE_V8_OILPAN) #include "third_party/blink/renderer/platform/heap/v8_wrapper/blink_gc.h" -#else // !USE_V8_OILPAN -#include "third_party/blink/renderer/platform/heap/impl/blink_gc.h" -#endif // !USE_V8_OILPAN #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_BLINK_GC_H_
diff --git a/third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider.h b/third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider.h index 3e6f4c2f..9ae4b7d 100644 --- a/third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider.h +++ b/third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider.h
@@ -5,12 +5,6 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_BLINK_GC_MEMORY_DUMP_PROVIDER_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_BLINK_GC_MEMORY_DUMP_PROVIDER_H_ -#include "third_party/blink/renderer/platform/wtf/buildflags.h" - -#if BUILDFLAG(USE_V8_OILPAN) #include "third_party/blink/renderer/platform/heap/v8_wrapper/blink_gc_memory_dump_provider.h" -#else // !USE_V8_OILPAN -#include "third_party/blink/renderer/platform/heap/impl/blink_gc_memory_dump_provider.h" -#endif // !USE_V8_OILPAN #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_BLINK_GC_MEMORY_DUMP_PROVIDER_H_
diff --git a/third_party/blink/renderer/platform/heap/collection_support/heap_hash_table_backing.h b/third_party/blink/renderer/platform/heap/collection_support/heap_hash_table_backing.h index f1c4c969..d21c4780 100644 --- a/third_party/blink/renderer/platform/heap/collection_support/heap_hash_table_backing.h +++ b/third_party/blink/renderer/platform/heap/collection_support/heap_hash_table_backing.h
@@ -7,13 +7,8 @@ #include "third_party/blink/renderer/platform/heap/trace_traits.h" #include "third_party/blink/renderer/platform/heap/visitor.h" -#include "third_party/blink/renderer/platform/wtf/buildflags.h" -#if BUILDFLAG(USE_V8_OILPAN) #include "third_party/blink/renderer/platform/heap/v8_wrapper/collection_support/heap_hash_table_backing.h" -#else // !USE_V8_OILPAN -#include "third_party/blink/renderer/platform/heap/impl/collection_support/heap_hash_table_backing.h" -#endif // !USE_V8_OILPAN namespace blink {
diff --git a/third_party/blink/renderer/platform/heap/collection_support/heap_vector_backing.h b/third_party/blink/renderer/platform/heap/collection_support/heap_vector_backing.h index 0a29da5..7f7f24a 100644 --- a/third_party/blink/renderer/platform/heap/collection_support/heap_vector_backing.h +++ b/third_party/blink/renderer/platform/heap/collection_support/heap_vector_backing.h
@@ -5,12 +5,6 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_COLLECTION_SUPPORT_HEAP_VECTOR_BACKING_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_COLLECTION_SUPPORT_HEAP_VECTOR_BACKING_H_ -#include "third_party/blink/renderer/platform/wtf/buildflags.h" - -#if BUILDFLAG(USE_V8_OILPAN) #include "third_party/blink/renderer/platform/heap/v8_wrapper/collection_support/heap_vector_backing.h" -#else // !USE_V8_OILPAN -#include "third_party/blink/renderer/platform/heap/impl/collection_support/heap_vector_backing.h" -#endif // !USE_V8_OILPAN #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_COLLECTION_SUPPORT_HEAP_VECTOR_BACKING_H_
diff --git a/third_party/blink/renderer/platform/heap/custom_spaces.h b/third_party/blink/renderer/platform/heap/custom_spaces.h index 0ce834e3..7b98bda 100644 --- a/third_party/blink/renderer/platform/heap/custom_spaces.h +++ b/third_party/blink/renderer/platform/heap/custom_spaces.h
@@ -5,10 +5,6 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_CUSTOM_SPACES_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_CUSTOM_SPACES_H_ -#include "third_party/blink/renderer/platform/wtf/buildflags.h" - -#if BUILDFLAG(USE_V8_OILPAN) #include "third_party/blink/renderer/platform/heap/v8_wrapper/custom_spaces.h" -#endif // USE_V8_OILPAN #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_CUSTOM_SPACES_H_
diff --git a/third_party/blink/renderer/platform/heap/forward.h b/third_party/blink/renderer/platform/heap/forward.h index 18a9238..1fb813f 100644 --- a/third_party/blink/renderer/platform/heap/forward.h +++ b/third_party/blink/renderer/platform/heap/forward.h
@@ -5,10 +5,6 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_FORWARD_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_FORWARD_H_ -#include "third_party/blink/renderer/platform/wtf/buildflags.h" - -#if BUILDFLAG(USE_V8_OILPAN) - namespace cppgc { class Visitor; } @@ -19,14 +15,4 @@ } // namespace blink -#else // !USE_V8_OILPAN - -namespace blink { - -class Visitor; - -} // namespace blink - -#endif // !USE_V8_OILPAN - #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_FORWARD_H_
diff --git a/third_party/blink/renderer/platform/heap/garbage_collected.h b/third_party/blink/renderer/platform/heap/garbage_collected.h index 0226743..9b81a6c4 100644 --- a/third_party/blink/renderer/platform/heap/garbage_collected.h +++ b/third_party/blink/renderer/platform/heap/garbage_collected.h
@@ -5,12 +5,6 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_GARBAGE_COLLECTED_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_GARBAGE_COLLECTED_H_ -#include "third_party/blink/renderer/platform/wtf/buildflags.h" - -#if BUILDFLAG(USE_V8_OILPAN) #include "third_party/blink/renderer/platform/heap/v8_wrapper/garbage_collected.h" -#else // !USE_V8_OILPAN -#include "third_party/blink/renderer/platform/heap/impl/garbage_collected.h" -#endif // !USE_V8_OILPAN #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_GARBAGE_COLLECTED_H_
diff --git a/third_party/blink/renderer/platform/heap/heap.h b/third_party/blink/renderer/platform/heap/heap.h index 530b1f79..cb41e7e6 100644 --- a/third_party/blink/renderer/platform/heap/heap.h +++ b/third_party/blink/renderer/platform/heap/heap.h
@@ -5,12 +5,6 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_HEAP_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_HEAP_H_ -#include "third_party/blink/renderer/platform/wtf/buildflags.h" - -#if BUILDFLAG(USE_V8_OILPAN) #include "third_party/blink/renderer/platform/heap/v8_wrapper/heap.h" -#else // !USE_V8_OILPAN -#include "third_party/blink/renderer/platform/heap/impl/heap.h" -#endif // !USE_V8_OILPAN #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_HEAP_H_
diff --git a/third_party/blink/renderer/platform/heap/heap_allocator.h b/third_party/blink/renderer/platform/heap/heap_allocator.h index 7f72942..989490e 100644 --- a/third_party/blink/renderer/platform/heap/heap_allocator.h +++ b/third_party/blink/renderer/platform/heap/heap_allocator.h
@@ -13,6 +13,5 @@ #include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_set.h" #include "third_party/blink/renderer/platform/heap/collection_support/heap_linked_hash_set.h" #include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h" -#include "third_party/blink/renderer/platform/wtf/buildflags.h" #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_HEAP_ALLOCATOR_H_
diff --git a/third_party/blink/renderer/platform/heap/heap_allocator_impl.h b/third_party/blink/renderer/platform/heap/heap_allocator_impl.h index e05ca5d..b67be25 100644 --- a/third_party/blink/renderer/platform/heap/heap_allocator_impl.h +++ b/third_party/blink/renderer/platform/heap/heap_allocator_impl.h
@@ -5,12 +5,6 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_HEAP_ALLOCATOR_IMPL_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_HEAP_ALLOCATOR_IMPL_H_ -#include "third_party/blink/renderer/platform/wtf/buildflags.h" - -#if BUILDFLAG(USE_V8_OILPAN) #include "third_party/blink/renderer/platform/heap/v8_wrapper/heap_allocator_impl.h" -#else // !USE_V8_OILPAN -#include "third_party/blink/renderer/platform/heap/impl/heap_allocator_impl.h" -#endif // !USE_V8_OILPAN #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_HEAP_ALLOCATOR_IMPL_H_
diff --git a/third_party/blink/renderer/platform/heap/heap_stats_collector.h b/third_party/blink/renderer/platform/heap/heap_stats_collector.h index 4b7f0657..3cda388 100644 --- a/third_party/blink/renderer/platform/heap/heap_stats_collector.h +++ b/third_party/blink/renderer/platform/heap/heap_stats_collector.h
@@ -5,10 +5,4 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_HEAP_STATS_COLLECTOR_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_HEAP_STATS_COLLECTOR_H_ -#include "third_party/blink/renderer/platform/wtf/buildflags.h" - -#if !BUILDFLAG(USE_V8_OILPAN) -#include "third_party/blink/renderer/platform/heap/impl/heap_stats_collector.h" -#endif // !BUILDFLAG(USE_V8_OILPAN) - #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_HEAP_STATS_COLLECTOR_H_
diff --git a/third_party/blink/renderer/platform/heap/heap_test_utilities.h b/third_party/blink/renderer/platform/heap/heap_test_utilities.h index 3c5be39..8461f8af 100644 --- a/third_party/blink/renderer/platform/heap/heap_test_utilities.h +++ b/third_party/blink/renderer/platform/heap/heap_test_utilities.h
@@ -5,12 +5,6 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_HEAP_TEST_UTILITIES_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_HEAP_TEST_UTILITIES_H_ -#include "third_party/blink/renderer/platform/wtf/buildflags.h" - -#if BUILDFLAG(USE_V8_OILPAN) #include "third_party/blink/renderer/platform/heap/v8_wrapper/heap_test_utilities.h" -#else // !USE_V8_OILPAN -#include "third_party/blink/renderer/platform/heap/impl/heap_test_utilities.h" -#endif // !USE_V8_OILPAN #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_HEAP_TEST_UTILITIES_H_
diff --git a/third_party/blink/renderer/platform/heap/impl/atomic_entry_flag.h b/third_party/blink/renderer/platform/heap/impl/atomic_entry_flag.h deleted file mode 100644 index 46342d94..0000000 --- a/third_party/blink/renderer/platform/heap/impl/atomic_entry_flag.h +++ /dev/null
@@ -1,51 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_ATOMIC_ENTRY_FLAG_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_ATOMIC_ENTRY_FLAG_H_ - -#include <atomic> - -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" - -namespace blink { - -// A flag which provides a fast check whether a scope may be entered on the -// current thread, without needing to access thread-local storage or mutex. -// -// Can have false positives (i.e., spuriously report that it might be entered), -// so it is expected that this will be used in tandem with a precise check that -// the scope is in fact entered on that thread. -// -// Example: -// g_frobnicating_flag.MightBeEntered() && -// ThreadLocalFrobnicator().IsFrobnicating() -// -// Relaxed atomic operations are sufficient, since: -// - all accesses remain atomic -// - each thread must observe its own operations in order -// - no thread ever exits the flag more times than it enters (if used correctly) -// And so if a thread observes zero, it must be because it has observed an equal -// number of exits as entries. -class AtomicEntryFlag { - DISALLOW_NEW(); - - public: - inline void Enter() { entries_.fetch_add(1, std::memory_order_relaxed); } - inline void Exit() { entries_.fetch_sub(1, std::memory_order_relaxed); } - - // Returns false only if the current thread is not between a call to Enter and - // a call to Exit. Returns true if this thread or another thread may currently - // be in the scope guarded by this flag. - inline bool MightBeEntered() const { - return entries_.load(std::memory_order_relaxed) != 0; - } - - private: - std::atomic_int entries_{0}; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_ATOMIC_ENTRY_FLAG_H_
diff --git a/third_party/blink/renderer/platform/heap/impl/blink_gc.cc b/third_party/blink/renderer/platform/heap/impl/blink_gc.cc deleted file mode 100644 index 58c86eb..0000000 --- a/third_party/blink/renderer/platform/heap/impl/blink_gc.cc +++ /dev/null
@@ -1,71 +0,0 @@ -// Copyright 2019 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/heap/blink_gc.h" - -namespace blink { - -const char* BlinkGC::ToString(BlinkGC::GCReason reason) { - switch (reason) { - case BlinkGC::GCReason::kForcedGCForTesting: - return "ForcedGCForTesting"; - case BlinkGC::GCReason::kThreadTerminationGC: - return "ThreadTerminationGC"; - case BlinkGC::GCReason::kUnifiedHeapGC: - return "UnifiedHeapGC"; - case BlinkGC::GCReason::kUnifiedHeapForMemoryReductionGC: - return "UnifiedHeapForMemoryReductionGC"; - case BlinkGC::GCReason::kUnifiedHeapForcedForTestingGC: - return "UnifiedHeapForcedForTestingGC"; - } - IMMEDIATE_CRASH(); -} - -const char* BlinkGC::ToString(BlinkGC::MarkingType type) { - switch (type) { - case BlinkGC::MarkingType::kAtomicMarking: - return "AtomicMarking"; - case BlinkGC::MarkingType::kIncrementalAndConcurrentMarking: - return "IncrementalAndConcurrentMarking"; - } - IMMEDIATE_CRASH(); -} - -const char* BlinkGC::ToString(BlinkGC::SweepingType type) { - switch (type) { - case BlinkGC::SweepingType::kConcurrentAndLazySweeping: - return "ConcurrentAndLazySweeping"; - case BlinkGC::SweepingType::kEagerSweeping: - return "EagerSweeping"; - } - IMMEDIATE_CRASH(); -} - -const char* BlinkGC::ToString(BlinkGC::StackState stack_state) { - switch (stack_state) { - case BlinkGC::kNoHeapPointersOnStack: - return "NoHeapPointersOnStack"; - case BlinkGC::kHeapPointersOnStack: - return "HeapPointersOnStack"; - } - IMMEDIATE_CRASH(); -} - -const char* BlinkGC::ToString(BlinkGC::ArenaIndices arena_index) { -#define ArenaCase(name) \ - case k##name##ArenaIndex: \ - return "" #name "Arena"; - - switch (arena_index) { - FOR_EACH_ARENA(ArenaCase) - - case BlinkGC::ArenaIndices::kNumberOfArenas: - IMMEDIATE_CRASH(); - } - IMMEDIATE_CRASH(); - -#undef ArenaCase -} - -} // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/impl/blink_gc.h b/third_party/blink/renderer/platform/heap/impl/blink_gc.h deleted file mode 100644 index bb35f79..0000000 --- a/third_party/blink/renderer/platform/heap/impl/blink_gc.h +++ /dev/null
@@ -1,127 +0,0 @@ -// Copyright 2015 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. - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_BLINK_GC_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_BLINK_GC_H_ - -// BlinkGC.h is a file that defines common things used by Blink GC. - -#include "third_party/blink/renderer/platform/platform_export.h" -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" - -#define PRINT_HEAP_STATS 0 // Enable this macro to print heap stats to stderr. - -namespace blink { - -class LivenessBroker; -class MarkingVisitor; -class Visitor; - -using Address = uint8_t*; -using ConstAddress = const uint8_t*; - -using VisitorCallback = void (*)(Visitor*, const void*); -using MarkingVisitorCallback = void (*)(MarkingVisitor*, const void*); -using TraceCallback = VisitorCallback; -using WeakCallback = void (*)(const LivenessBroker&, const void*); -using EphemeronCallback = VisitorCallback; - -// Simple alias to avoid heap compaction type signatures turning into -// a sea of generic |void*|s. -using MovableReference = const void*; - -// List of all arenas. Includes typed arenas as well. -#define FOR_EACH_ARENA(H) \ - H(NormalPage1) \ - H(NormalPage2) \ - H(NormalPage3) \ - H(NormalPage4) \ - H(Vector) \ - H(HashTable) \ - H(Node) \ - H(CSSValue) \ - H(LayoutObject) \ - H(LargeObject) - -class PLATFORM_EXPORT WorklistTaskId { - public: - static constexpr int MutatorThread = 0; - static constexpr int ConcurrentThreadBase = 1; -}; - -class PLATFORM_EXPORT BlinkGC final { - STATIC_ONLY(BlinkGC); - - public: - // CollectionType represents generational collection. kMinor collects objects - // in the young generation (i.e. allocated since the previous collection - // cycle, since we use sticky bits), kMajor collects the entire heap. - enum class CollectionType { kMinor, kMajor }; - - // When garbage collecting we need to know whether or not there - // can be pointers to Blink GC managed objects on the stack for - // each thread. When threads reach a safe point they record - // whether or not they have pointers on the stack. - enum StackState { kNoHeapPointersOnStack, kHeapPointersOnStack }; - - enum MarkingType { - // The marking completes synchronously. - kAtomicMarking, - // The marking task is split and executed in chunks (either on the mutator - // thread or concurrently). - kIncrementalAndConcurrentMarking - }; - - enum SweepingType { - // The sweeping task is split into chunks and scheduled lazily and - // concurrently. - kConcurrentAndLazySweeping, - // The sweeping task executes synchronously right after marking. - kEagerSweeping, - }; - - // Commented out reasons have been used in the past but are not used any - // longer. We keep them here as the corresponding UMA histograms cannot be - // changed. - enum class GCReason { - // kIdleGC = 0 - // kPreciseGC = 1 - // kConservativeGC = 2 - kForcedGCForTesting = 3, - // kMemoryPressureGC = 4 - // kPageNavigationGC = 5 - kThreadTerminationGC = 6, - // kTesting = 7 - // kIncrementalIdleGC = 8 - // kIncrementalV8FollowupGC = 9 - kUnifiedHeapGC = 10, - kUnifiedHeapForMemoryReductionGC = 11, - kUnifiedHeapForcedForTestingGC = 12, - // Used by UMA_HISTOGRAM_ENUMERATION macro. - kMaxValue = kUnifiedHeapForcedForTestingGC, - }; - -#define DeclareArenaIndex(name) k##name##ArenaIndex, - enum ArenaIndices { - FOR_EACH_ARENA(DeclareArenaIndex) - // Values used for iteration of heap segments. - kNumberOfArenas, - }; -#undef DeclareArenaIndex - - enum V8GCType { - kV8MinorGC, - kV8MajorGC, - }; - - static const char* ToString(GCReason); - static const char* ToString(MarkingType); - static const char* ToString(StackState); - static const char* ToString(SweepingType); - static const char* ToString(ArenaIndices); -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_BLINK_GC_H_
diff --git a/third_party/blink/renderer/platform/heap/impl/blink_gc_memory_dump_provider.cc b/third_party/blink/renderer/platform/heap/impl/blink_gc_memory_dump_provider.cc deleted file mode 100644 index cb8ce72..0000000 --- a/third_party/blink/renderer/platform/heap/impl/blink_gc_memory_dump_provider.cc +++ /dev/null
@@ -1,144 +0,0 @@ -// Copyright 2015 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/heap/blink_gc_memory_dump_provider.h" - -#include "base/strings/string_number_conversions.h" -#include "base/strings/stringprintf.h" -#include "base/trace_event/memory_allocator_dump.h" -#include "base/trace_event/memory_dump_manager.h" -#include "base/trace_event/process_memory_dump.h" -#include "third_party/blink/public/platform/platform.h" -#include "third_party/blink/renderer/platform/heap/handle.h" -#include "third_party/blink/renderer/platform/heap/impl/thread_state_statistics.h" -#include "third_party/blink/renderer/platform/heap/thread_state.h" -#include "third_party/blink/renderer/platform/instrumentation/tracing/web_memory_allocator_dump.h" -#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h" -#include "third_party/blink/renderer/platform/wtf/threading.h" - -namespace blink { -namespace { - -constexpr const char* HeapTypeString( - BlinkGCMemoryDumpProvider::HeapType heap_type) { - switch (heap_type) { - case BlinkGCMemoryDumpProvider::HeapType::kBlinkMainThread: - return "main"; - case BlinkGCMemoryDumpProvider::HeapType::kBlinkWorkerThread: - return "workers"; - } -} - -} // namespace - -BlinkGCMemoryDumpProvider::BlinkGCMemoryDumpProvider( - ThreadState* thread_state, - scoped_refptr<base::SingleThreadTaskRunner> task_runner, - BlinkGCMemoryDumpProvider::HeapType heap_type) - : thread_state_(thread_state), - heap_type_(heap_type), - dump_base_name_( - "blink_gc/" + std::string(HeapTypeString(heap_type_)) + "/heap" + - (heap_type_ == HeapType::kBlinkWorkerThread - ? "/" + base::StringPrintf( - "worker_0x%" PRIXPTR, - reinterpret_cast<uintptr_t>(thread_state_)) - : "")) { - base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( - this, "BlinkGC", task_runner); -} - -BlinkGCMemoryDumpProvider::~BlinkGCMemoryDumpProvider() { - base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider( - this); -} - -bool BlinkGCMemoryDumpProvider::OnMemoryDump( - const base::trace_event::MemoryDumpArgs& args, - base::trace_event::ProcessMemoryDump* process_memory_dump) { - ThreadState::Statistics::DetailLevel detail_level = - args.level_of_detail == - base::trace_event::MemoryDumpLevelOfDetail::DETAILED - ? ThreadState::Statistics::kDetailed - : ThreadState::Statistics::kBrief; - - ThreadState::Statistics stats = - ThreadState::StatisticsCollector(thread_state_) - .CollectStatistics(detail_level); - - auto* heap_dump = process_memory_dump->CreateAllocatorDump(dump_base_name_); - heap_dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize, - base::trace_event::MemoryAllocatorDump::kUnitsBytes, - stats.committed_size_bytes); - heap_dump->AddScalar("allocated_objects_size", - base::trace_event::MemoryAllocatorDump::kUnitsBytes, - stats.used_size_bytes); - - if (detail_level == ThreadState::Statistics::kBrief) { - return true; - } - - // Detailed statistics. - for (const ThreadState::Statistics::ArenaStatistics& arena_stats : - stats.arena_stats) { - std::string arena_dump_name = dump_base_name_ + "/" + arena_stats.name; - auto* arena_dump = - process_memory_dump->CreateAllocatorDump(arena_dump_name); - arena_dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize, - base::trace_event::MemoryAllocatorDump::kUnitsBytes, - arena_stats.committed_size_bytes); - arena_dump->AddScalar("allocated_objects_size", - base::trace_event::MemoryAllocatorDump::kUnitsBytes, - arena_stats.used_size_bytes); - - size_t page_count = 0; - for (const ThreadState::Statistics::PageStatistics& page_stats : - arena_stats.page_stats) { - auto* page_dump = process_memory_dump->CreateAllocatorDump( - arena_dump_name + "/pages/page_" + - base::NumberToString(page_count++)); - page_dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize, - base::trace_event::MemoryAllocatorDump::kUnitsBytes, - page_stats.committed_size_bytes); - page_dump->AddScalar("allocated_objects_size", - base::trace_event::MemoryAllocatorDump::kUnitsBytes, - page_stats.used_size_bytes); - } - - const ThreadState::Statistics::FreeListStatistics& free_list_stats = - arena_stats.free_list_stats; - for (wtf_size_t i = 0; i < free_list_stats.bucket_size.size(); ++i) { - constexpr size_t kDigits = 8; - std::string original_bucket_size = - base::NumberToString(free_list_stats.bucket_size[i]); - std::string padded_bucket_size = - std::string(kDigits - original_bucket_size.length(), '0') + - original_bucket_size; - auto* free_list_bucket_dump = process_memory_dump->CreateAllocatorDump( - arena_dump_name + "/freelist/bucket_" + padded_bucket_size); - free_list_bucket_dump->AddScalar( - "free_size", base::trace_event::MemoryAllocatorDump::kUnitsBytes, - free_list_stats.free_size[i]); - } - - const ThreadState::Statistics::ObjectStatistics& object_stats = - arena_stats.object_stats; - for (wtf_size_t i = 1; i < object_stats.num_types; i++) { - if (object_stats.type_name[i].empty()) - continue; - - auto* class_dump = process_memory_dump->CreateAllocatorDump( - arena_dump_name + "/classes/" + object_stats.type_name[i]); - class_dump->AddScalar( - "object_count", base::trace_event::MemoryAllocatorDump::kUnitsObjects, - object_stats.type_count[i]); - class_dump->AddScalar("object_size", - base::trace_event::MemoryAllocatorDump::kUnitsBytes, - object_stats.type_bytes[i]); - } - } - return true; -} - -} // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/impl/blink_gc_memory_dump_provider.h b/third_party/blink/renderer/platform/heap/impl/blink_gc_memory_dump_provider.h deleted file mode 100644 index e730f8d..0000000 --- a/third_party/blink/renderer/platform/heap/impl/blink_gc_memory_dump_provider.h +++ /dev/null
@@ -1,47 +0,0 @@ -// Copyright 2015 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. - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_BLINK_GC_MEMORY_DUMP_PROVIDER_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_BLINK_GC_MEMORY_DUMP_PROVIDER_H_ - -#include "base/trace_event/memory_dump_provider.h" -#include "third_party/blink/renderer/platform/heap/blink_gc.h" -#include "third_party/blink/renderer/platform/platform_export.h" -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" -#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" - -namespace base { -class SingleThreadTaskRunner; -} // namespace base - -namespace blink { - -class ThreadState; - -class PLATFORM_EXPORT BlinkGCMemoryDumpProvider final - : public base::trace_event::MemoryDumpProvider { - USING_FAST_MALLOC(BlinkGCMemoryDumpProvider); - - public: - enum class HeapType { kBlinkMainThread, kBlinkWorkerThread }; - - ~BlinkGCMemoryDumpProvider() final; - BlinkGCMemoryDumpProvider( - ThreadState* thread_state, - scoped_refptr<base::SingleThreadTaskRunner> task_runner, - HeapType heap_type); - - // MemoryDumpProvider implementation. - bool OnMemoryDump(const base::trace_event::MemoryDumpArgs&, - base::trace_event::ProcessMemoryDump*) final; - - private: - ThreadState* const thread_state_; - const HeapType heap_type_; - const std::string dump_base_name_; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_BLINK_GC_MEMORY_DUMP_PROVIDER_H_
diff --git a/third_party/blink/renderer/platform/heap/impl/collection_support/heap_hash_table_backing.h b/third_party/blink/renderer/platform/heap/impl/collection_support/heap_hash_table_backing.h deleted file mode 100644 index 1e81ebc..0000000 --- a/third_party/blink/renderer/platform/heap/impl/collection_support/heap_hash_table_backing.h +++ /dev/null
@@ -1,283 +0,0 @@ -// Copyright 2020 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. - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_COLLECTION_SUPPORT_HEAP_HASH_TABLE_BACKING_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_COLLECTION_SUPPORT_HEAP_HASH_TABLE_BACKING_H_ - -#include "third_party/blink/renderer/platform/heap/impl/heap_page.h" -#include "third_party/blink/renderer/platform/heap/impl/threading_traits.h" -#include "third_party/blink/renderer/platform/heap/impl/trace_traits.h" -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" -#include "third_party/blink/renderer/platform/wtf/conditional_destructor.h" - -namespace blink { - -template <typename Table> -class HeapHashTableBacking final - : public GarbageCollected<HeapHashTableBacking<Table>>, - public WTF::ConditionalDestructor< - HeapHashTableBacking<Table>, - std::is_trivially_destructible<typename Table::ValueType>::value> { - public: - template <typename Backing> - static void* AllocateObject(size_t); - - // Conditionally invoked via destructor. - void Finalize(); -}; - -template <typename Table> -struct ThreadingTrait<HeapHashTableBacking<Table>> { - STATIC_ONLY(ThreadingTrait); - using Key = typename Table::KeyType; - using Value = typename Table::ValueType; - static const ThreadAffinity kAffinity = - (ThreadingTrait<Key>::kAffinity == kMainThreadOnly) && - (ThreadingTrait<Value>::kAffinity == kMainThreadOnly) - ? kMainThreadOnly - : kAnyThread; -}; - -// static -template <typename Table> -template <typename Backing> -void* HeapHashTableBacking<Table>::AllocateObject(size_t size) { - ThreadState* state = - ThreadStateFor<ThreadingTrait<Backing>::kAffinity>::GetState(); - DCHECK(state->IsAllocationAllowed()); - return state->Heap().AllocateOnArenaIndex( - state, size, BlinkGC::kHashTableArenaIndex, GCInfoTrait<Backing>::Index(), - WTF_HEAP_PROFILER_TYPE_NAME(Backing)); -} - -template <typename Table> -void HeapHashTableBacking<Table>::Finalize() { - using Value = typename Table::ValueType; - static_assert( - !std::is_trivially_destructible<Value>::value, - "Finalization of trivially destructible classes should not happen."); - HeapObjectHeader* header = HeapObjectHeader::FromPayload(this); - // Use the payload size as recorded by the heap to determine how many - // elements to finalize. - size_t length = header->PayloadSize() / sizeof(Value); - Value* table = reinterpret_cast<Value*>(this); - for (unsigned i = 0; i < length; ++i) { - if (!Table::IsEmptyOrDeletedBucket(table[i])) - table[i].~Value(); - } -} - -template <typename Table> -struct MakeGarbageCollectedTrait<HeapHashTableBacking<Table>> { - static HeapHashTableBacking<Table>* Call(size_t num_elements) { - static_assert(!std::is_polymorphic<HeapHashTableBacking<Table>>::value, - "HeapHashTableBacking must not be polymorphic as it is " - "converted to a raw array of buckets for certain operation"); - CHECK_GT(num_elements, 0u); - void* memory = HeapHashTableBacking<Table>::template AllocateObject< - HeapHashTableBacking<Table>>(num_elements * - sizeof(typename Table::ValueType)); - HeapObjectHeader* header = HeapObjectHeader::FromPayload(memory); - // Placement new as regular operator new() is deleted. - HeapHashTableBacking<Table>* object = - ::new (memory) HeapHashTableBacking<Table>(); - header->MarkFullyConstructed<HeapObjectHeader::AccessMode::kAtomic>(); - return object; - } -}; - -// The trace trait for the heap hashtable backing is used when we find a -// direct pointer to the backing from the conservative stack scanner. This -// normally indicates that there is an ongoing iteration over the table, and so -// we disable weak processing of table entries. When the backing is found -// through the owning hash table we mark differently, in order to do weak -// processing. -template <typename Table> -struct TraceTrait<HeapHashTableBacking<Table>> { - STATIC_ONLY(TraceTrait); - using Backing = HeapHashTableBacking<Table>; - using ValueType = typename Table::ValueTraits::TraitType; - using Traits = typename Table::ValueTraits; - - public: - static TraceDescriptor GetTraceDescriptor(const void* self) { - return {self, Trace<WTF::kNoWeakHandling>}; - } - - static TraceDescriptor GetWeakTraceDescriptor(const void* self) { - return GetWeakTraceDescriptorImpl<ValueType>::GetWeakTraceDescriptor(self); - } - - template <WTF::WeakHandlingFlag WeakHandling = WTF::kNoWeakHandling> - static void Trace(Visitor* visitor, const void* self) { - if (!Traits::kCanTraceConcurrently && self) { - if (visitor->DeferredTraceIfConcurrent({self, &Trace<WeakHandling>}, - GetBackingStoreSize(self))) - return; - } - - static_assert(WTF::IsTraceableInCollectionTrait<Traits>::value || - WTF::IsWeak<ValueType>::value, - "T should not be traced"); - WTF::TraceInCollectionTrait<WeakHandling, Backing, void>::Trace(visitor, - self); - } - - private: - static size_t GetBackingStoreSize(const void* backing_store) { - const HeapObjectHeader* header = - HeapObjectHeader::FromPayload(backing_store); - return header->IsLargeObject<HeapObjectHeader::AccessMode::kAtomic>() - ? static_cast<LargeObjectPage*>(PageFromObject(header)) - ->ObjectSize() - : header->size<HeapObjectHeader::AccessMode::kAtomic>(); - } - - template <typename ValueType> - struct GetWeakTraceDescriptorImpl { - static TraceDescriptor GetWeakTraceDescriptor(const void* backing) { - return {backing, nullptr}; - } - }; - - template <typename K, typename V> - struct GetWeakTraceDescriptorImpl<WTF::KeyValuePair<K, V>> { - static TraceDescriptor GetWeakTraceDescriptor(const void* backing) { - return GetWeakTraceDescriptorKVPImpl<K, V>::GetWeakTraceDescriptor( - backing); - } - - template <typename KeyType, - typename ValueType, - bool ephemeron_semantics = (WTF::IsWeak<KeyType>::value && - !WTF::IsWeak<ValueType>::value && - WTF::IsTraceable<ValueType>::value) || - (WTF::IsWeak<ValueType>::value && - !WTF::IsWeak<KeyType>::value && - WTF::IsTraceable<KeyType>::value)> - struct GetWeakTraceDescriptorKVPImpl { - static TraceDescriptor GetWeakTraceDescriptor(const void* backing) { - return {backing, nullptr}; - } - }; - - template <typename KeyType, typename ValueType> - struct GetWeakTraceDescriptorKVPImpl<KeyType, ValueType, true> { - static TraceDescriptor GetWeakTraceDescriptor(const void* backing) { - return {backing, Trace<WTF::kWeakHandling>}; - } - }; - }; -}; - -} // namespace blink - -namespace WTF { - -namespace internal { - -// ConcurrentBucket is a wrapper for HashTable buckets for concurrent marking. -// It is used to provide a snapshot view of the bucket key and guarantee -// that the same key is used for checking empty/deleted buckets and tracing. -template <typename T> -class ConcurrentBucket { - using KeyExtractionCallback = void (*)(const T&, void*); - - public: - using BucketType = T; - - ConcurrentBucket(const T& t, KeyExtractionCallback extract_key) { - extract_key(t, &buf_); - } - - // for HashTable that don't use KeyValuePair (i.e. *HashSets), the key - // and the value are the same. - const T* key() const { return reinterpret_cast<const T*>(&buf_); } - const T* value() const { return key(); } - const T* bucket() const { return key(); } - - private: - // Alignment is needed for atomic accesses to |buf_| and to assure |buf_| - // can be accessed the same as objects of type T - static constexpr size_t boundary = std::max(alignof(T), sizeof(size_t)); - alignas(boundary) char buf_[sizeof(T)]; -}; - -template <typename Key, typename Value> -class ConcurrentBucket<KeyValuePair<Key, Value>> { - using KeyExtractionCallback = void (*)(const KeyValuePair<Key, Value>&, - void*); - - public: - using BucketType = ConcurrentBucket; - - ConcurrentBucket(const KeyValuePair<Key, Value>& pair, - KeyExtractionCallback extract_key) - : value_(&pair.value) { - extract_key(pair, &buf_); - } - - const Key* key() const { return reinterpret_cast<const Key*>(&buf_); } - const Value* value() const { return value_; } - const ConcurrentBucket* bucket() const { return this; } - - private: - // Alignment is needed for atomic accesses to |buf_| and to assure |buf_| - // can be accessed the same as objects of type Key - static constexpr size_t boundary = std::max(alignof(Key), sizeof(size_t)); - alignas(boundary) char buf_[sizeof(Key)]; - const Value* value_; -}; - -} // namespace internal - -// This trace method is for tracing a HashTableBacking either through regular -// tracing (via the relevant TraceTraits) or when finding a HashTableBacking -// through conservative stack scanning (which will treat all references in the -// backing strongly). -template <WTF::WeakHandlingFlag WeakHandling, typename Table> -struct TraceHashTableBackingInCollectionTrait { - using Value = typename Table::ValueType; - using Traits = typename Table::ValueTraits; - using Extractor = typename Table::ExtractorType; - - static void Trace(blink::Visitor* visitor, const void* self) { - static_assert(IsTraceableInCollectionTrait<Traits>::value || - WTF::IsWeak<Value>::value, - "Table should not be traced"); - const Value* array = reinterpret_cast<const Value*>(self); - blink::HeapObjectHeader* header = - blink::HeapObjectHeader::FromPayload(self); - // Use the payload size as recorded by the heap to determine how many - // elements to trace. - size_t length = header->PayloadSize() / sizeof(Value); - const bool is_concurrent = visitor->IsConcurrent(); - for (size_t i = 0; i < length; ++i) { - // If tracing concurrently, use a concurrent-safe version of - // IsEmptyOrDeletedBucket (check performed on a local copy instead - // of directly on the bucket). - if (is_concurrent) { - internal::ConcurrentBucket<Value> concurrent_bucket( - array[i], Extractor::ExtractSafe); - if (!HashTableHelper<Value, Extractor, typename Table::KeyTraitsType>:: - IsEmptyOrDeletedBucketForKey(*concurrent_bucket.key())) { - blink::TraceCollectionIfEnabled< - WeakHandling, - typename internal::ConcurrentBucket<Value>::BucketType, - Traits>::Trace(visitor, concurrent_bucket.bucket()); - } - } else { - if (!HashTableHelper<Value, Extractor, typename Table::KeyTraitsType>:: - IsEmptyOrDeletedBucket(array[i])) { - blink::TraceCollectionIfEnabled<WeakHandling, Value, Traits>::Trace( - visitor, &array[i]); - } - } - } - } -}; - -} // namespace WTF - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_COLLECTION_SUPPORT_HEAP_HASH_TABLE_BACKING_H_
diff --git a/third_party/blink/renderer/platform/heap/impl/collection_support/heap_vector_backing.h b/third_party/blink/renderer/platform/heap/impl/collection_support/heap_vector_backing.h deleted file mode 100644 index c7b75ba..0000000 --- a/third_party/blink/renderer/platform/heap/impl/collection_support/heap_vector_backing.h +++ /dev/null
@@ -1,213 +0,0 @@ -// Copyright 2020 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. - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_COLLECTION_SUPPORT_HEAP_VECTOR_BACKING_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_COLLECTION_SUPPORT_HEAP_VECTOR_BACKING_H_ - -#include "base/check_op.h" -#include "third_party/blink/renderer/platform/heap/heap.h" -#include "third_party/blink/renderer/platform/heap/impl/finalizer_traits.h" -#include "third_party/blink/renderer/platform/heap/impl/gc_info.h" -#include "third_party/blink/renderer/platform/heap/impl/threading_traits.h" -#include "third_party/blink/renderer/platform/heap/thread_state.h" -#include "third_party/blink/renderer/platform/heap/trace_traits.h" -#include "third_party/blink/renderer/platform/wtf/conditional_destructor.h" -#include "third_party/blink/renderer/platform/wtf/vector.h" - -namespace blink { - -template <typename T, typename Traits = WTF::VectorTraits<T>> -class HeapVectorBacking final - : public GarbageCollected<HeapVectorBacking<T, Traits>>, - public WTF::ConditionalDestructor<HeapVectorBacking<T, Traits>, - !Traits::kNeedsDestruction> { - public: - template <typename Backing> - static void* AllocateObject(size_t); - - // Conditionally invoked via destructor. - void Finalize(); -}; - -// static -template <typename T, typename Traits> -template <typename Backing> -void* HeapVectorBacking<T, Traits>::AllocateObject(size_t size) { - ThreadState* state = ThreadStateFor<ThreadingTrait<T>::kAffinity>::GetState(); - DCHECK(state->IsAllocationAllowed()); - return state->Heap().AllocateOnArenaIndex( - state, size, BlinkGC::kVectorArenaIndex, GCInfoTrait<Backing>::Index(), - WTF_HEAP_PROFILER_TYPE_NAME(Backing)); -} - -template <typename T, typename Traits> -void HeapVectorBacking<T, Traits>::Finalize() { - static_assert(Traits::kNeedsDestruction, - "Only vector buffers with items requiring destruction should " - "be finalized"); - static_assert( - Traits::kCanClearUnusedSlotsWithMemset || std::is_polymorphic<T>::value, - "HeapVectorBacking doesn't support objects that cannot be cleared as " - "unused with memset or don't have a vtable"); - - static_assert( - !std::is_trivially_destructible<T>::value, - "Finalization of trivially destructible classes should not happen."); - HeapObjectHeader* header = HeapObjectHeader::FromPayload(this); - // Use the payload size as recorded by the heap to determine how many - // elements to finalize. - size_t length = header->PayloadSize() / sizeof(T); - Address payload = header->Payload(); -#ifdef ANNOTATE_CONTIGUOUS_CONTAINER - ANNOTATE_CHANGE_SIZE(payload, length * sizeof(T), 0, length * sizeof(T)); -#endif - // As commented above, HeapVectorBacking calls finalizers for unused slots - // (which are already zeroed out). - if (std::is_polymorphic<T>::value) { - for (unsigned i = 0; i < length; ++i) { - Address element = payload + i * sizeof(T); - if (blink::VTableInitialized(element)) - reinterpret_cast<T*>(element)->~T(); - } - } else { - T* buffer = reinterpret_cast<T*>(payload); - for (unsigned i = 0; i < length; ++i) - buffer[i].~T(); - } -} - -template <typename T> -struct MakeGarbageCollectedTrait<HeapVectorBacking<T>> { - static HeapVectorBacking<T>* Call(size_t num_elements) { - static_assert(!std::is_polymorphic<HeapVectorBacking<T>>::value, - "HeapVectorBacking must not be polymorphic as it is " - "converted to a raw array of buckets for certain operation"); - CHECK_GT(num_elements, 0u); - void* memory = - HeapVectorBacking<T>::template AllocateObject<HeapVectorBacking<T>>( - num_elements * sizeof(T)); - HeapObjectHeader* header = HeapObjectHeader::FromPayload(memory); - // Placement new as regular operator new() is deleted. - HeapVectorBacking<T>* object = ::new (memory) HeapVectorBacking<T>(); - header->MarkFullyConstructed<HeapObjectHeader::AccessMode::kAtomic>(); - return object; - } -}; - -template <typename T, typename Traits> -struct ThreadingTrait<HeapVectorBacking<T, Traits>> { - STATIC_ONLY(ThreadingTrait); - static const ThreadAffinity kAffinity = ThreadingTrait<T>::Affinity; -}; - -template <typename T, typename Traits> -struct TraceTrait<HeapVectorBacking<T, Traits>> { - STATIC_ONLY(TraceTrait); - using Backing = HeapVectorBacking<T, Traits>; - - public: - static TraceDescriptor GetTraceDescriptor(const void* self) { - return {self, TraceTrait<Backing>::Trace}; - } - - static void Trace(Visitor* visitor, const void* self) { - if (!Traits::kCanTraceConcurrently && self) { - if (visitor->DeferredTraceIfConcurrent({self, &Trace}, - GetBackingStoreSize(self))) - return; - } - - static_assert(!WTF::IsWeak<T>::value, - "Weakness is not supported in HeapVector and HeapDeque"); - if (WTF::IsTraceableInCollectionTrait<Traits>::value) { - WTF::TraceInCollectionTrait<WTF::kNoWeakHandling, - HeapVectorBacking<T, Traits>, - void>::Trace(visitor, self); - } - } - - private: - static size_t GetBackingStoreSize(const void* backing_store) { - const HeapObjectHeader* header = - HeapObjectHeader::FromPayload(backing_store); - return header->IsLargeObject<HeapObjectHeader::AccessMode::kAtomic>() - ? static_cast<LargeObjectPage*>(PageFromObject(header)) - ->ObjectSize() - : header->size<HeapObjectHeader::AccessMode::kAtomic>(); - } -}; - -} // namespace blink - -namespace WTF { - -// This trace method is used for all HeapVectorBacking objects. On-stack objects -// are found and dispatched using conservative stack scanning. HeapVector (i.e. -// Vector) dispatches all regular on-heap backings to this method. -template <typename T, typename Traits> -struct TraceInCollectionTrait<kNoWeakHandling, - blink::HeapVectorBacking<T, Traits>, - void> { - static void Trace(blink::Visitor* visitor, const void* self) { - // HeapVectorBacking does not know the exact size of the vector - // and just knows the capacity of the vector. Due to the constraint, - // HeapVectorBacking can support only the following objects: - // - // - An object that has a vtable. In this case, HeapVectorBacking - // traces only slots that are not zeroed out. This is because if - // the object has a vtable, the zeroed slot means that it is - // an unused slot (Remember that the unused slots are guaranteed - // to be zeroed out by VectorUnusedSlotClearer). - // - // - An object that can be initialized with memset. In this case, - // HeapVectorBacking traces all slots including unused slots. - // This is fine because the fact that the object can be initialized - // with memset indicates that it is safe to treat the zerod slot - // as a valid object. - static_assert(!IsTraceableInCollectionTrait<Traits>::value || - Traits::kCanClearUnusedSlotsWithMemset || - std::is_polymorphic<T>::value, - "HeapVectorBacking doesn't support objects that cannot be " - "cleared as unused with memset."); - - // This trace method is instantiated for vectors where - // IsTraceableInCollectionTrait<Traits>::value is false, but the trace - // method should not be called. Thus we cannot static-assert - // IsTraceableInCollectionTrait<Traits>::value but should runtime-assert it. - DCHECK(IsTraceableInCollectionTrait<Traits>::value); - - const T* array = reinterpret_cast<const T*>(self); - blink::HeapObjectHeader* header = - blink::HeapObjectHeader::FromPayload(self); - // Use the payload size as recorded by the heap to determine how many - // elements to trace. - size_t length = header->PayloadSize() / sizeof(T); -#ifdef ANNOTATE_CONTIGUOUS_CONTAINER - // As commented above, HeapVectorBacking can trace unused slots - // (which are already zeroed out). - ANNOTATE_CHANGE_SIZE(array, length, 0, length); -#endif - if (std::is_polymorphic<T>::value) { - const char* pointer = reinterpret_cast<const char*>(array); - for (unsigned i = 0; i < length; ++i) { - const char* element = pointer + i * sizeof(T); - if (blink::VTableInitialized(element)) { - blink::TraceIfNeeded< - T, IsTraceableInCollectionTrait<Traits>::value>::Trace(visitor, - array[i]); - } - } - } else { - for (size_t i = 0; i < length; ++i) { - blink::TraceIfNeeded< - T, IsTraceableInCollectionTrait<Traits>::value>::Trace(visitor, - array[i]); - } - } - } -}; - -} // namespace WTF - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_COLLECTION_SUPPORT_HEAP_VECTOR_BACKING_H_
diff --git a/third_party/blink/renderer/platform/heap/impl/finalizer_traits.h b/third_party/blink/renderer/platform/heap/impl/finalizer_traits.h deleted file mode 100644 index 2f0e0ee..0000000 --- a/third_party/blink/renderer/platform/heap/impl/finalizer_traits.h +++ /dev/null
@@ -1,95 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_FINALIZER_TRAITS_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_FINALIZER_TRAITS_H_ - -#include <type_traits> - -#include "base/template_util.h" -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" - -namespace blink { -namespace internal { - -using FinalizationCallback = void (*)(void*); - -template <typename T, typename = void> -struct HasFinalizeGarbageCollectedObject : std::false_type {}; - -template <typename T> -struct HasFinalizeGarbageCollectedObject< - T, - base::void_t<decltype(std::declval<T>().FinalizeGarbageCollectedObject())>> - : std::true_type {}; - -// The FinalizerTraitImpl specifies how to finalize objects. -template <typename T, bool isFinalized> -struct FinalizerTraitImpl; - -template <typename T> -struct FinalizerTraitImpl<T, true> { - private: - STATIC_ONLY(FinalizerTraitImpl); - struct Custom { - static void Call(void* obj) { - static_cast<T*>(obj)->FinalizeGarbageCollectedObject(); - } - }; - struct Destructor { - static void Call(void* obj) { -// The garbage collector differs from regular C++ here as it remembers whether -// an object's base class has a virtual destructor. In case there is no virtual -// destructor present, the object is always finalized through its leaf type. In -// other words: there is no finalization through a base pointer. -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor" - static_cast<T*>(obj)->~T(); -#pragma GCC diagnostic pop - } - }; - using FinalizeImpl = - std::conditional_t<HasFinalizeGarbageCollectedObject<T>::value, - Custom, - Destructor>; - - public: - static void Finalize(void* obj) { - static_assert(sizeof(T), "T must be fully defined"); - FinalizeImpl::Call(obj); - } -}; - -template <typename T> -struct FinalizerTraitImpl<T, false> { - STATIC_ONLY(FinalizerTraitImpl); - static void Finalize(void* obj) { - static_assert(sizeof(T), "T must be fully defined"); - } -}; - -// The FinalizerTrait is used to determine if a type requires finalization and -// what finalization means. -template <typename T> -struct FinalizerTrait { - STATIC_ONLY(FinalizerTrait); - - private: - static constexpr bool kNonTrivialFinalizer = - internal::HasFinalizeGarbageCollectedObject<T>::value || - !std::is_trivially_destructible<typename std::remove_cv<T>::type>::value; - - static void Finalize(void* obj) { - internal::FinalizerTraitImpl<T, kNonTrivialFinalizer>::Finalize(obj); - } - - public: - static constexpr FinalizationCallback kCallback = - kNonTrivialFinalizer ? Finalize : nullptr; -}; - -} // namespace internal -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_FINALIZER_TRAITS_H_
diff --git a/third_party/blink/renderer/platform/heap/impl/garbage_collected.h b/third_party/blink/renderer/platform/heap/impl/garbage_collected.h deleted file mode 100644 index ccdeb37c..0000000 --- a/third_party/blink/renderer/platform/heap/impl/garbage_collected.h +++ /dev/null
@@ -1,114 +0,0 @@ -// Copyright 2015 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. - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_GARBAGE_COLLECTED_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_GARBAGE_COLLECTED_H_ - -#include "third_party/blink/renderer/platform/heap/thread_state.h" -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" -#include "third_party/blink/renderer/platform/wtf/type_traits.h" - -namespace blink { - -template <typename T> -class GarbageCollected; - -// GC_PLUGIN_IGNORE is used to make the plugin ignore a particular class or -// field when checking for proper usage. When using GC_PLUGIN_IGNORE -// a bug-number should be provided as an argument where the bug describes -// what needs to happen to remove the GC_PLUGIN_IGNORE again. -#if defined(__clang__) -#define GC_PLUGIN_IGNORE(bug) \ - __attribute__((annotate("blink_gc_plugin_ignore"))) -#else -#define GC_PLUGIN_IGNORE(bug) -#endif - -// Template to determine if a class is a GarbageCollectedMixin by checking if it -// has IsGarbageCollectedMixinMarker -template <typename T> -struct IsGarbageCollectedMixin { - private: - typedef char YesType; - struct NoType { - char padding[8]; - }; - - template <typename U> - static YesType CheckMarker(typename U::IsGarbageCollectedMixinMarker*); - template <typename U> - static NoType CheckMarker(...); - - public: - static const bool value = sizeof(CheckMarker<T>(nullptr)) == sizeof(YesType); -}; - -// TraceDescriptor is used to describe how to trace an object. -struct TraceDescriptor { - STACK_ALLOCATED(); - - public: - // The adjusted base pointer of the object that should be traced. - const void* base_object_payload; - // A callback for tracing the object. - TraceCallback callback; -}; - -// The GarbageCollectedMixin interface can be used to automatically define -// TraceTrait/ObjectAliveTrait on non-leftmost deriving classes which need -// to be garbage collected. -class PLATFORM_EXPORT GarbageCollectedMixin { - public: - typedef int IsGarbageCollectedMixinMarker; - virtual void Trace(Visitor*) const {} -}; - -// Base class for objects allocated in the Blink garbage-collected heap. -// -// Instances of GarbageCollected will be finalized if they are non-trivially -// destructible. -template <typename T> -class GarbageCollected; - -template <typename T, - bool = WTF::IsSubclassOfTemplate<typename std::remove_const<T>::type, - GarbageCollected>::value> -class NeedsAdjustPointer; - -template <typename T> -class NeedsAdjustPointer<T, true> { - static_assert(sizeof(T), "T must be fully defined"); - - public: - static const bool value = false; -}; - -template <typename T> -class NeedsAdjustPointer<T, false> { - static_assert(sizeof(T), "T must be fully defined"); - - public: - static const bool value = true; -}; - -// TODO(sof): migrate to wtf/TypeTraits.h -template <typename T> -class IsFullyDefined { - using TrueType = char; - struct FalseType { - char dummy[2]; - }; - - template <typename U, size_t sz = sizeof(U)> - static TrueType IsSizeofKnown(U*); - static FalseType IsSizeofKnown(...); - static T& t_; - - public: - static const bool value = sizeof(TrueType) == sizeof(IsSizeofKnown(&t_)); -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_GARBAGE_COLLECTED_H_
diff --git a/third_party/blink/renderer/platform/heap/impl/gc_info.cc b/third_party/blink/renderer/platform/heap/impl/gc_info.cc deleted file mode 100644 index a527169..0000000 --- a/third_party/blink/renderer/platform/heap/impl/gc_info.cc +++ /dev/null
@@ -1,134 +0,0 @@ -// Copyright 2015 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/heap/impl/gc_info.h" - -#include "base/allocator/partition_allocator/page_allocator.h" -#include "base/bits.h" -#include "build/build_config.h" -#include "third_party/blink/renderer/platform/heap/heap.h" -#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h" - -namespace blink { - -namespace { - -constexpr size_t kEntrySize = sizeof(GCInfo*); - -PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR GCInfoIndex -ComputeInitialTableLimit() { - // (Light) experimentation suggests that Blink doesn't need more than this - // while handling content on popular web properties. - constexpr size_t kInitialWantedLimit = 512; - - // Different OSes have different page sizes, so we have to choose the minimum - // of memory wanted and OS page size. - constexpr size_t memory_wanted = kInitialWantedLimit * kEntrySize; - return static_cast<GCInfoIndex>( - base::RoundUpToPageAllocationGranularity(memory_wanted) / kEntrySize); -} - -PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR size_t MaxTableSize() { - return base::RoundUpToPageAllocationGranularity(GCInfoTable::kMaxIndex * - kEntrySize); -} - -} // namespace - -GCInfoTable* GCInfoTable::global_table_ = nullptr; -constexpr GCInfoIndex GCInfoTable::kMaxIndex; -constexpr GCInfoIndex GCInfoTable::kMinIndex; - -void GCInfoTable::CreateGlobalTable() { - // Allocation and resizing are built around the following invariants. - static_assert(base::bits::IsPowerOfTwo(kEntrySize), - "GCInfoTable entries size must be power of " - "two"); - -#if defined(PAGE_ALLOCATOR_CONSTANTS_ARE_CONSTEXPR) -#define STATIC_ASSERT_OR_CHECK(condition, message) \ - static_assert(condition, message) -#else -#define STATIC_ASSERT_OR_CHECK(condition, message) \ - do { \ - CHECK(condition) << (message); \ - } while (false) -#endif - - STATIC_ASSERT_OR_CHECK( - 0 == base::PageAllocationGranularity() % base::SystemPageSize(), - "System page size must be a multiple of page allocation granularity"); - -#undef STATIC_ASSERT_OR_CHECK - - DEFINE_STATIC_LOCAL(GCInfoTable, table, ()); - global_table_ = &table; -} - -GCInfoIndex GCInfoTable::EnsureGCInfoIndex( - const GCInfo* gc_info, - std::atomic<GCInfoIndex>* gc_info_index_slot) { - DCHECK(gc_info); - DCHECK(gc_info_index_slot); - - // Ensuring a new index involves current index adjustment as well as - // potentially resizing the table. For simplicity we use a lock. - MutexLocker locker(table_mutex_); - - // If more than one thread ends up allocating a slot for the same GCInfo, have - // later threads reuse the slot allocated by the first. - GCInfoIndex gc_info_index = - gc_info_index_slot->load(std::memory_order_relaxed); - if (gc_info_index) - return gc_info_index; - - if (current_index_ == limit_) - Resize(); - - gc_info_index = current_index_++; - CHECK_LT(gc_info_index, GCInfoTable::kMaxIndex); - - table_[gc_info_index] = gc_info; - gc_info_index_slot->store(gc_info_index, std::memory_order_release); - return gc_info_index; -} - -void GCInfoTable::Resize() { - const GCInfoIndex new_limit = - (limit_) ? 2 * limit_ : ComputeInitialTableLimit(); - CHECK_GT(new_limit, limit_); - const size_t old_committed_size = limit_ * kEntrySize; - const size_t new_committed_size = new_limit * kEntrySize; - CHECK(table_); - CHECK_EQ(0u, new_committed_size % base::PageAllocationGranularity()); - CHECK_GE(MaxTableSize(), limit_ * kEntrySize); - - // Recommitting and zapping assumes byte-addressable storage. - uint8_t* const current_table_end = - reinterpret_cast<uint8_t*>(table_) + old_committed_size; - const size_t table_size_delta = new_committed_size - old_committed_size; - - // Commit the new size and allow read/write. - base::RecommitSystemPages(current_table_end, table_size_delta, - base::PageReadWrite, base::PageUpdatePermissions); - -#if DCHECK_IS_ON() - // Check that newly-committed memory is zero-initialized. - for (size_t i = 0; i < (table_size_delta / sizeof(uintptr_t)); ++i) { - DCHECK(!reinterpret_cast<uintptr_t*>(current_table_end)[i]); - } -#endif // DCHECK_IS_ON() - - limit_ = new_limit; -} - -GCInfoTable::GCInfoTable() { - table_ = reinterpret_cast<GCInfo const**>(base::AllocPages( - nullptr, MaxTableSize(), base::PageAllocationGranularity(), - base::PageInaccessible, base::PageTag::kBlinkGC)); - CHECK(table_); - Resize(); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/impl/gc_info.h b/third_party/blink/renderer/platform/heap/impl/gc_info.h deleted file mode 100644 index bec05ee6..0000000 --- a/third_party/blink/renderer/platform/heap/impl/gc_info.h +++ /dev/null
@@ -1,128 +0,0 @@ -// Copyright 2015 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. - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_GC_INFO_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_GC_INFO_H_ - -#include <atomic> -#include "base/gtest_prod_util.h" -#include "third_party/blink/renderer/platform/heap/blink_gc.h" -#include "third_party/blink/renderer/platform/heap/impl/finalizer_traits.h" -#include "third_party/blink/renderer/platform/heap/impl/name_traits.h" -#include "third_party/blink/renderer/platform/wtf/threading_primitives.h" - -namespace blink { - -template <typename T> -struct TraceTrait; - -using GCInfoIndex = uint32_t; - -// GCInfo contains metadata for objects that are instantiated from classes that -// inherit from GarbageCollected. -struct PLATFORM_EXPORT GCInfo final { - static inline const GCInfo& From(GCInfoIndex); - - const TraceCallback trace; - const internal::FinalizationCallback finalize; - const NameCallback name; - const bool has_v_table; -}; - -class PLATFORM_EXPORT GCInfoTable final { - public: - // At maximum |kMaxIndex - 1| indices are supported. - // - // We assume that 14 bits is enough to represent all possible types: during - // telemetry runs, we see about 1,000 different types; looking at the output - // of the Oilpan GC Clang plugin, there appear to be at most about 6,000 - // types. Thus 14 bits should be more than twice as many bits as we will ever - // need. - static constexpr GCInfoIndex kMaxIndex = 1 << 14; - - // Minimum index returned. Values smaller |kMinIndex| may be used as - // sentinels. - static constexpr GCInfoIndex kMinIndex = 1; - - // Sets up a singleton table that can be acquired using Get(). - static void CreateGlobalTable(); - - static GCInfoTable* GetMutable() { return global_table_; } - static const GCInfoTable& Get() { return *global_table_; } - - const GCInfo& GCInfoFromIndex(GCInfoIndex index) const { - DCHECK_GE(index, kMinIndex); - DCHECK_LT(index, kMaxIndex); - DCHECK(table_); - const GCInfo* info = table_[index]; - DCHECK(info); - return *info; - } - - GCInfoIndex EnsureGCInfoIndex(const GCInfo*, std::atomic<GCInfoIndex>*); - - // Returns the number of recorded GCInfo objects, including |kMinIndex|. - GCInfoIndex NumberOfGCInfos() const { return current_index_; } - - private: - FRIEND_TEST_ALL_PREFIXES(GCInfoTest, InitialEmpty); - FRIEND_TEST_ALL_PREFIXES(GCInfoTest, ResizeToMaxIndex); - FRIEND_TEST_ALL_PREFIXES(GCInfoDeathTest, MoreThanMaxIndexInfos); - - // Singleton for each process. Retrieved through Get(). - static GCInfoTable* global_table_; - - // Use GCInfoTable::Get() for retrieving the global table outside of testing - // code. - GCInfoTable(); - - void Resize(); - - // Holds the per-class GCInfo descriptors; each HeapObjectHeader keeps an - // index into this table. - const GCInfo** table_ = nullptr; - - // Current index used when requiring a new GCInfo object. - GCInfoIndex current_index_ = kMinIndex; - - // The limit (exclusive) of the currently allocated table. - GCInfoIndex limit_ = 0; - - Mutex table_mutex_; -}; - -// static -const GCInfo& GCInfo::From(GCInfoIndex index) { - return GCInfoTable::Get().GCInfoFromIndex(index); -} - -template <typename T> -struct GCInfoTrait { - STATIC_ONLY(GCInfoTrait); - - static GCInfoIndex Index() { - static_assert(sizeof(T), "T must be fully defined"); - static const GCInfo kGcInfo = { - TraceTrait<T>::Trace, internal::FinalizerTrait<T>::kCallback, - NameTrait<T>::GetName, std::is_polymorphic<T>::value}; - // This is more complicated than using threadsafe initialization, but this - // is instantiated many times (once for every GC type). - static std::atomic<GCInfoIndex> gc_info_index{0}; - GCInfoIndex index = gc_info_index.load(std::memory_order_acquire); - if (!index) { - index = GCInfoTable::GetMutable()->EnsureGCInfoIndex(&kGcInfo, - &gc_info_index); - } - DCHECK_GE(index, GCInfoTable::kMinIndex); - DCHECK_LT(index, GCInfoTable::kMaxIndex); - return index; - } -}; - -template <typename U> -class GCInfoTrait<const U> : public GCInfoTrait<U> {}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_GC_INFO_H_
diff --git a/third_party/blink/renderer/platform/heap/impl/heap.cc b/third_party/blink/renderer/platform/heap/impl/heap.cc deleted file mode 100644 index 577bb37c..0000000 --- a/third_party/blink/renderer/platform/heap/impl/heap.cc +++ /dev/null
@@ -1,794 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "third_party/blink/renderer/platform/heap/heap.h" - -#include <algorithm> -#include <limits> -#include <memory> - -#include "base/trace_event/process_memory_dump.h" -#include "third_party/blink/public/common/features.h" -#include "third_party/blink/public/platform/platform.h" -#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h" -#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h" -#include "third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider.h" -#include "third_party/blink/renderer/platform/heap/heap_stats_collector.h" -#include "third_party/blink/renderer/platform/heap/impl/heap_compact.h" -#include "third_party/blink/renderer/platform/heap/impl/marking_scheduling_oracle.h" -#include "third_party/blink/renderer/platform/heap/impl/marking_visitor.h" -#include "third_party/blink/renderer/platform/heap/impl/page_bloom_filter.h" -#include "third_party/blink/renderer/platform/heap/impl/page_memory.h" -#include "third_party/blink/renderer/platform/heap/impl/page_pool.h" -#include "third_party/blink/renderer/platform/heap/thread_state_scopes.h" -#include "third_party/blink/renderer/platform/heap/unified_heap_marking_visitor.h" -#include "third_party/blink/renderer/platform/instrumentation/histogram.h" -#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h" -#include "third_party/blink/renderer/platform/instrumentation/tracing/web_memory_allocator_dump.h" -#include "third_party/blink/renderer/platform/instrumentation/tracing/web_process_memory_dump.h" -#include "third_party/blink/renderer/platform/wtf/allocator/partitions.h" -#include "third_party/blink/renderer/platform/wtf/leak_annotations.h" - -namespace blink { - -class ProcessHeapReporter final : public ThreadHeapStatsObserver { - public: - void IncreaseAllocatedSpace(size_t bytes) final { - ProcessHeap::IncreaseTotalAllocatedSpace(bytes); - } - - void DecreaseAllocatedSpace(size_t bytes) final { - ProcessHeap::DecreaseTotalAllocatedSpace(bytes); - } - - void ResetAllocatedObjectSize(size_t bytes) final { - ProcessHeap::DecreaseTotalAllocatedObjectSize(prev_incremented_); - ProcessHeap::IncreaseTotalAllocatedObjectSize(bytes); - prev_incremented_ = bytes; - } - - void IncreaseAllocatedObjectSize(size_t bytes) final { - ProcessHeap::IncreaseTotalAllocatedObjectSize(bytes); - prev_incremented_ += bytes; - } - - void DecreaseAllocatedObjectSize(size_t bytes) final { - ProcessHeap::DecreaseTotalAllocatedObjectSize(bytes); - prev_incremented_ -= bytes; - } - - private: - size_t prev_incremented_ = 0; -}; - -ThreadHeap::ThreadHeap(ThreadState* thread_state) - : thread_state_(thread_state), - heap_stats_collector_(std::make_unique<ThreadHeapStatsCollector>()), - region_tree_(std::make_unique<RegionTree>()), - page_bloom_filter_(std::make_unique<PageBloomFilter>()), - free_page_pool_(std::make_unique<PagePool>()), - process_heap_reporter_(std::make_unique<ProcessHeapReporter>()) { - if (ThreadState::Current()->IsMainThread()) - main_thread_heap_ = this; - - for (int arena_index = 0; arena_index < BlinkGC::kLargeObjectArenaIndex; - arena_index++) { - arenas_[arena_index] = new NormalPageArena(thread_state_, arena_index); - } - arenas_[BlinkGC::kLargeObjectArenaIndex] = - new LargeObjectArena(thread_state_, BlinkGC::kLargeObjectArenaIndex); - - stats_collector()->RegisterObserver(process_heap_reporter_.get()); -} - -ThreadHeap::~ThreadHeap() { - for (int i = 0; i < BlinkGC::kNumberOfArenas; ++i) - delete arenas_[i]; -} - -Address ThreadHeap::CheckAndMarkPointer(MarkingVisitor* visitor, - Address address) { - DCHECK(thread_state_->InAtomicMarkingPause()); - -#if !DCHECK_IS_ON() - if (!page_bloom_filter_->MayContain(address)) { - return nullptr; - } -#endif - - if (BasePage* page = LookupPageForAddress(address)) { -#if DCHECK_IS_ON() - DCHECK(page->Contains(address)) - << "address " << address << " not part of page " << page; -#endif - DCHECK(page_bloom_filter_->MayContain(address)); - DCHECK(&visitor->Heap() == &page->Arena()->GetThreadState()->Heap()); - visitor->ConservativelyMarkAddress(page, address); - return address; - } - - return nullptr; -} - -void ThreadHeap::VisitRememberedSets(MarkingVisitor* visitor) { - static_assert(BlinkGC::kLargeObjectArenaIndex + 1 == BlinkGC::kNumberOfArenas, - "LargeObject arena must be the last one."); - const auto visit_header = [visitor](HeapObjectHeader* header) { - // Process only old objects. - if (header->IsOld<HeapObjectHeader::AccessMode::kNonAtomic>()) { - // The design of young generation requires collections to be executed at - // the top level (with the guarantee that no objects are currently being - // in construction). This can be ensured by running young GCs from safe - // points or by reintroducing nested allocation scopes that avoid - // finalization. - DCHECK(header->IsMarked()); - DCHECK(!header->IsInConstruction()); - const GCInfo& gc_info = GCInfo::From(header->GcInfoIndex()); - gc_info.trace(visitor, header->Payload()); - } - }; - for (size_t i = 0; i < BlinkGC::kLargeObjectArenaIndex; ++i) { - static_cast<NormalPageArena*>(arenas_[i]) - ->IterateAndClearCardTables(visit_header); - } - static_cast<LargeObjectArena*>(arenas_[BlinkGC::kLargeObjectArenaIndex]) - ->IterateAndClearRememberedPages(visit_header); -} - -void ThreadHeap::SetupWorklists(bool should_initialize_compaction_worklists) { - marking_worklist_ = std::make_unique<MarkingWorklist>(); - write_barrier_worklist_ = std::make_unique<WriteBarrierWorklist>(); - not_fully_constructed_worklist_ = - std::make_unique<NotFullyConstructedWorklist>(); - previously_not_fully_constructed_worklist_ = - std::make_unique<NotFullyConstructedWorklist>(); - weak_callback_worklist_ = std::make_unique<WeakCallbackWorklist>(); - discovered_ephemeron_pairs_worklist_ = - std::make_unique<EphemeronPairsWorklist>(); - ephemeron_pairs_to_process_worklist_ = - std::make_unique<EphemeronPairsWorklist>(); - v8_references_worklist_ = std::make_unique<V8ReferencesWorklist>(); - not_safe_to_concurrently_trace_worklist_ = - std::make_unique<NotSafeToConcurrentlyTraceWorklist>(); - weak_containers_worklist_ = std::make_unique<WeakContainersWorklist>(); - if (should_initialize_compaction_worklists) { - movable_reference_worklist_ = std::make_unique<MovableReferenceWorklist>(); - } -} - -void ThreadHeap::DestroyMarkingWorklists(BlinkGC::StackState stack_state) { - marking_worklist_.reset(); - write_barrier_worklist_.reset(); - previously_not_fully_constructed_worklist_.reset(); - weak_callback_worklist_.reset(); - ephemeron_pairs_to_process_worklist_.reset(); - v8_references_worklist_.reset(); - not_safe_to_concurrently_trace_worklist_.reset(); - weak_containers_worklist_.reset(); - // The fixed point iteration may have found not-fully-constructed objects. - // Such objects should have already been found through the stack scan though - // and should thus already be marked. - // - // Possible reasons for encountering unmarked objects here: - // - Object is not allocated through MakeGarbageCollected. - // - Broken stack (roots) scanning. - if (!not_fully_constructed_worklist_->IsGlobalEmpty()) { -#if DCHECK_IS_ON() - const bool conservative_gc = - BlinkGC::StackState::kHeapPointersOnStack == stack_state; - NotFullyConstructedItem item; - while (not_fully_constructed_worklist_->Pop(WorklistTaskId::MutatorThread, - &item)) { - HeapObjectHeader* const header = HeapObjectHeader::FromInnerAddress( - reinterpret_cast<Address>(const_cast<void*>(item))); - DCHECK(conservative_gc && header->IsMarked()) - << " conservative: " << (conservative_gc ? "yes" : "no") - << " type: " << header->Name(); - } -#else - not_fully_constructed_worklist_->Clear(); -#endif - } - not_fully_constructed_worklist_.reset(); - - // |discovered_ephemeron_pairs_worklist_| may still hold ephemeron pairs with - // dead keys. - if (!discovered_ephemeron_pairs_worklist_->IsGlobalEmpty()) { -#if DCHECK_IS_ON() - EphemeronPairItem item; - while (discovered_ephemeron_pairs_worklist_->Pop( - WorklistTaskId::MutatorThread, &item)) { - const HeapObjectHeader* const header = HeapObjectHeader::FromInnerAddress( - reinterpret_cast<ConstAddress>(item.key)); - DCHECK(!header->IsMarked()); - } -#else - discovered_ephemeron_pairs_worklist_->Clear(); -#endif - } - discovered_ephemeron_pairs_worklist_.reset(); -} - -void ThreadHeap::DestroyCompactionWorklists() { - movable_reference_worklist_.reset(); -} - -HeapCompact* ThreadHeap::Compaction() { - if (!compaction_) - compaction_ = std::make_unique<HeapCompact>(this); - return compaction_.get(); -} - -bool ThreadHeap::ShouldRegisterMovingAddress() { - return Compaction()->ShouldRegisterMovingAddress(); -} - -void ThreadHeap::FlushNotFullyConstructedObjects() { - NotFullyConstructedWorklist::View view(not_fully_constructed_worklist_.get(), - WorklistTaskId::MutatorThread); - if (!view.IsLocalViewEmpty()) { - view.FlushToGlobal(); - previously_not_fully_constructed_worklist_->MergeGlobalPool( - not_fully_constructed_worklist_.get()); - } - DCHECK(view.IsLocalViewEmpty()); -} - -void ThreadHeap::FlushEphemeronPairs(EphemeronProcessing ephemeron_processing) { - if (ephemeron_processing == EphemeronProcessing::kPartialProcessing) { - if (steps_since_last_ephemeron_pairs_flush_ < - kStepsBeforeEphemeronPairsFlush) - return; - } - - ThreadHeapStatsCollector::EnabledScope stats_scope( - stats_collector(), ThreadHeapStatsCollector::kMarkFlushEphemeronPairs); - - EphemeronPairsWorklist::View view(discovered_ephemeron_pairs_worklist_.get(), - WorklistTaskId::MutatorThread); - if (!view.IsLocalViewEmpty()) { - view.FlushToGlobal(); - ephemeron_pairs_to_process_worklist_->MergeGlobalPool( - discovered_ephemeron_pairs_worklist_.get()); - } - - steps_since_last_ephemeron_pairs_flush_ = 0; -} - -void ThreadHeap::MarkNotFullyConstructedObjects(MarkingVisitor* visitor) { - DCHECK(!thread_state_->IsIncrementalMarking()); - ThreadHeapStatsCollector::Scope stats_scope( - stats_collector(), - ThreadHeapStatsCollector::kMarkNotFullyConstructedObjects); - - DCHECK_EQ(WorklistTaskId::MutatorThread, visitor->task_id()); - NotFullyConstructedItem item; - while (not_fully_constructed_worklist_->Pop(WorklistTaskId::MutatorThread, - &item)) { - BasePage* const page = PageFromObject(item); - visitor->ConservativelyMarkAddress(page, - reinterpret_cast<ConstAddress>(item)); - } -} - -namespace { - -static constexpr size_t kDefaultDeadlineCheckInterval = 150u; -static constexpr size_t kDefaultConcurrentDeadlineCheckInterval = - 5 * kDefaultDeadlineCheckInterval; - -template <size_t kDeadlineCheckInterval = kDefaultDeadlineCheckInterval, - typename Worklist, - typename Callback, - typename YieldPredicate> -bool DrainWorklist(Worklist* worklist, - Callback callback, - YieldPredicate should_yield, - int task_id) { - // For concurrent markers, should_yield also reports marked bytes. - if (worklist->IsLocalViewEmpty(task_id)) - return true; - if (should_yield()) - return false; - size_t processed_callback_count = kDeadlineCheckInterval; - typename Worklist::EntryType item; - while (worklist->Pop(task_id, &item)) { - callback(item); - if (--processed_callback_count == 0) { - if (should_yield()) { - return false; - } - processed_callback_count = kDeadlineCheckInterval; - } - } - return true; -} - -template <size_t kDeadlineCheckInterval = kDefaultDeadlineCheckInterval, - typename Worklist, - typename Callback> -bool DrainWorklistWithDeadline(base::TimeTicks deadline, - Worklist* worklist, - Callback callback, - int task_id) { - return DrainWorklist<kDeadlineCheckInterval>( - worklist, std::move(callback), - [deadline]() { return deadline <= base::TimeTicks::Now(); }, task_id); -} - -} // namespace - -bool ThreadHeap::InvokeEphemeronCallbacks( - EphemeronProcessing ephemeron_processing, - MarkingVisitor* visitor, - base::TimeTicks deadline) { - if (ephemeron_processing == EphemeronProcessing::kPartialProcessing) { - if (steps_since_last_ephemeron_processing_ < - kStepsBeforeEphemeronProcessing) { - // Returning "no more work" to avoid excessive processing. The fixed - // point computation in the atomic pause takes care of correctness. - return true; - } - } - - FlushEphemeronPairs(EphemeronProcessing::kFullProcessing); - - steps_since_last_ephemeron_processing_ = 0; - - // Mark any strong pointers that have now become reachable in ephemeron maps. - ThreadHeapStatsCollector::EnabledScope stats_scope( - stats_collector(), - ThreadHeapStatsCollector::kMarkInvokeEphemeronCallbacks); - - DCHECK_EQ(WorklistTaskId::MutatorThread, visitor->task_id()); - - // Then we iterate over the new callbacks found by the marking visitor. - // Callbacks found by the concurrent marking will be flushed eventually - // and then invoked by the mutator thread (in the atomic pause at latest). - return DrainWorklistWithDeadline( - deadline, ephemeron_pairs_to_process_worklist_.get(), - [visitor](EphemeronPairItem& item) { - visitor->VisitEphemeron(item.key, item.value_desc); - }, - WorklistTaskId::MutatorThread); -} - -bool ThreadHeap::AdvanceMarking(MarkingVisitor* visitor, - base::TimeTicks deadline, - EphemeronProcessing ephemeron_processing) { - DCHECK_EQ(WorklistTaskId::MutatorThread, visitor->task_id()); - - ++steps_since_last_ephemeron_pairs_flush_; - ++steps_since_last_ephemeron_processing_; - - bool finished; - bool processed_ephemerons = false; - FlushEphemeronPairs(ephemeron_processing); - // Ephemeron fixed point loop. - do { - { - // Iteratively mark all objects that are reachable from the objects - // currently pushed onto the marking worklist. - ThreadHeapStatsCollector::EnabledScope stats_scope( - stats_collector(), ThreadHeapStatsCollector::kMarkProcessWorklists); - - // Start with mutator-thread-only worklists (not fully constructed). - // If time runs out, concurrent markers can take care of the rest. - - { - ThreadHeapStatsCollector::EnabledScope inner_scope( - stats_collector(), ThreadHeapStatsCollector::kMarkBailOutObjects); - // Items in the bailout worklist are only collection backing stores. - // These items could take a long time to process, so we should check - // the deadline more often (backing stores and large items can also be - // found in the regular marking worklist, but those are interleaved - // with smaller objects). - finished = DrainWorklistWithDeadline<kDefaultDeadlineCheckInterval / 5>( - deadline, not_safe_to_concurrently_trace_worklist_.get(), - [visitor](const NotSafeToConcurrentlyTraceItem& item) { - item.desc.callback(visitor, item.desc.base_object_payload); - visitor->AccountMarkedBytes(item.bailout_size); - }, - WorklistTaskId::MutatorThread); - if (!finished) - break; - } - - { - ThreadHeapStatsCollector::EnabledScope inner_scope( - stats_collector(), - ThreadHeapStatsCollector::kMarkFlushV8References); - finished = FlushV8References(deadline); - if (!finished) - break; - } - - { - ThreadHeapStatsCollector::EnabledScope inner_scope( - stats_collector(), - ThreadHeapStatsCollector::kMarkProcessNotFullyconstructeddWorklist); - // Convert |previously_not_fully_constructed_worklist_| to - // |marking_worklist_|. This merely re-adds items with the proper - // callbacks. - finished = DrainWorklistWithDeadline( - deadline, previously_not_fully_constructed_worklist_.get(), - [visitor](NotFullyConstructedItem& item) { - visitor->DynamicallyMarkAddress( - reinterpret_cast<ConstAddress>(item)); - }, - WorklistTaskId::MutatorThread); - if (!finished) - break; - } - - { - ThreadHeapStatsCollector::EnabledScope inner_scope( - stats_collector(), - ThreadHeapStatsCollector::kMarkProcessMarkingWorklist); - finished = DrainWorklistWithDeadline( - deadline, marking_worklist_.get(), - [visitor](const MarkingItem& item) { - HeapObjectHeader* header = - HeapObjectHeader::FromPayload(item.base_object_payload); - DCHECK(!header->IsInConstruction()); - item.callback(visitor, item.base_object_payload); - visitor->AccountMarkedBytes(header); - }, - WorklistTaskId::MutatorThread); - if (!finished) - break; - } - - { - ThreadHeapStatsCollector::EnabledScope inner_scope( - stats_collector(), - ThreadHeapStatsCollector::kMarkProcessWriteBarrierWorklist); - finished = DrainWorklistWithDeadline( - deadline, write_barrier_worklist_.get(), - [visitor](HeapObjectHeader* header) { - DCHECK(!header->IsInConstruction()); - GCInfo::From(header->GcInfoIndex()) - .trace(visitor, header->Payload()); - visitor->AccountMarkedBytes(header); - }, - WorklistTaskId::MutatorThread); - if (!finished) - break; - } - } - - if ((ephemeron_processing == EphemeronProcessing::kFullProcessing) || - !processed_ephemerons) { - processed_ephemerons = true; - finished = - InvokeEphemeronCallbacks(ephemeron_processing, visitor, deadline); - if (!finished) - break; - } - - // Rerun loop if ephemeron processing queued more objects for tracing. - } while (!marking_worklist_->IsLocalViewEmpty(WorklistTaskId::MutatorThread)); - - return finished; -} - -bool ThreadHeap::HasWorkForConcurrentMarking() const { - return !marking_worklist_->IsGlobalPoolEmpty() || - !write_barrier_worklist_->IsGlobalPoolEmpty() || - !previously_not_fully_constructed_worklist_->IsGlobalPoolEmpty() || - !ephemeron_pairs_to_process_worklist_->IsGlobalPoolEmpty(); -} - -size_t ThreadHeap::ConcurrentMarkingGlobalWorkSize() const { - return marking_worklist_->GlobalPoolSize() + - write_barrier_worklist_->GlobalPoolSize() + - previously_not_fully_constructed_worklist_->GlobalPoolSize() + - ephemeron_pairs_to_process_worklist_->GlobalPoolSize(); -} - -bool ThreadHeap::AdvanceConcurrentMarking( - ConcurrentMarkingVisitor* visitor, - base::JobDelegate* delegate, - MarkingSchedulingOracle* marking_scheduler) { - auto should_yield_callback = [marking_scheduler, visitor, delegate]() { - marking_scheduler->AddConcurrentlyMarkedBytes( - visitor->RecentlyMarkedBytes()); - return delegate->ShouldYield(); - }; - bool finished; - do { - // Convert |previously_not_fully_constructed_worklist_| to - // |marking_worklist_|. This merely re-adds items with the proper - // callbacks. - finished = DrainWorklist<kDefaultConcurrentDeadlineCheckInterval>( - previously_not_fully_constructed_worklist_.get(), - [visitor](NotFullyConstructedItem& item) { - PageFromObject(item)->SynchronizedLoad(); - visitor->DynamicallyMarkAddress(reinterpret_cast<ConstAddress>(item)); - }, - should_yield_callback, visitor->task_id()); - if (!finished) - break; - - // Iteratively mark all objects that are reachable from the objects - // currently pushed onto the marking worklist. - finished = DrainWorklist<kDefaultConcurrentDeadlineCheckInterval>( - marking_worklist_.get(), - [visitor](const MarkingItem& item) { - HeapObjectHeader* header = - HeapObjectHeader::FromPayload(item.base_object_payload); - PageFromObject(header)->SynchronizedLoad(); - DCHECK( - !header - ->IsInConstruction<HeapObjectHeader::AccessMode::kAtomic>()); - item.callback(visitor, item.base_object_payload); - visitor->AccountMarkedBytes(header); - }, - should_yield_callback, visitor->task_id()); - if (!finished) - break; - - finished = DrainWorklist<kDefaultConcurrentDeadlineCheckInterval>( - write_barrier_worklist_.get(), - [visitor](HeapObjectHeader* header) { - PageFromObject(header)->SynchronizedLoad(); - DCHECK( - !header - ->IsInConstruction<HeapObjectHeader::AccessMode::kAtomic>()); - GCInfo::From(header->GcInfoIndex()).trace(visitor, header->Payload()); - visitor->AccountMarkedBytes(header); - }, - should_yield_callback, visitor->task_id()); - if (!finished) - break; - - { - ThreadHeapStatsCollector::ConcurrentScope stats_scope( - stats_collector(), - ThreadHeapStatsCollector::kConcurrentMarkInvokeEphemeronCallbacks); - - // Then we iterate over the new ephemerons found by the marking visitor. - // Callbacks found by the concurrent marking will be flushed eventually - // by the mutator thread and then invoked either concurrently or by the - // mutator thread (in the atomic pause at latest). - finished = DrainWorklist<kDefaultConcurrentDeadlineCheckInterval>( - ephemeron_pairs_to_process_worklist_.get(), - [visitor](EphemeronPairItem& item) { - visitor->VisitEphemeron(item.key, item.value_desc); - }, - should_yield_callback, visitor->task_id()); - if (!finished) - break; - } - - } while (HasWorkForConcurrentMarking()); - - return finished; -} - -void ThreadHeap::WeakProcessing(MarkingVisitor* visitor) { - ThreadHeapStatsCollector::Scope stats_scope( - stats_collector(), ThreadHeapStatsCollector::kMarkWeakProcessing); - - // Weak processing may access unmarked objects but are forbidden from - // resurrecting them or allocating new ones. - ThreadState::NoAllocationScope allocation_forbidden(ThreadState::Current()); - - DCHECK_EQ(WorklistTaskId::MutatorThread, visitor->task_id()); - - // Call weak callbacks on objects that may now be pointing to dead objects. - CustomCallbackItem item; - LivenessBroker broker = internal::LivenessBrokerFactory::Create(); - while (weak_callback_worklist_->Pop(WorklistTaskId::MutatorThread, &item)) { - item.callback(broker, item.parameter); - } - // Weak callbacks should not add any new objects for marking. - DCHECK(marking_worklist_->IsGlobalEmpty()); -} - -void ThreadHeap::VerifyMarking() { - for (int i = 0; i < BlinkGC::kNumberOfArenas; ++i) { - arenas_[i]->VerifyMarking(); - } -} - -size_t ThreadHeap::ObjectPayloadSizeForTesting() { - ThreadState::AtomicPauseScope atomic_pause_scope(thread_state_); - ScriptForbiddenScope script_forbidden_scope; - size_t object_payload_size = 0; - thread_state_->SetGCPhase(ThreadState::GCPhase::kMarking); - thread_state_->Heap().MakeConsistentForGC(); - thread_state_->Heap().PrepareForSweep(BlinkGC::CollectionType::kMajor); - for (int i = 0; i < BlinkGC::kNumberOfArenas; ++i) - object_payload_size += arenas_[i]->ObjectPayloadSizeForTesting(); - MakeConsistentForMutator(); - thread_state_->SetGCPhase(ThreadState::GCPhase::kSweeping); - thread_state_->SetGCPhase(ThreadState::GCPhase::kNone); - return object_payload_size; -} - -void ThreadHeap::ResetAllocationPointForTesting() { - for (int i = 0; i < BlinkGC::kNumberOfArenas; ++i) - arenas_[i]->ResetAllocationPoint(); -} - -BasePage* ThreadHeap::LookupPageForAddress(ConstAddress address) { - if (PageMemoryRegion* region = region_tree_->Lookup(address)) { - return region->PageFromAddress(address); - } - return nullptr; -} - -void ThreadHeap::MakeConsistentForGC() { - DCHECK(thread_state_->InAtomicMarkingPause()); - for (BaseArena* arena : arenas_) { - arena->MakeConsistentForGC(); - } -} - -void ThreadHeap::MakeConsistentForMutator() { - DCHECK(thread_state_->InAtomicMarkingPause()); - for (BaseArena* arena : arenas_) { - arena->MakeConsistentForMutator(); - } -} - -void ThreadHeap::Unmark() { - DCHECK(thread_state_->InAtomicMarkingPause()); - for (BaseArena* arena : arenas_) { - arena->Unmark(); - } -} - -void ThreadHeap::Compact() { - if (!Compaction()->IsCompacting()) - return; - - ThreadHeapStatsCollector::Scope stats_scope( - stats_collector(), ThreadHeapStatsCollector::kAtomicPauseCompaction); - // Compaction is done eagerly and before the mutator threads get - // to run again. Doing it lazily is problematic, as the mutator's - // references to live objects could suddenly be invalidated by - // compaction of a page/heap. We do know all the references to - // the relocating objects just after marking, but won't later. - // (e.g., stack references could have been created, new objects - // created which refer to old collection objects, and so on.) - - // Compact the hash table backing store arena first, it usually has - // higher fragmentation and is larger. - for (int i = BlinkGC::kHashTableArenaIndex; i >= BlinkGC::kVectorArenaIndex; - --i) - static_cast<NormalPageArena*>(arenas_[i])->SweepAndCompact(); - Compaction()->Finish(); -} - -void ThreadHeap::PrepareForSweep(BlinkGC::CollectionType collection_type) { - DCHECK(thread_state_->InAtomicMarkingPause()); - DCHECK(thread_state_->CheckThread()); - for (int i = 0; i < BlinkGC::kNumberOfArenas; i++) - arenas_[i]->PrepareForSweep(collection_type); -} - -void ThreadHeap::RemoveAllPages() { - DCHECK(thread_state_->CheckThread()); - for (int i = 0; i < BlinkGC::kNumberOfArenas; ++i) - arenas_[i]->RemoveAllPages(); -} - -void ThreadHeap::CompleteSweep() { - for (int i = 0; i < BlinkGC::kNumberOfArenas; i++) - arenas_[i]->CompleteSweep(); -} - -void ThreadHeap::InvokeFinalizersOnSweptPages() { - for (size_t i = BlinkGC::kNormalPage1ArenaIndex; i < BlinkGC::kNumberOfArenas; - i++) - arenas_[i]->InvokeFinalizersOnSweptPages(); -} - -#if defined(ADDRESS_SANITIZER) -void ThreadHeap::PoisonUnmarkedObjects() { - // Poisoning all unmarked objects in the other arenas. - for (int i = 1; i < BlinkGC::kNumberOfArenas; i++) - arenas_[i]->PoisonUnmarkedObjects(); -} -#endif - -#if DCHECK_IS_ON() -BasePage* ThreadHeap::FindPageFromAddress(Address address) { - for (int i = 0; i < BlinkGC::kNumberOfArenas; ++i) { - if (BasePage* page = arenas_[i]->FindPageFromAddress(address)) - return page; - } - return nullptr; -} -#endif - -void ThreadHeap::CollectStatistics(ThreadState::Statistics* stats) { -#define SNAPSHOT_ARENA(name) \ - arenas_[BlinkGC::k##name##ArenaIndex]->CollectStatistics( \ - BlinkGC::ToString(BlinkGC::k##name##ArenaIndex), stats); - - FOR_EACH_ARENA(SNAPSHOT_ARENA) -#undef SNAPSHOT_ARENA -} - -bool ThreadHeap::AdvanceLazySweep(base::TimeTicks deadline) { - static constexpr base::TimeDelta slack = base::TimeDelta::FromSecondsD(0.001); - for (size_t i = 0; i < BlinkGC::kNumberOfArenas; i++) { - // lazySweepWithDeadline() won't check the deadline until it sweeps - // 10 pages. So we give a small slack for safety. - const base::TimeDelta remaining_budget = - deadline - slack - base::TimeTicks::Now(); - if (remaining_budget <= base::TimeDelta() || - !arenas_[i]->LazySweepWithDeadline(deadline)) { - return false; - } - } - return true; -} - -bool ThreadHeap::AdvanceConcurrentSweep(base::JobDelegate* job) { - for (size_t i = 0; i < BlinkGC::kNumberOfArenas; i++) { - while (!arenas_[i]->ConcurrentSweepOnePage()) { - if (job->ShouldYield()) - return false; - } - } - return true; -} - -// TODO(omerkatz): Temporary solution until concurrent marking is ready. see -// https://crrev.com/c/1730054 for details. Eventually this will be removed. -bool ThreadHeap::FlushV8References(base::TimeTicks deadline) { - if (!thread_state_->IsUnifiedGCMarkingInProgress()) - return true; - - DCHECK(base::FeatureList::IsEnabled( - blink::features::kBlinkHeapConcurrentMarking) || - v8_references_worklist_->IsGlobalEmpty()); - - v8::EmbedderHeapTracer* controller = - reinterpret_cast<v8::EmbedderHeapTracer*>( - thread_state_->unified_heap_controller()); - return DrainWorklistWithDeadline( - deadline, v8_references_worklist_.get(), - [controller](const V8Reference& reference) { - if (!reference->Get().IsEmpty()) { - controller->RegisterEmbedderReference( - reference->template Cast<v8::Data>().Get()); - } - }, - WorklistTaskId::MutatorThread); -} - -ThreadHeap* ThreadHeap::main_thread_heap_ = nullptr; - -} // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/impl/heap.h b/third_party/blink/renderer/platform/heap/impl/heap.h deleted file mode 100644 index 687463da..0000000 --- a/third_party/blink/renderer/platform/heap/impl/heap.h +++ /dev/null
@@ -1,720 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_HEAP_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_HEAP_H_ - -#include <limits> -#include <memory> -#include <unordered_set> - -#include "base/dcheck_is_on.h" -#include "build/build_config.h" -#include "third_party/blink/renderer/platform/heap/impl/gc_info.h" -#include "third_party/blink/renderer/platform/heap/impl/heap_page.h" -#include "third_party/blink/renderer/platform/heap/impl/thread_state_statistics.h" -#include "third_party/blink/renderer/platform/heap/impl/worklist.h" -#include "third_party/blink/renderer/platform/heap/process_heap.h" -#include "third_party/blink/renderer/platform/heap/thread_state.h" -#include "third_party/blink/renderer/platform/heap/visitor.h" -#include "third_party/blink/renderer/platform/platform_export.h" -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" -#include "third_party/blink/renderer/platform/wtf/forward.h" -#include "third_party/blink/renderer/platform/wtf/sanitizers.h" -#include "third_party/blink/renderer/platform/wtf/threading_primitives.h" - -namespace blink { - -namespace incremental_marking_test { -class IncrementalMarkingScopeBase; -} // namespace incremental_marking_test - -class ConcurrentMarkingVisitor; -class ThreadHeapStatsCollector; -class PageBloomFilter; -class PagePool; -class ProcessHeapReporter; -class RegionTree; -class MarkingSchedulingOracle; - -using MarkingItem = TraceDescriptor; -using NotFullyConstructedItem = const void*; - -struct EphemeronPairItem { - const void* key; - TraceDescriptor value_desc; -}; - -struct CustomCallbackItem { - WeakCallback callback; - const void* parameter; -}; - -struct NotSafeToConcurrentlyTraceItem { - TraceDescriptor desc; - size_t bailout_size; -}; - -using V8Reference = const TraceWrapperV8Reference<v8::Value>*; - -// Segment size of 512 entries necessary to avoid throughput regressions. Since -// the work list is currently a temporary object this is not a problem. -using MarkingWorklist = Worklist<MarkingItem, 512 /* local entries */>; -using WriteBarrierWorklist = Worklist<HeapObjectHeader*, 64>; -using NotFullyConstructedWorklist = - Worklist<NotFullyConstructedItem, 16 /* local entries */>; -using WeakCallbackWorklist = - Worklist<CustomCallbackItem, 64 /* local entries */>; -// Using large local segments here (sized 512 entries) to avoid throughput -// regressions. -using MovableReferenceWorklist = - Worklist<const MovableReference*, 256 /* local entries */>; -using EphemeronPairsWorklist = - Worklist<EphemeronPairItem, 64 /* local entries */>; -using V8ReferencesWorklist = Worklist<V8Reference, 16 /* local entries */>; -using NotSafeToConcurrentlyTraceWorklist = - Worklist<NotSafeToConcurrentlyTraceItem, 64 /* local entries */>; - -class WeakContainersWorklist { - public: - inline void Push(const HeapObjectHeader* object) { - DCHECK(object); - WTF::MutexLocker locker(lock_); - objects_.insert(object); - } - - inline bool Contains(const HeapObjectHeader* object) { - // This method is called only during atomic pause, so lock is not needed. - DCHECK(object); - return objects_.find(object) != objects_.end(); - } - - private: - WTF::Mutex lock_; - std::unordered_set<const HeapObjectHeader*> objects_; -}; - -class HeapCompact; -template <typename T> -class Member; -template <typename T> -class WeakMember; -template <typename T> -class UntracedMember; - -namespace internal { - -class LivenessBrokerFactory; - -template <typename T, bool = NeedsAdjustPointer<T>::value> -class ObjectAliveTrait; - -template <typename T> -class ObjectAliveTrait<T, false> { - STATIC_ONLY(ObjectAliveTrait); - - public: - static bool IsHeapObjectAlive(const T* object) { - static_assert(sizeof(T), "T must be fully defined"); - return HeapObjectHeader::FromPayload(object)->IsMarked(); - } -}; - -template <typename T> -class ObjectAliveTrait<T, true> { - STATIC_ONLY(ObjectAliveTrait); - - public: - NO_SANITIZE_ADDRESS - static bool IsHeapObjectAlive(const T* object) { - static_assert(sizeof(T), "T must be fully defined"); - const HeapObjectHeader* header = HeapObjectHeader::FromPayload( - TraceTrait<T>::GetTraceDescriptor(object).base_object_payload); - DCHECK(!header->IsInConstruction() || header->IsMarked()); - return header->IsMarked(); - } -}; - -template <typename T, typename = int> -struct IsGarbageCollectedContainer : std::false_type {}; - -template <typename T> -struct IsGarbageCollectedContainer< - T, - typename T::IsGarbageCollectedCollectionTypeMarker> : std::true_type {}; - -} // namespace internal - -class PLATFORM_EXPORT ThreadHeap { - USING_FAST_MALLOC(ThreadHeap); - - using EphemeronProcessing = ThreadState::EphemeronProcessing; - - public: - explicit ThreadHeap(ThreadState*); - ~ThreadHeap(); - - MarkingWorklist* GetMarkingWorklist() const { - return marking_worklist_.get(); - } - - WriteBarrierWorklist* GetWriteBarrierWorklist() const { - return write_barrier_worklist_.get(); - } - - NotFullyConstructedWorklist* GetNotFullyConstructedWorklist() const { - return not_fully_constructed_worklist_.get(); - } - - NotFullyConstructedWorklist* GetPreviouslyNotFullyConstructedWorklist() - const { - return previously_not_fully_constructed_worklist_.get(); - } - - WeakCallbackWorklist* GetWeakCallbackWorklist() const { - return weak_callback_worklist_.get(); - } - - MovableReferenceWorklist* GetMovableReferenceWorklist() const { - return movable_reference_worklist_.get(); - } - - EphemeronPairsWorklist* GetDiscoveredEphemeronPairsWorklist() const { - return discovered_ephemeron_pairs_worklist_.get(); - } - - EphemeronPairsWorklist* GetEphemeronPairsToProcessWorklist() const { - return ephemeron_pairs_to_process_worklist_.get(); - } - - V8ReferencesWorklist* GetV8ReferencesWorklist() const { - return v8_references_worklist_.get(); - } - - NotSafeToConcurrentlyTraceWorklist* GetNotSafeToConcurrentlyTraceWorklist() - const { - return not_safe_to_concurrently_trace_worklist_.get(); - } - - WeakContainersWorklist* GetWeakContainersWorklist() const { - return weak_containers_worklist_.get(); - } - - // Register an ephemeron table for fixed-point iteration. - void RegisterWeakTable(void* container_object, EphemeronCallback); - - // Heap compaction registration methods: - - // Checks whether we need to register |addr| as a backing store or a slot - // containing reference to it. - bool ShouldRegisterMovingAddress(); - - RegionTree* GetRegionTree() { return region_tree_.get(); } - - static inline size_t AllocationSizeFromSize(size_t size) { - // Add space for header. - size_t allocation_size = size + sizeof(HeapObjectHeader); - // The allocation size calculation can overflow for large sizes. - CHECK_GT(allocation_size, size); - // Align size with allocation granularity. - allocation_size = (allocation_size + kAllocationMask) & ~kAllocationMask; - return allocation_size; - } - Address AllocateOnArenaIndex(ThreadState*, - size_t, - int arena_index, - uint32_t gc_info_index, - const char* type_name); - template <typename T> - static Address Allocate(size_t); - - void WeakProcessing(MarkingVisitor*); - - // Moves not fully constructed objects to previously not fully constructed - // objects. Such objects can be iterated using the Trace() method and do - // not need to rely on conservative handling. - void FlushNotFullyConstructedObjects(); - - // Moves ephemeron pairs from |discovered_ephemeron_pairs_worklist_| to - // |ephemeron_pairs_to_process_worklist_| - void FlushEphemeronPairs(EphemeronProcessing); - - // Marks not fully constructed objects. - void MarkNotFullyConstructedObjects(MarkingVisitor*); - // Marks the transitive closure including ephemerons. - bool AdvanceMarking(MarkingVisitor*, base::TimeTicks, EphemeronProcessing); - void VerifyMarking(); - - // Returns true if concurrent markers will have work to steal - bool HasWorkForConcurrentMarking() const; - // Returns the amount of work currently available for stealing (there could be - // work remaining even if this is 0). - size_t ConcurrentMarkingGlobalWorkSize() const; - // Returns true if marker is done - bool AdvanceConcurrentMarking(ConcurrentMarkingVisitor*, - base::JobDelegate*, - MarkingSchedulingOracle* marking_scheduler); - - // Conservatively checks whether an address is a pointer in any of the - // thread heaps. If so marks the object pointed to as live. - Address CheckAndMarkPointer(MarkingVisitor*, Address); - - // Visits remembered sets. - void VisitRememberedSets(MarkingVisitor*); - - size_t ObjectPayloadSizeForTesting(); - void ResetAllocationPointForTesting(); - - PagePool* GetFreePagePool() { return free_page_pool_.get(); } - - // This look-up uses the region search tree and a negative contains cache to - // provide an efficient mapping from arbitrary addresses to the containing - // heap-page if one exists. - BasePage* LookupPageForAddress(ConstAddress); - - HeapCompact* Compaction(); - - // Get one of the heap structures for this thread. - // The thread heap is split into multiple heap parts based on object types - // and object sizes. - BaseArena* Arena(int arena_index) const { - DCHECK_LE(0, arena_index); - DCHECK_LT(arena_index, BlinkGC::kNumberOfArenas); - return arenas_[arena_index]; - } - - static bool IsVectorArenaIndex(int arena_index) { - return BlinkGC::kVectorArenaIndex == arena_index; - } - static bool IsNormalArenaIndex(int); - - void MakeConsistentForGC(); - // MakeConsistentForMutator() drops marks from marked objects and rebuild - // free lists. This is called after taking a snapshot and before resuming - // the executions of mutators. - void MakeConsistentForMutator(); - - // Unmarks all objects in the entire heap. This is supposed to be called in - // the beginning of major GC. - void Unmark(); - - void Compact(); - - bool AdvanceLazySweep(base::TimeTicks deadline); - bool AdvanceConcurrentSweep(base::JobDelegate*); - - void PrepareForSweep(BlinkGC::CollectionType); - void RemoveAllPages(); - void InvokeFinalizersOnSweptPages(); - void CompleteSweep(); - - void CollectStatistics(ThreadState::Statistics* statistics); - - ThreadHeapStatsCollector* stats_collector() const { - return heap_stats_collector_.get(); - } - -#if defined(ADDRESS_SANITIZER) - void PoisonUnmarkedObjects(); -#endif - -#if DCHECK_IS_ON() - // Infrastructure to determine if an address is within one of the - // address ranges for the Blink heap. If the address is in the Blink - // heap the containing heap page is returned. - BasePage* FindPageFromAddress(Address); - BasePage* FindPageFromAddress(const void* pointer) { - return FindPageFromAddress( - reinterpret_cast<Address>(const_cast<void*>(pointer))); - } -#endif - - PageBloomFilter* page_bloom_filter() { return page_bloom_filter_.get(); } - - bool IsInLastAllocatedRegion(Address address) const; - void SetLastAllocatedRegion(Address start, size_t length); - - private: - struct LastAllocatedRegion { - Address start = nullptr; - size_t length = 0; - }; - - static int ArenaIndexForObjectSize(size_t); - - void SetupWorklists(bool); - void DestroyMarkingWorklists(BlinkGC::StackState); - void DestroyCompactionWorklists(); - - bool InvokeEphemeronCallbacks(EphemeronProcessing, - MarkingVisitor*, - base::TimeTicks); - - bool FlushV8References(base::TimeTicks); - - ThreadState* thread_state_; - std::unique_ptr<ThreadHeapStatsCollector> heap_stats_collector_; - std::unique_ptr<RegionTree> region_tree_; - std::unique_ptr<PageBloomFilter> page_bloom_filter_; - std::unique_ptr<PagePool> free_page_pool_; - std::unique_ptr<ProcessHeapReporter> process_heap_reporter_; - - // All objects on this worklist have been fully initialized and assigned a - // trace callback for iterating the body of the object. This worklist should - // contain almost all objects. - std::unique_ptr<MarkingWorklist> marking_worklist_; - - // Objects on this worklist have been collected in the write barrier. The - // worklist is different from |marking_worklist_| to minimize execution in the - // path where a write barrier is executed. - std::unique_ptr<WriteBarrierWorklist> write_barrier_worklist_; - - // Objects on this worklist were observed to be in construction (in their - // constructor) and thus have been delayed for processing. They have not yet - // been assigned a valid header and trace callback. - std::unique_ptr<NotFullyConstructedWorklist> not_fully_constructed_worklist_; - - // Objects on this worklist were previously in construction but have been - // moved here upon observing a safepoint, i.e., processing without stack. They - // have not yet been assigned a valid header and trace callback but are fully - // specified and can thus be iterated using the trace callback (which can be - // looked up dynamically). - std::unique_ptr<NotFullyConstructedWorklist> - previously_not_fully_constructed_worklist_; - - // Worklist of weak callbacks accumulated for objects. Such callbacks are - // processed after finishing marking objects. - std::unique_ptr<WeakCallbackWorklist> weak_callback_worklist_; - - // The worklist is to remember slots that are traced during - // marking phases. The mapping between the slots and the backing stores are - // created at the atomic pause phase. - std::unique_ptr<MovableReferenceWorklist> movable_reference_worklist_; - - // Worklist of ephemeron callbacks. Used to pass new callbacks from - // MarkingVisitor to ThreadHeap. - std::unique_ptr<EphemeronPairsWorklist> discovered_ephemeron_pairs_worklist_; - std::unique_ptr<EphemeronPairsWorklist> ephemeron_pairs_to_process_worklist_; - - // Worklist for storing the V8 references until ThreadHeap can flush them - // to V8. - std::unique_ptr<V8ReferencesWorklist> v8_references_worklist_; - - std::unique_ptr<NotSafeToConcurrentlyTraceWorklist> - not_safe_to_concurrently_trace_worklist_; - - std::unique_ptr<WeakContainersWorklist> weak_containers_worklist_; - - std::unique_ptr<HeapCompact> compaction_; - - LastAllocatedRegion last_allocated_region_; - - BaseArena* arenas_[BlinkGC::kNumberOfArenas]; - - static ThreadHeap* main_thread_heap_; - - static constexpr size_t kStepsBeforeEphemeronPairsFlush = 4u; - size_t steps_since_last_ephemeron_pairs_flush_ = 0; - static constexpr size_t kStepsBeforeEphemeronProcessing = 16u; - size_t steps_since_last_ephemeron_processing_ = 0; - - friend class incremental_marking_test::IncrementalMarkingScopeBase; - template <typename T> - friend class Member; - friend class ThreadState; -}; - -template <typename T> -class GarbageCollected { - IS_GARBAGE_COLLECTED_TYPE(); - - public: - using ParentMostGarbageCollectedType = T; - - // Must use MakeGarbageCollected. - void* operator new(size_t) = delete; - void* operator new[](size_t) = delete; - // The garbage collector is taking care of reclaiming the object. Also, - // virtual destructor requires an unambiguous, accessible 'operator delete'. - void operator delete(void*) { NOTREACHED(); } - void operator delete[](void*) = delete; - - template <typename Derived> - static void* AllocateObject(size_t size) { - return ThreadHeap::Allocate<GCInfoFoldedType<Derived>>(size); - } - - protected: - // This trait in theory can be moved to gc_info.h, but that would cause - // significant memory bloat caused by huge number of ThreadHeap::Allocate<> - // instantiations, which linker is not able to fold. - template <typename Derived> - class GCInfoFolded { - static constexpr bool is_virtual_destructor_at_base = - std::has_virtual_destructor<ParentMostGarbageCollectedType>::value; - static constexpr bool both_trivially_destructible = - std::is_trivially_destructible<ParentMostGarbageCollectedType>::value && - std::is_trivially_destructible<Derived>::value; - static constexpr bool has_custom_dispatch_at_base = - internal::HasFinalizeGarbageCollectedObject< - ParentMostGarbageCollectedType>::value; - - public: - using Type = std::conditional_t<is_virtual_destructor_at_base || - both_trivially_destructible || - has_custom_dispatch_at_base, - ParentMostGarbageCollectedType, - Derived>; - }; - - template <typename Derived> - using GCInfoFoldedType = typename GCInfoFolded<Derived>::Type; - - GarbageCollected() = default; -}; - -// Used for passing custom sizes to MakeGarbageCollected. -struct AdditionalBytes { - explicit AdditionalBytes(wtf_size_t bytes) : value(bytes) {} - const wtf_size_t value; -}; - -template <typename T> -struct MakeGarbageCollectedTrait { - template <typename... Args> - static T* Call(Args&&... args) { - static_assert(WTF::IsGarbageCollectedType<T>::value, - "T needs to be a garbage collected object"); - static_assert( - std::is_trivially_destructible<T>::value || - std::has_virtual_destructor<T>::value || std::is_final<T>::value || - internal::IsGarbageCollectedContainer<T>::value || - internal::HasFinalizeGarbageCollectedObject<T>::value, - "Finalized GarbageCollected class should either have a virtual " - "destructor or be marked as final"); - static_assert(!IsGarbageCollectedMixin<T>::value || - sizeof(T) <= kLargeObjectSizeThreshold, - "GarbageCollectedMixin may not be a large object"); - void* memory = T::template AllocateObject<T>(sizeof(T)); - HeapObjectHeader* header = HeapObjectHeader::FromPayload(memory); - // Placement new as regular operator new() is deleted. - T* object = ::new (memory) T(std::forward<Args>(args)...); - header->MarkFullyConstructed<HeapObjectHeader::AccessMode::kAtomic>(); - return object; - } - - template <typename... Args> - static T* Call(AdditionalBytes additional_bytes, Args&&... args) { - static_assert(WTF::IsGarbageCollectedType<T>::value, - "T needs to be a garbage collected object"); - static_assert( - std::is_trivially_destructible<T>::value || - std::has_virtual_destructor<T>::value || std::is_final<T>::value || - internal::IsGarbageCollectedContainer<T>::value || - internal::HasFinalizeGarbageCollectedObject<T>::value, - "Finalized GarbageCollected class should either have a virtual " - "destructor or be marked as final."); - const size_t size = sizeof(T) + additional_bytes.value; - if (IsGarbageCollectedMixin<T>::value) { - // Ban large mixin so we can use PageFromObject() on them. - CHECK_GE(kLargeObjectSizeThreshold, size) - << "GarbageCollectedMixin may not be a large object"; - } - void* memory = T::template AllocateObject<T>(size); - HeapObjectHeader* header = HeapObjectHeader::FromPayload(memory); - // Placement new as regular operator new() is deleted. - T* object = ::new (memory) T(std::forward<Args>(args)...); - header->MarkFullyConstructed<HeapObjectHeader::AccessMode::kAtomic>(); - return object; - } -}; - -template <typename T, typename = void> -struct PostConstructionHookTrait { - static void Call(T*) {} -}; - -// Default MakeGarbageCollected: Constructs an instance of T, which is a garbage -// collected type. -template <typename T, typename... Args> -T* MakeGarbageCollected(Args&&... args) { - T* object = MakeGarbageCollectedTrait<T>::Call(std::forward<Args>(args)...); - PostConstructionHookTrait<T>::Call(object); - return object; -} - -// Constructs an instance of T, which is a garbage collected type. This special -// version takes size which enables constructing inline objects. -template <typename T, typename... Args> -T* MakeGarbageCollected(AdditionalBytes additional_bytes, Args&&... args) { - T* object = MakeGarbageCollectedTrait<T>::Call(additional_bytes, - std::forward<Args>(args)...); - PostConstructionHookTrait<T>::Call(object); - return object; -} - -// Assigning class types to their arenas. -// -// We use sized arenas for most 'normal' objects to improve memory locality. -// It seems that the same type of objects are likely to be accessed together, -// which means that we want to group objects by type. That's one reason -// why we provide dedicated arenas for popular types (e.g., Node, CSSValue), -// but it's not practical to prepare dedicated arenas for all types. -// Thus we group objects by their sizes, hoping that this will approximately -// group objects by their types. -// - -inline int ThreadHeap::ArenaIndexForObjectSize(size_t size) { - if (size < 64) { - if (size < 32) - return BlinkGC::kNormalPage1ArenaIndex; - return BlinkGC::kNormalPage2ArenaIndex; - } - if (size < 128) - return BlinkGC::kNormalPage3ArenaIndex; - return BlinkGC::kNormalPage4ArenaIndex; -} - -inline bool ThreadHeap::IsNormalArenaIndex(int index) { - return index >= BlinkGC::kNormalPage1ArenaIndex && - index <= BlinkGC::kNormalPage4ArenaIndex; -} - -inline Address ThreadHeap::AllocateOnArenaIndex(ThreadState* state, - size_t size, - int arena_index, - uint32_t gc_info_index, - const char* type_name) { - DCHECK(state->IsAllocationAllowed()); - DCHECK_NE(arena_index, BlinkGC::kLargeObjectArenaIndex); - NormalPageArena* arena = static_cast<NormalPageArena*>(Arena(arena_index)); - Address address = - arena->AllocateObject(AllocationSizeFromSize(size), gc_info_index); - return address; -} - -template <typename T> -Address ThreadHeap::Allocate(size_t size) { - ThreadState* state = ThreadStateFor<ThreadingTrait<T>::kAffinity>::GetState(); - const char* type_name = WTF_HEAP_PROFILER_TYPE_NAME(T); - return state->Heap().AllocateOnArenaIndex( - state, size, ThreadHeap::ArenaIndexForObjectSize(size), - GCInfoTrait<T>::Index(), type_name); -} - -inline bool ThreadHeap::IsInLastAllocatedRegion(Address address) const { - return last_allocated_region_.start <= address && - address < - (last_allocated_region_.start + last_allocated_region_.length); -} - -inline void ThreadHeap::SetLastAllocatedRegion(Address start, size_t length) { - last_allocated_region_.start = start; - last_allocated_region_.length = length; -} - -class PLATFORM_EXPORT LivenessBroker final { - public: - template <typename T> - bool IsHeapObjectAlive(const T*) const; - template <typename T> - bool IsHeapObjectAlive(const WeakMember<T>&) const; - template <typename T> - bool IsHeapObjectAlive(const UntracedMember<T>&) const; - - private: - LivenessBroker() = default; - friend class internal::LivenessBrokerFactory; -}; - -template <typename T> -bool LivenessBroker::IsHeapObjectAlive(const T* object) const { - static_assert(sizeof(T), "T must be fully defined"); - // The strongification of collections relies on the fact that once a - // collection has been strongified, there is no way that it can contain - // non-live entries, so no entries will be removed. Since you can't set - // the mark bit on a null pointer, that means that null pointers are - // always 'alive'. - if (!object) - return true; - // TODO(keishi): some tests create CrossThreadPersistent on non attached - // threads. - if (!ThreadState::Current()) - return true; - DCHECK(&ThreadState::Current()->Heap() == - &PageFromObject(object)->Arena()->GetThreadState()->Heap()); - return internal::ObjectAliveTrait<T>::IsHeapObjectAlive(object); -} - -template <typename T> -bool LivenessBroker::IsHeapObjectAlive(const WeakMember<T>& weak_member) const { - return IsHeapObjectAlive(weak_member.Get()); -} - -template <typename T> -bool LivenessBroker::IsHeapObjectAlive( - const UntracedMember<T>& untraced_member) const { - return IsHeapObjectAlive(untraced_member.Get()); -} - -template <typename T> -void Visitor::HandleWeakCell(const LivenessBroker& broker, const void* object) { - WeakMember<T>* weak_member = - reinterpret_cast<WeakMember<T>*>(const_cast<void*>(object)); - if (weak_member->Get()) { - if (weak_member->IsHashTableDeletedValue()) { - // This can happen when weak fields are deleted while incremental marking - // is running. Deleted values need to be preserved to avoid reviving - // objects in containers. - return; - } - if (!broker.IsHeapObjectAlive(weak_member->Get())) - weak_member->Clear(); - } -} - -namespace internal { - -class LivenessBrokerFactory final { - public: - static LivenessBroker Create() { return LivenessBroker(); } -}; - -} // namespace internal - -#if DCHECK_IS_ON() -static constexpr bool kBlinkGCHasDebugChecks = true; -#else -static constexpr bool kBlinkGCHasDebugChecks = false; -#endif // DCHECK_IS_ON() - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_HEAP_H_
diff --git a/third_party/blink/renderer/platform/heap/impl/heap_allocator_impl.cc b/third_party/blink/renderer/platform/heap/impl/heap_allocator_impl.cc deleted file mode 100644 index 8f690a3..0000000 --- a/third_party/blink/renderer/platform/heap/impl/heap_allocator_impl.cc +++ /dev/null
@@ -1,131 +0,0 @@ -// Copyright 2021 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/heap/impl/heap_allocator_impl.h" - -namespace blink { - -namespace { - -struct BackingModifier { - bool can_modify; - BasePage* const page; - HeapObjectHeader* const header; -}; - -BackingModifier CanModifyBacking(ThreadState* const state, void* address) { - // - |SweepForbidden| protects against modifying objects from destructors. - // - |IsSweepingInProgress| protects against modifying objects while - // concurrent sweeping is in progress. - // - |in_atomic_pause| protects against modifying objects from within the GC. - // This can - // e.g. happen when hash table buckets that have containers inlined are - // freed during weakness processing. - // - |IsMarkingInProgress| protects against incremental marking which may have - // registered callbacks. - if (state->SweepForbidden() || state->IsSweepingInProgress() || - state->in_atomic_pause() || state->IsMarkingInProgress()) - return {false, nullptr, nullptr}; - - // - Don't adjust large objects because their page is never reused. - // - Don't free backings allocated on other threads. - BasePage* page = PageFromObject(address); - if (page->IsLargeObjectPage() || page->Arena()->GetThreadState() != state) - return {false, nullptr, nullptr}; - - HeapObjectHeader* const header = HeapObjectHeader::FromPayload(address); - // - Guards against pages that have not been swept. Technically, it should be - // fine to modify those backings. We bail out to maintain the invariant that - // no marked backing is modified. - if (header->IsMarked()) - return {false, nullptr, nullptr}; - return {true, page, header}; -} - -} // namespace - -void HeapAllocator::BackingFree(void* address) { - if (!address) - return; - - ThreadState* const state = ThreadState::Current(); - BackingModifier result = CanModifyBacking(state, address); - if (!result.can_modify) - return; - - static_cast<NormalPage*>(result.page) - ->ArenaForNormalPage() - ->PromptlyFreeObject(result.header); -} - -void HeapAllocator::FreeVectorBacking(void* address) { - BackingFree(address); -} - -bool HeapAllocator::BackingExpand(void* address, size_t new_size) { - if (!address) - return false; - - ThreadState* state = ThreadState::Current(); - - BackingModifier result = CanModifyBacking(state, address); - if (!result.can_modify) - return false; - DCHECK(!state->in_atomic_pause()); - DCHECK(state->IsAllocationAllowed()); - DCHECK_EQ(&state->Heap(), &ThreadState::FromObject(address)->Heap()); - - // FIXME: Support expand for large objects. - // Don't expand backings allocated on other threads. - BasePage* page = PageFromObject(address); - if (page->IsLargeObjectPage() || page->Arena()->GetThreadState() != state) - return false; - - HeapObjectHeader* header = HeapObjectHeader::FromPayload(address); - NormalPageArena* arena = static_cast<NormalPage*>(page)->ArenaForNormalPage(); - return arena->ExpandObject(header, new_size); -} - -bool HeapAllocator::ExpandVectorBacking(void* address, size_t new_size) { - return BackingExpand(address, new_size); -} - -bool HeapAllocator::BackingShrink(void* address, - size_t quantized_current_size, - size_t quantized_shrunk_size) { - if (!address || quantized_shrunk_size == quantized_current_size) - return true; - - DCHECK_LT(quantized_shrunk_size, quantized_current_size); - - ThreadState* const state = ThreadState::Current(); - BackingModifier result = CanModifyBacking(state, address); - if (!result.can_modify) - return false; - - DCHECK(state->IsAllocationAllowed()); - DCHECK_EQ(&state->Heap(), &ThreadState::FromObject(address)->Heap()); - - NormalPageArena* arena = - static_cast<NormalPage*>(result.page)->ArenaForNormalPage(); - // We shrink the object only if the shrinking will make a non-small - // prompt-free block. - // FIXME: Optimize the threshold size. - if (quantized_current_size <= quantized_shrunk_size + - sizeof(HeapObjectHeader) + - sizeof(void*) * 32 && - !arena->IsObjectAllocatedAtAllocationPoint(result.header)) - return true; - - arena->ShrinkObject(result.header, quantized_shrunk_size); - return true; -} - -bool HeapAllocator::ShrinkVectorBacking(void* address, - size_t quantized_current_size, - size_t quantized_shrunk_size) { - return BackingShrink(address, quantized_current_size, quantized_shrunk_size); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/impl/heap_allocator_impl.h b/third_party/blink/renderer/platform/heap/impl/heap_allocator_impl.h deleted file mode 100644 index d58dc394..0000000 --- a/third_party/blink/renderer/platform/heap/impl/heap_allocator_impl.h +++ /dev/null
@@ -1,184 +0,0 @@ -// Copyright 2015 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. - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_HEAP_ALLOCATOR_IMPL_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_HEAP_ALLOCATOR_IMPL_H_ - -#include "build/build_config.h" -#include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_table_backing.h" -#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector_backing.h" -#include "third_party/blink/renderer/platform/heap/impl/heap.h" -#include "third_party/blink/renderer/platform/heap/impl/marking_visitor.h" -#include "third_party/blink/renderer/platform/heap/impl/trace_traits.h" -#include "third_party/blink/renderer/platform/wtf/type_traits.h" - -namespace blink { - -// This is a static-only class used as a trait on collections to make them heap -// allocated. -class PLATFORM_EXPORT HeapAllocator { - STATIC_ONLY(HeapAllocator); - - public: - using LivenessBroker = blink::LivenessBroker; - using Visitor = blink::Visitor; - static constexpr bool kIsGarbageCollected = true; - - // See wtf/size_t.h for details. - static constexpr size_t kMaxHeapObjectSizeLog2 = 27; - static constexpr size_t kMaxHeapObjectSize = 1 << kMaxHeapObjectSizeLog2; - - template <typename T> - static size_t MaxElementCountInBackingStore() { - return kMaxHeapObjectSize / sizeof(T); - } - - template <typename T> - static size_t QuantizedSize(size_t count) { - CHECK_LE(count, MaxElementCountInBackingStore<T>()); - // Oilpan's internal size is independent of MaxElementCountInBackingStore() - // and the required size to match capacity needs. - return count * sizeof(T); - } - - template <typename T> - static T* AllocateVectorBacking(size_t size) { - return reinterpret_cast<T*>( - MakeGarbageCollected<HeapVectorBacking<T>>(size / sizeof(T))); - } - static void FreeVectorBacking(void*); - static bool ExpandVectorBacking(void*, size_t); - static bool ShrinkVectorBacking(void* address, - size_t quantized_current_size, - size_t quantized_shrunk_size); - - template <typename T, typename HashTable> - static T* AllocateHashTableBacking(size_t size) { - static_assert(sizeof(T) == sizeof(typename HashTable::ValueType), - "T must match ValueType."); - return reinterpret_cast<T*>( - MakeGarbageCollected<HeapHashTableBacking<HashTable>>(size / - sizeof(T))); - } - template <typename T, typename HashTable> - static T* AllocateZeroedHashTableBacking(size_t size) { - return AllocateHashTableBacking<T, HashTable>(size); - } - template <typename T, typename HashTable> - static void FreeHashTableBacking(void* address) { - BackingFree(address); - } - template <typename T, typename HashTable> - static bool ExpandHashTableBacking(T* address, size_t new_size) { - return BackingExpand(address, new_size); - } - - template <typename Traits> - static bool CanReuseHashTableDeletedBucket() { - if (Traits::kEmptyValueIsZero || !Traits::kCanTraceConcurrently) - return true; - return !ThreadState::Current()->IsMarkingInProgress(); - } - - static bool IsAllocationAllowed() { - return ThreadState::Current()->IsAllocationAllowed(); - } - - static bool IsIncrementalMarking() { - return ThreadState::IsAnyIncrementalMarking() && - ThreadState::Current()->IsIncrementalMarking(); - } - - static void EnterGCForbiddenScope() { - ThreadState::Current()->EnterGCForbiddenScope(); - } - - static void LeaveGCForbiddenScope() { - ThreadState::Current()->LeaveGCForbiddenScope(); - } - - template <typename T, typename Traits> - static void Trace(Visitor* visitor, const T& t) { - TraceCollectionIfEnabled<WTF::WeakHandlingTrait<T>::value, T, - Traits>::Trace(visitor, &t); - } - - template <typename T> - static void TraceVectorBacking(Visitor* visitor, - const T* backing, - const T* const* backing_slot) { - visitor->TraceMovablePointer(backing_slot); - visitor->Trace(reinterpret_cast<const HeapVectorBacking<T>*>(backing)); - } - - template <typename T, typename HashTable> - static void TraceHashTableBackingStrongly(Visitor* visitor, - const T* backing, - const T* const* backing_slot) { - visitor->TraceMovablePointer(backing_slot); - visitor->Trace( - reinterpret_cast<const HeapHashTableBacking<HashTable>*>(backing)); - } - - template <typename T, typename HashTable> - static void TraceHashTableBackingWeakly(Visitor* visitor, - const T* backing, - const T* const* backing_slot, - WeakCallback callback, - const void* parameter) { - visitor->TraceMovablePointer(backing_slot); - visitor->TraceWeakContainer( - reinterpret_cast<const HeapHashTableBacking<HashTable>*>(backing), - reinterpret_cast<const HeapHashTableBacking<HashTable>* const*>( - backing_slot), - TraceTrait<HeapHashTableBacking<HashTable>>::GetTraceDescriptor( - backing), - TraceTrait<HeapHashTableBacking<HashTable>>::GetWeakTraceDescriptor( - backing), - callback, parameter); - } - - template <typename T> - static void BackingWriteBarrier(T** slot) { - MarkingVisitor::WriteBarrier(reinterpret_cast<void**>(slot)); - } - - template <typename T> - static void TraceBackingStoreIfMarked(T* object) { - MarkingVisitor::RetraceObject(object); - } - - template <typename T, typename Traits> - static void NotifyNewObject(T* object) { - MarkingVisitor::WriteBarrier( - []() { return ThreadState::Current(); }, object, sizeof(T), 1, - TraceCollectionIfEnabled<WTF::kNoWeakHandling, T, Traits>::Trace); - } - - template <typename T, typename Traits> - static void NotifyNewObjects(T* array, size_t len) { - MarkingVisitor::WriteBarrier( - []() { return ThreadState::Current(); }, array, sizeof(T), len, - TraceCollectionIfEnabled<WTF::kNoWeakHandling, T, Traits>::Trace); - } - - static bool DeferTraceToMutatorThreadIfConcurrent(Visitor* visitor, - const void* object, - TraceCallback callback, - size_t deferred_size) { - return visitor->DeferredTraceIfConcurrent({object, callback}, - deferred_size); - } - - private: - static void BackingFree(void*); - static bool BackingExpand(void*, size_t); - static bool BackingShrink(void*, - size_t quantized_current_size, - size_t quantized_shrunk_size); -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_HEAP_ALLOCATOR_IMPL_H_
diff --git a/third_party/blink/renderer/platform/heap/impl/heap_compact.cc b/third_party/blink/renderer/platform/heap/impl/heap_compact.cc deleted file mode 100644 index 1a5cf4c..0000000 --- a/third_party/blink/renderer/platform/heap/impl/heap_compact.cc +++ /dev/null
@@ -1,456 +0,0 @@ -// Copyright 2016 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/heap/impl/heap_compact.h" - -#include <memory> - -#include "base/debug/alias.h" -#include "base/memory/ptr_util.h" -#include "third_party/blink/public/common/features.h" -#include "third_party/blink/renderer/platform/heap/heap.h" -#include "third_party/blink/renderer/platform/heap/heap_stats_collector.h" -#include "third_party/blink/renderer/platform/instrumentation/histogram.h" -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" -#include "third_party/blink/renderer/platform/wtf/hash_map.h" - -namespace blink { - -// The real worker behind heap compaction, recording references to movable -// objects ("slots".) When the objects end up being compacted and moved, -// relocate() will adjust the slots to point to the new location of the -// object along with handling fixups for interior pointers. -// -// The "fixups" object is created and maintained for the lifetime of one -// heap compaction-enhanced GC. -class HeapCompact::MovableObjectFixups final { - USING_FAST_MALLOC(HeapCompact::MovableObjectFixups); - - public: - explicit MovableObjectFixups(ThreadHeap* heap) : heap_(heap) {} - ~MovableObjectFixups() = default; - - // For the arenas being compacted, record all pages belonging to them. - // This is needed to handle interior pointers that reside on areas that are - // compacted themselves. - void AddCompactingPage(BasePage* page); - - // Adds a slot for compaction. Filters slots in dead objects. - void AddOrFilter(const MovableReference*); - - // Relocates a backing store |from| -> |to|. - void Relocate(Address from, Address to); - - // Relocates interior slots in a backing store that is moved |from| -> |to|. - void RelocateInteriorFixups(Address from, Address to, size_t size); - - // Updates the collection of callbacks from the item pushed the worklist by - // marking visitors. - void UpdateCallbacks(); - -#if DEBUG_HEAP_COMPACTION - void dumpDebugStats() { - LOG_HEAP_COMPACTION() << "Fixups: pages=" << relocatable_pages_.size() - << " objects=" << fixups_.size() - << " interior-size=" << interior_fixups_.size(); - } -#endif - - private: - void VerifyUpdatedSlot(MovableReference* slot); - - ThreadHeap* const heap_; - - // Map from movable reference (value) to its slots. Upon moving an object its - // slot pointing to it requires updating. - HashMap<MovableReference, MovableReference*> fixups_; - - // Map of interior slots to their final location. Needs to be an ordered map - // as it is used to walk through slots starting at a given memory address. - // Requires log(n) lookup to make the early bailout reasonably fast. Currently - // only std::map fullfills those requirements. - // - // - The initial value for a given key is nullptr. - // - Upon moving a an object this value is adjusted accordingly. - std::map<MovableReference*, Address> interior_fixups_; - - // All pages that are being compacted. The set keeps references to - // BasePage instances. The void* type was selected to allow to check - // arbitrary addresses. - HashSet<void*> relocatable_pages_; - -#if DCHECK_IS_ON() - // The following two collections are used to allow refer back from a slot to - // an already moved object. - HashSet<const void*> moved_objects_; - HashMap<MovableReference*, MovableReference> interior_slot_to_object_; -#endif // DCHECK_IS_ON() -}; - -void HeapCompact::MovableObjectFixups::AddCompactingPage(BasePage* page) { - DCHECK(!page->IsLargeObjectPage()); - relocatable_pages_.insert(page); -} - -void HeapCompact::MovableObjectFixups::AddOrFilter( - const MovableReference* const_slot) { - const void* value = *const_slot; - CHECK(value); - - // All slots and values are part of Oilpan's heap. - // - Slots may be contained within dead objects if e.g. the write barrier - // registered the slot while the out backing itself has not been marked - // live in time. Slots in dead objects are filtered below. - // - Values may only be contained in or point to live objects. - - // Slots handling. - BasePage* const slot_page = - heap_->LookupPageForAddress(reinterpret_cast<ConstAddress>(const_slot)); - CHECK(slot_page); - HeapObjectHeader* const header = - slot_page->IsLargeObjectPage() - ? static_cast<LargeObjectPage*>(slot_page)->ObjectHeader() - : static_cast<NormalPage*>(slot_page)->FindHeaderFromAddress( - reinterpret_cast<ConstAddress>(const_slot)); - CHECK(header); - // Filter the slot since the object that contains the slot is dead. - if (!header->IsMarked()) - return; - - // Value handling. - BasePage* const value_page = - heap_->LookupPageForAddress(reinterpret_cast<ConstAddress>(value)); - CHECK(value_page); - - // The following cases are not compacted and do not require recording: - // - Backings in large pages. - // - Inline backings that are part of a non-backing arena. - if (value_page->IsLargeObjectPage() || - !HeapCompact::IsCompactableArena(value_page->Arena()->ArenaIndex())) - return; - - // Slots must reside in and values must point to live objects at this - // point, with the exception of slots in eagerly swept arenas where objects - // have already been processed. |value| usually points to a separate - // backing store but can also point to inlined storage which is why the - // dynamic header lookup is required. - HeapObjectHeader* const value_header = - static_cast<NormalPage*>(value_page) - ->FindHeaderFromAddress(reinterpret_cast<ConstAddress>(value)); - CHECK(value_header); - CHECK(value_header->IsMarked()); - - // Slots may have been recorded already but must point to the same - // value. Example: Ephemeron iterations may register slots multiple - // times. - auto fixup_it = fixups_.find(value); - if (UNLIKELY(fixup_it != fixups_.end())) { - CHECK_EQ(const_slot, fixup_it->value); - return; - } - - // Add regular fixup. - MovableReference* slot = const_cast<MovableReference*>(const_slot); - fixups_.insert(value, slot); - - // Check whether the slot itself resides on a page that is compacted. - if (LIKELY(!relocatable_pages_.Contains(slot_page))) - return; - - auto interior_it = interior_fixups_.find(slot); - CHECK(interior_fixups_.end() == interior_it); - interior_fixups_.emplace(slot, nullptr); -#if DCHECK_IS_ON() - interior_slot_to_object_.insert(slot, header->Payload()); -#endif // DCHECK_IS_ON() - LOG_HEAP_COMPACTION() << "Interior slot: " << slot; -} - -void HeapCompact::MovableObjectFixups::Relocate(Address from, Address to) { -#if DCHECK_IS_ON() - moved_objects_.insert(from); -#endif // DCHECK_IS_ON() - - const HeapObjectHeader* header = HeapObjectHeader::FromPayload(to); - const size_t size = header->PayloadSize(); - - // Interior slots always need to be processed for moved objects. - // Consider an object A with slot A.x pointing to value B where A is - // allocated on a movable page itself. When B is finally moved, it needs to - // find the corresponding slot A.x. Object A may be moved already and the - // memory may have been freed, which would result in a crash. - if (!interior_fixups_.empty()) { - RelocateInteriorFixups(from, to, size); - } - - auto it = fixups_.find(from); - // This means that there is no corresponding slot for a live backing store. - // This may happen because a mutator may change the slot to point to a - // different backing store because e.g. incremental marking marked a backing - // store as live that was later on replaced. - if (it == fixups_.end()) { - return; - } - -#if DCHECK_IS_ON() - BasePage* from_page = PageFromObject(from); - DCHECK(relocatable_pages_.Contains(from_page)); -#endif - - // If the object is referenced by a slot that is contained on a compacted - // area itself, check whether it can be updated already. - MovableReference* slot = it->value; - auto interior_it = interior_fixups_.find(slot); - if (interior_it != interior_fixups_.end()) { - MovableReference* slot_location = - reinterpret_cast<MovableReference*>(interior_it->second); - if (!slot_location) { - interior_it->second = to; -#if DCHECK_IS_ON() - // Check that the containing object has not been moved yet. - auto reverse_it = interior_slot_to_object_.find(slot); - DCHECK(interior_slot_to_object_.end() != reverse_it); - DCHECK(moved_objects_.end() == moved_objects_.find(reverse_it->value)); -#endif // DCHECK_IS_ON() - } else { - LOG_HEAP_COMPACTION() - << "Redirected slot: " << slot << " => " << slot_location; - slot = slot_location; - } - } - - // If the slot has subsequently been updated, e.g. a destructor having - // mutated and expanded/shrunk the collection, do not update and relocate - // the slot -- |from| is no longer valid and referenced. - if (UNLIKELY(*slot != from)) { - LOG_HEAP_COMPACTION() << "No relocation: slot = " << slot - << ", *slot = " << *slot << ", from = " << from - << ", to = " << to; - VerifyUpdatedSlot(slot); - return; - } - - // Update the slots new value. - *slot = to; -} - -void HeapCompact::MovableObjectFixups::RelocateInteriorFixups(Address from, - Address to, - size_t size) { - // |from| is a valid address for a slot. - auto interior_it = - interior_fixups_.lower_bound(reinterpret_cast<MovableReference*>(from)); - if (interior_it == interior_fixups_.end()) - return; - - CHECK_GE(reinterpret_cast<Address>(interior_it->first), from); - size_t offset = reinterpret_cast<Address>(interior_it->first) - from; - while (offset < size) { - if (!interior_it->second) { - // Update the interior fixup value, so that when the object the slot is - // pointing to is moved, it can re-use this value. - Address fixup = to + offset; - interior_it->second = fixup; - - // If the |slot|'s content is pointing into the region [from, from + - // size) we are dealing with an interior pointer that does not point to - // a valid HeapObjectHeader. Such references need to be fixed up - // immediately. - Address fixup_contents = *reinterpret_cast<Address*>(fixup); - if (fixup_contents > from && fixup_contents < (from + size)) { - *reinterpret_cast<Address*>(fixup) = fixup_contents - from + to; - } - } - - interior_it++; - if (interior_it == interior_fixups_.end()) - return; - offset = reinterpret_cast<Address>(interior_it->first) - from; - } -} - -void HeapCompact::MovableObjectFixups::VerifyUpdatedSlot( - MovableReference* slot) { -// Verify that the already updated slot is valid, meaning: -// - has been cleared. -// - has been updated & expanded with a large object backing store. -// - has been updated with a larger, freshly allocated backing store. -// (on a fresh page in a compactable arena that is not being -// compacted.) -#if DCHECK_IS_ON() - if (!*slot) - return; - BasePage* slot_page = - heap_->LookupPageForAddress(reinterpret_cast<ConstAddress>(*slot)); - // ref_page is null if *slot is pointing to an off-heap region. This may - // happy if *slot is pointing to an inline buffer of HeapVector with - // inline capacity. - if (!slot_page) - return; - DCHECK(slot_page->IsLargeObjectPage() || - (HeapCompact::IsCompactableArena(slot_page->Arena()->ArenaIndex()) && - !relocatable_pages_.Contains(slot_page))); -#endif // DCHECK_IS_ON() -} - -HeapCompact::HeapCompact(ThreadHeap* heap) : heap_(heap) { - // The heap compaction implementation assumes the contiguous range, - // - // [VectorArenaIndex, HashTableArenaIndex] - // - // in a few places. Use static asserts here to not have that assumption - // be silently invalidated by ArenaIndices changes. - static_assert(BlinkGC::kVectorArenaIndex + 1 == BlinkGC::kHashTableArenaIndex, - "unexpected ArenaIndices ordering"); -} - -HeapCompact::~HeapCompact() = default; - -HeapCompact::MovableObjectFixups& HeapCompact::Fixups() { - if (!fixups_) - fixups_ = std::make_unique<MovableObjectFixups>(heap_); - return *fixups_; -} - -bool HeapCompact::ShouldCompact(BlinkGC::StackState stack_state, - BlinkGC::MarkingType marking_type, - BlinkGC::GCReason reason) { - if (marking_type == BlinkGC::MarkingType::kAtomicMarking && - stack_state == BlinkGC::StackState::kHeapPointersOnStack) { - // The following check ensures that tests that want to test compaction are - // not interrupted by garbage collections that cannot use compaction. - CHECK(!force_for_next_gc_); - return false; - } - - UpdateHeapResidency(); - - if (force_for_next_gc_) { - return true; - } - - if (!base::FeatureList::IsEnabled(blink::features::kBlinkHeapCompaction)) { - return false; - } - - // Only enable compaction when in a memory reduction garbage collection as it - // may significantly increase the final garbage collection pause. - if (reason == BlinkGC::GCReason::kUnifiedHeapForMemoryReductionGC || - reason == BlinkGC::GCReason::kUnifiedHeapForcedForTestingGC) { - return free_list_size_ > kFreeListSizeThreshold; - } - - return false; -} - -void HeapCompact::Initialize(ThreadState* state) { - CHECK(force_for_next_gc_ || - base::FeatureList::IsEnabled(blink::features::kBlinkHeapCompaction)); - CHECK(!do_compact_); - CHECK(!fixups_); - LOG_HEAP_COMPACTION() << "Compacting: free=" << free_list_size_; - do_compact_ = true; - gc_count_since_last_compaction_ = 0; - force_for_next_gc_ = false; -} - -bool HeapCompact::ShouldRegisterMovingAddress() { - return do_compact_; -} - -void HeapCompact::UpdateHeapResidency() { - size_t total_free_list_size = 0; - - compactable_arenas_ = 0; -#if DEBUG_HEAP_FREELIST - std::stringstream stream; - size_t total_arena_size = 0; -#endif - for (int i = BlinkGC::kVectorArenaIndex; i <= BlinkGC::kHashTableArenaIndex; - ++i) { - NormalPageArena* arena = static_cast<NormalPageArena*>(heap_->Arena(i)); - size_t arena_size = arena->ArenaSize(); - size_t free_list_size = arena->FreeListSize(); - total_free_list_size += free_list_size; -#if DEBUG_HEAP_FREELIST - total_arena_size += arena_size; - stream << i << ": [" << arena_size << ", " << free_list_size << "], "; -#endif - // TODO: be more discriminating and consider arena - // load factor, effectiveness of past compactions etc. - if (!arena_size) - continue; - // Mark the arena as compactable. - compactable_arenas_ |= 0x1u << i; - } -#if DEBUG_HEAP_FREELIST - LOG_HEAP_FREELIST() << "Arena residencies: {" << stream.str() << "}"; - LOG_HEAP_FREELIST() << "Total = " << total_arena_size - << ", Free = " << total_free_list_size; -#endif - - // TODO(sof): consider smoothing the reported sizes. - free_list_size_ = total_free_list_size; -} - -void HeapCompact::FinishedArenaCompaction(NormalPageArena* arena, - size_t freed_pages, - size_t freed_size) { - if (!do_compact_) - return; - - heap_->stats_collector()->IncreaseCompactionFreedPages(freed_pages); - heap_->stats_collector()->IncreaseCompactionFreedSize(freed_size); -} - -void HeapCompact::Relocate(Address from, Address to) { - Fixups().Relocate(from, to); -} - -void HeapCompact::FilterNonLiveSlots() { - if (!do_compact_) - return; - - last_fixup_count_for_testing_ = 0; - MovableReferenceWorklist::View traced_slots( - heap_->GetMovableReferenceWorklist(), WorklistTaskId::MutatorThread); - const MovableReference* slot; - while (traced_slots.Pop(&slot)) { - CHECK(heap_->LookupPageForAddress(reinterpret_cast<ConstAddress>(slot))); - if (*slot) { - Fixups().AddOrFilter(slot); - last_fixup_count_for_testing_++; - } - } -} - -void HeapCompact::Finish() { - if (!do_compact_) - return; - -#if DEBUG_HEAP_COMPACTION - if (fixups_) - fixups_->dumpDebugStats(); -#endif - do_compact_ = false; - fixups_.reset(); -} - -void HeapCompact::Cancel() { - if (!do_compact_) - return; - - last_fixup_count_for_testing_ = 0; - do_compact_ = false; - heap_->GetMovableReferenceWorklist()->Clear(); - fixups_.reset(); -} - -void HeapCompact::AddCompactingPage(BasePage* page) { - DCHECK(do_compact_); - DCHECK(IsCompactingArena(page->Arena()->ArenaIndex())); - Fixups().AddCompactingPage(page); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/impl/heap_compact.h b/third_party/blink/renderer/platform/heap/impl/heap_compact.h deleted file mode 100644 index e39c9c5..0000000 --- a/third_party/blink/renderer/platform/heap/impl/heap_compact.h +++ /dev/null
@@ -1,167 +0,0 @@ -// Copyright 2016 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. - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_HEAP_COMPACT_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_HEAP_COMPACT_H_ - -#include <memory> - -#include "base/memory/ptr_util.h" -#include "third_party/blink/renderer/platform/heap/blink_gc.h" -#include "third_party/blink/renderer/platform/platform_export.h" -#include "third_party/blink/renderer/platform/wtf/hash_map.h" -#include "third_party/blink/renderer/platform/wtf/hash_set.h" -#include "third_party/blink/renderer/platform/wtf/threading_primitives.h" - -#include <bitset> -#include <utility> - -// Compaction-specific debug switches: - -// Emit debug info during compaction. -#define DEBUG_HEAP_COMPACTION 0 - -// Emit stats on freelist occupancy. -// 0 - disabled, 1 - minimal, 2 - verbose. -#define DEBUG_HEAP_FREELIST 0 - -namespace blink { - -class NormalPageArena; -class BasePage; -class ThreadState; -class ThreadHeap; - -class PLATFORM_EXPORT HeapCompact final { - public: - // Returns |true| if the ongoing GC may compact the given arena/sub-heap. - static bool IsCompactableArena(int arena_index) { - return arena_index >= BlinkGC::kVectorArenaIndex && - arena_index <= BlinkGC::kHashTableArenaIndex; - } - - explicit HeapCompact(ThreadHeap*); - ~HeapCompact(); - - // Returns true if compaction can and should be used for the provided - // parameters. - bool ShouldCompact(BlinkGC::StackState, - BlinkGC::MarkingType, - BlinkGC::GCReason); - - // Compaction should be performed as part of the ongoing GC, initialize - // the heap compaction pass. - void Initialize(ThreadState*); - - // Returns true if the ongoing GC will perform compaction. - bool IsCompacting() const { return do_compact_; } - - // Returns true if the ongoing GC will perform compaction for the given - // heap arena. - bool IsCompactingArena(int arena_index) const { - return do_compact_ && (compactable_arenas_ & (0x1u << arena_index)); - } - - // See |Heap::ShouldRegisterMovingAddress()| documentation. - bool ShouldRegisterMovingAddress(); - - // Slots that are not contained within live objects are filtered. This can - // happen when the write barrier for in-payload objects triggers but the outer - // backing store does not survive the marking phase because all its referents - // die before being reached by the marker. - void FilterNonLiveSlots(); - - // Finishes compaction and clears internal state. - void Finish(); - - // Cancels compaction after slots may have been recorded already. - void Cancel(); - - // Perform any relocation post-processing after having completed compacting - // the given arena. The number of pages that were freed together with the - // total size (in bytes) of freed heap storage, are passed in as arguments. - void FinishedArenaCompaction(NormalPageArena*, - size_t freed_pages, - size_t freed_size); - - // Register the heap page as containing live objects that will all be - // compacted. Registration happens as part of making the arenas ready - // for a GC. - void AddCompactingPage(BasePage*); - - // Notify heap compaction that object at |from| has been relocated to.. |to|. - // (Called by the sweep compaction pass.) - void Relocate(Address from, Address to); - - // Enables compaction for the next garbage collection if technically possible. - void EnableCompactionForNextGCForTesting() { force_for_next_gc_ = true; } - - // Returns true if one or more vector arenas are being compacted. - bool IsCompactingVectorArenasForTesting() const { - return IsCompactingArena(BlinkGC::kVectorArenaIndex); - } - - size_t LastFixupCountForTesting() const { - return last_fixup_count_for_testing_; - } - - private: - class MovableObjectFixups; - - // Freelist size threshold that must be exceeded before compaction - // should be considered. - static const size_t kFreeListSizeThreshold = 512 * 1024; - - // Sample the amount of fragmentation and heap memory currently residing - // on the freelists of the arenas we're able to compact. The computed - // numbers will be subsequently used to determine if a heap compaction - // is on order (shouldCompact().) - void UpdateHeapResidency(); - - MovableObjectFixups& Fixups(); - - ThreadHeap* const heap_; - std::unique_ptr<MovableObjectFixups> fixups_; - - // Set to |true| when a compacting sweep will go ahead. - bool do_compact_ = false; - size_t gc_count_since_last_compaction_ = 0; - - // Last reported freelist size, across all compactable arenas. - size_t free_list_size_ = 0; - - // If compacting, i'th heap arena will be compacted if corresponding bit is - // set. Indexes are in the range of BlinkGC::ArenaIndices. - unsigned compactable_arenas_ = 0u; - - size_t last_fixup_count_for_testing_ = 0; - - bool force_for_next_gc_ = false; -}; - -} // namespace blink - -// Logging macros activated by debug switches. - -#define LOG_HEAP_COMPACTION_INTERNAL() DLOG(INFO) - -#if DEBUG_HEAP_COMPACTION -#define LOG_HEAP_COMPACTION() LOG_HEAP_COMPACTION_INTERNAL() -#else -#define LOG_HEAP_COMPACTION() EAT_STREAM_PARAMETERS -#endif - -#if DEBUG_HEAP_FREELIST -#define LOG_HEAP_FREELIST() LOG_HEAP_COMPACTION_INTERNAL() -#else -#define LOG_HEAP_FREELIST() EAT_STREAM_PARAMETERS -#endif - -#if DEBUG_HEAP_FREELIST == 2 -#define LOG_HEAP_FREELIST_VERBOSE() LOG_HEAP_COMPACTION_INTERNAL() -#else -#define LOG_HEAP_FREELIST_VERBOSE() EAT_STREAM_PARAMETERS -#endif - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_HEAP_COMPACT_H_
diff --git a/third_party/blink/renderer/platform/heap/impl/heap_page.cc b/third_party/blink/renderer/platform/heap/impl/heap_page.cc deleted file mode 100644 index 96f3b88..0000000 --- a/third_party/blink/renderer/platform/heap/impl/heap_page.cc +++ /dev/null
@@ -1,1931 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "third_party/blink/renderer/platform/heap/impl/heap_page.h" - -#include "base/allocator/partition_allocator/page_allocator.h" -#include "base/auto_reset.h" -#include "base/trace_event/process_memory_dump.h" -#include "third_party/blink/public/platform/platform.h" -#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h" -#include "third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider.h" -#include "third_party/blink/renderer/platform/heap/heap_stats_collector.h" -#include "third_party/blink/renderer/platform/heap/impl/heap_compact.h" -#include "third_party/blink/renderer/platform/heap/impl/marking_verifier.h" -#include "third_party/blink/renderer/platform/heap/impl/page_bloom_filter.h" -#include "third_party/blink/renderer/platform/heap/impl/page_memory.h" -#include "third_party/blink/renderer/platform/heap/impl/page_pool.h" -#include "third_party/blink/renderer/platform/heap/thread_state.h" -#include "third_party/blink/renderer/platform/instrumentation/histogram.h" -#include "third_party/blink/renderer/platform/instrumentation/memory_pressure_listener.h" -#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h" -#include "third_party/blink/renderer/platform/instrumentation/tracing/web_memory_allocator_dump.h" -#include "third_party/blink/renderer/platform/instrumentation/tracing/web_process_memory_dump.h" -#include "third_party/blink/renderer/platform/wtf/allocator/partitions.h" -#include "third_party/blink/renderer/platform/wtf/container_annotations.h" -#include "third_party/blink/renderer/platform/wtf/leak_annotations.h" - -#ifdef ANNOTATE_CONTIGUOUS_CONTAINER - -// When finalizing a non-inlined vector backing store/container, remove -// its contiguous container annotation. Required as it will not be destructed -// from its Vector. -#define ASAN_RETIRE_CONTAINER_ANNOTATION(object, objectSize) \ - do { \ - BasePage* page = PageFromObject(object); \ - DCHECK(page); \ - bool is_container = \ - ThreadHeap::IsVectorArenaIndex(page->Arena()->ArenaIndex()); \ - if (!is_container && page->IsLargeObjectPage()) \ - is_container = \ - static_cast<LargeObjectPage*>(page)->IsVectorBackingPage(); \ - if (is_container) \ - ANNOTATE_DELETE_BUFFER(object, objectSize, 0); \ - } while (0) - -// A vector backing store represented by a large object is marked -// so that when it is finalized, its ASan annotation will be -// correctly retired. -#define ASAN_MARK_LARGE_VECTOR_CONTAINER(arena, large_object) \ - if (ThreadHeap::IsVectorArenaIndex(arena->ArenaIndex())) { \ - BasePage* large_page = PageFromObject(large_object); \ - DCHECK(large_page->IsLargeObjectPage()); \ - static_cast<LargeObjectPage*>(large_page)->SetIsVectorBackingPage(); \ - } -#else -#define ASAN_RETIRE_CONTAINER_ANNOTATION(payload, payloadSize) -#define ASAN_MARK_LARGE_VECTOR_CONTAINER(arena, largeObject) -#endif - -namespace blink { - -void HeapObjectHeader::Finalize(Address object, size_t object_size) { - DCHECK(!IsInConstruction<HeapObjectHeader::AccessMode::kAtomic>()); - const GCInfo& gc_info = GCInfo::From(GcInfoIndex()); - if (gc_info.finalize) - gc_info.finalize(object); - - ASAN_RETIRE_CONTAINER_ANNOTATION(object, object_size); -} - -bool HeapObjectHeader::HasNonTrivialFinalizer() const { - return GCInfo::From(GcInfoIndex()).finalize; -} - -const char* HeapObjectHeader::Name() const { - return GCInfo::From(GcInfoIndex()).name(Payload()).value; -} - -BaseArena::BaseArena(ThreadState* state, int index) - : thread_state_(state), index_(index) {} - -BaseArena::~BaseArena() { - DCHECK(swept_pages_.IsEmpty()); - DCHECK(unswept_pages_.IsEmpty()); - DCHECK(swept_unfinalized_pages_.IsEmpty()); - DCHECK(swept_unfinalized_empty_pages_.IsEmpty()); -} - -void BaseArena::RemoveAllPages() { - ClearFreeLists(); - - DCHECK(SweepingAndFinalizationCompleted()); - while (BasePage* page = swept_pages_.Pop()) { - page->RemoveFromHeap(); - } -} - -void BaseArena::CollectStatistics(std::string name, - ThreadState::Statistics* stats) { - ThreadState::Statistics::ArenaStatistics arena_stats; - - ResetAllocationPoint(); - - if (!NameClient::HideInternalName()) { - const size_t num_types = GCInfoTable::Get().NumberOfGCInfos(); - arena_stats.object_stats.num_types = num_types; - arena_stats.object_stats.type_name.resize(num_types); - arena_stats.object_stats.type_count.resize(num_types); - arena_stats.object_stats.type_bytes.resize(num_types); - } - - arena_stats.name = std::move(name); - DCHECK(unswept_pages_.IsEmpty()); - for (BasePage* page : swept_pages_) { - page->CollectStatistics(&arena_stats); - } - CollectFreeListStatistics(&arena_stats.free_list_stats); - stats->used_size_bytes += arena_stats.used_size_bytes; - stats->committed_size_bytes += arena_stats.committed_size_bytes; - stats->arena_stats.emplace_back(std::move(arena_stats)); -} - -size_t BaseArena::AllocatedBytes() { - DCHECK(unswept_pages_.IsEmpty()); - size_t result = 0; - for (BasePage* page : swept_pages_) { - result += page->AllocatedBytes(); - } - return result; -} - -void NormalPageArena::CollectFreeListStatistics( - ThreadState::Statistics::FreeListStatistics* stats) { - free_list_.CollectStatistics(stats); -} - -#if DCHECK_IS_ON() -BasePage* BaseArena::FindPageFromAddress(ConstAddress address) const { - for (BasePage* page : swept_pages_) { - if (page->Contains(address)) - return page; - } - for (BasePage* page : unswept_pages_) { - if (page->Contains(address)) - return page; - } - for (BasePage* page : swept_unfinalized_pages_) { - if (page->Contains(address)) - return page; - } - for (BasePage* page : swept_unfinalized_empty_pages_) { - if (page->Contains(address)) - return page; - } - return nullptr; -} -#endif - -void BaseArena::MakeConsistentForGC() { -#if DCHECK_IS_ON() - DCHECK(IsConsistentForGC()); -#endif - - // We should not start a new GC until we finish sweeping in the current GC. - CHECK(SweepingAndFinalizationCompleted()); - - HeapCompact* heap_compactor = GetThreadState()->Heap().Compaction(); - if (!heap_compactor->IsCompactingArena(ArenaIndex())) - return; - - for (BasePage* page : swept_pages_) { - if (!page->IsLargeObjectPage()) - heap_compactor->AddCompactingPage(page); - } -} - -void BaseArena::MakeConsistentForMutator() { - ClearFreeLists(); -#if DCHECK_IS_ON() - DCHECK(IsConsistentForGC()); -#endif - DCHECK(swept_pages_.IsEmpty()); - - // Drop marks from marked objects and rebuild free lists in preparation for - // resuming the executions of mutators. - for (BasePage* page : unswept_pages_) { - page->MakeConsistentForMutator(); - page->MarkAsSwept(); - } - - swept_pages_.MoveFrom(std::move(unswept_pages_)); - DCHECK(SweepingAndFinalizationCompleted()); - - VerifyObjectStartBitmap(); -} - -void BaseArena::Unmark() { - DCHECK(GetThreadState()->InAtomicMarkingPause()); - DCHECK(SweepingAndFinalizationCompleted()); - - for (BasePage* page : swept_pages_) { - page->Unmark(); - } -} - -size_t BaseArena::ObjectPayloadSizeForTesting() { -#if DCHECK_IS_ON() - DCHECK(IsConsistentForGC()); -#endif - // DCHECK(SweepingCompleted()); - - size_t object_payload_size = 0; - for (BasePage* page : unswept_pages_) { - object_payload_size += page->ObjectPayloadSizeForTesting(); - } - return object_payload_size; -} - -void BaseArena::PrepareForSweep(BlinkGC::CollectionType collection_type) { - DCHECK(GetThreadState()->InAtomicMarkingPause()); - DCHECK(SweepingAndFinalizationCompleted()); - - ClearFreeLists(); - - // Verification depends on the allocation point being cleared. - VerifyObjectStartBitmap(); - - if (collection_type == BlinkGC::CollectionType::kMinor) { - auto** first_young = - std::partition(swept_pages_.begin(), swept_pages_.end(), - [](BasePage* page) { return !page->IsYoung(); }); - for (auto** it = first_young; it != swept_pages_.end(); ++it) { - BasePage* page = *it; - page->MarkAsUnswept(); - page->SetAsYoung(false); - unswept_pages_.Push(page); - } - swept_pages_.erase(first_young, swept_pages_.end()); - return; - } - - for (BasePage* page : swept_pages_) { - page->MarkAsUnswept(); - } - // Move all pages to a list of unswept pages. - unswept_pages_.MoveFrom(std::move(swept_pages_)); - DCHECK(swept_pages_.IsEmpty()); -} - -#if defined(ADDRESS_SANITIZER) -void BaseArena::PoisonUnmarkedObjects() { - for (BasePage* page : unswept_pages_) { - page->PoisonUnmarkedObjects(); - } -} -#endif - -Address BaseArena::LazySweep(size_t allocation_size, size_t gc_info_index) { - // If there are no pages to be swept, return immediately. - if (SweepingAndFinalizationCompleted()) - return nullptr; - - CHECK(GetThreadState()->IsSweepingInProgress()); - - // lazySweepPages() can be called recursively if finalizers invoked in - // page->Sweep() allocate memory and the allocation triggers - // lazySweepPages(). This check prevents the sweeping from being executed - // recursively. - if (GetThreadState()->SweepForbidden()) - return nullptr; - - ThreadHeapStatsCollector::EnabledScope stats_scope( - GetThreadState()->Heap().stats_collector(), - ThreadHeapStatsCollector::kLazySweepOnAllocation); - ThreadState::SweepForbiddenScope sweep_forbidden(GetThreadState()); - ScriptForbiddenScope script_forbidden; - return LazySweepPages(allocation_size, gc_info_index); -} - -bool BaseArena::SweepUnsweptPageOnConcurrentThread(BasePage* page) { - const bool is_empty = page->Sweep(FinalizeType::kDeferred); - if (is_empty) { - swept_unfinalized_empty_pages_.PushLocked(page); - } else { - swept_unfinalized_pages_.PushLocked(page); - } - return is_empty; -} - -bool BaseArena::SweepUnsweptPage(BasePage* page) { - const bool is_empty = page->Sweep(FinalizeType::kInlined); - if (is_empty) { - page->FinalizeSweep(SweepResult::kPageEmpty); - } else { - // First, we add page to the list of swept pages - // so that the FindPageFromAddress check is happy. - swept_pages_.PushLocked(page); - page->FinalizeSweep(SweepResult::kPageNotEmpty); - } - return is_empty; -} - -bool BaseArena::LazySweepWithDeadline(base::TimeTicks deadline) { - // It might be heavy to call - // Platform::current()->monotonicallyIncreasingTimeSeconds() per page (i.e., - // 128 KB sweep or one LargeObject sweep), so we check the deadline per 10 - // pages. - static constexpr size_t kDeadlineCheckInterval = 10; - - CHECK(GetThreadState()->IsSweepingInProgress()); - DCHECK(GetThreadState()->SweepForbidden()); - DCHECK(ScriptForbiddenScope::IsScriptForbidden()); - - size_t page_count = 1; - // First, process empty pages to faster reduce memory footprint. - while (BasePage* page = swept_unfinalized_empty_pages_.PopLocked()) { - page->FinalizeSweep(SweepResult::kPageEmpty); - if (page_count % kDeadlineCheckInterval == 0) { - if (deadline <= base::TimeTicks::Now()) { - // Deadline has come. - return SweepingAndFinalizationCompleted(); - } - } - page_count++; - } - // Second, execute finalizers to leave more work for concurrent sweeper. - while (BasePage* page = swept_unfinalized_pages_.PopLocked()) { - swept_pages_.PushLocked(page); - page->FinalizeSweep(SweepResult::kPageNotEmpty); - if (page_count % kDeadlineCheckInterval == 0) { - if (deadline <= base::TimeTicks::Now()) { - // Deadline has come. - return SweepingAndFinalizationCompleted(); - } - } - page_count++; - } - // Help concurrent sweeper. - while (BasePage* page = unswept_pages_.PopLocked()) { - SweepUnsweptPage(page); - if (page_count % kDeadlineCheckInterval == 0) { - if (deadline <= base::TimeTicks::Now()) { - // Deadline has come. - return SweepingAndFinalizationCompleted(); - } - } - page_count++; - } - - return true; -} - -void BaseArena::InvokeFinalizersOnSweptPages() { - DCHECK(GetThreadState()->CheckThread()); - DCHECK(GetThreadState()->IsSweepingInProgress()); - DCHECK(GetThreadState()->SweepForbidden()); - while (BasePage* page = swept_unfinalized_pages_.PopLocked()) { - swept_pages_.PushLocked(page); - page->FinalizeSweep(SweepResult::kPageNotEmpty); - } - while (BasePage* page = swept_unfinalized_empty_pages_.PopLocked()) { - page->FinalizeSweep(SweepResult::kPageEmpty); - } -} - -bool BaseArena::ConcurrentSweepOnePage() { - BasePage* page = unswept_pages_.PopLocked(); - if (!page) - return true; - SweepUnsweptPageOnConcurrentThread(page); - return false; -} - -void BaseArena::CompleteSweep() { - CHECK(GetThreadState()->IsSweepingInProgress()); - DCHECK(GetThreadState()->SweepForbidden()); - DCHECK(ScriptForbiddenScope::IsScriptForbidden()); - - // Some phases, e.g. verification, require iterability of a page. - MakeIterable(); - - // First, finalize pages that have been processed by concurrent sweepers. - InvokeFinalizersOnSweptPages(); - - // Then, sweep and finalize pages. - while (BasePage* page = unswept_pages_.PopLocked()) { - SweepUnsweptPage(page); - } - - // Verify object start bitmap after all freelists have been merged. - VerifyObjectStartBitmap(); -} - -Address BaseArena::AllocateLargeObject(size_t allocation_size, - size_t gc_info_index) { - LargeObjectArena* large_object_arena = static_cast<LargeObjectArena*>( - GetThreadState()->Heap().Arena(BlinkGC::kLargeObjectArenaIndex)); - Address large_object = large_object_arena->AllocateLargeObjectPage( - allocation_size, gc_info_index); - ASAN_MARK_LARGE_VECTOR_CONTAINER(this, large_object); - return large_object; -} - -NormalPageArena::NormalPageArena(ThreadState* state, int index) - : BaseArena(state, index), - current_allocation_point_(nullptr), - remaining_allocation_size_(0), - promptly_freed_size_(0) {} - -void NormalPageArena::AddToFreeList(Address address, size_t size) { -#if DCHECK_IS_ON() - DCHECK(FindPageFromAddress(address)); - DCHECK(FindPageFromAddress(address + size - 1)); -#endif - free_list_.Add(address, size); - static_cast<NormalPage*>(PageFromObject(address)) - ->object_start_bit_map() - ->SetBit<HeapObjectHeader::AccessMode::kAtomic>(address); -} - -void NormalPageArena::MakeConsistentForGC() { - BaseArena::MakeConsistentForGC(); - - // Remove linear allocation area. - SetAllocationPoint(nullptr, 0); -} - -void NormalPageArena::ClearFreeLists() { - SetAllocationPoint(nullptr, 0); - free_list_.Clear(); - promptly_freed_size_ = 0; -} - -void NormalPageArena::MakeIterable() { - SetAllocationPoint(nullptr, 0); -} - -size_t NormalPageArena::ArenaSize() { - size_t size = 0; - for (BasePage* page : swept_pages_) { - size += page->size(); - } - LOG_HEAP_FREELIST_VERBOSE() - << "Heap size: " << size << "(" << ArenaIndex() << ")"; - return size; -} - -size_t NormalPageArena::FreeListSize() { - size_t free_size = free_list_.FreeListSize(); - LOG_HEAP_FREELIST_VERBOSE() - << "Free size: " << free_size << "(" << ArenaIndex() << ")"; - return free_size; -} - -void NormalPageArena::SweepAndCompact() { - ThreadHeap& heap = GetThreadState()->Heap(); - if (!heap.Compaction()->IsCompactingArena(ArenaIndex())) - return; - - if (SweepingCompleted()) { - heap.Compaction()->FinishedArenaCompaction(this, 0, 0); - return; - } - - // Compaction is performed in-place, sliding objects down over unused - // holes for a smaller heap page footprint and improved locality. - // A "compaction pointer" is consequently kept, pointing to the next - // available address to move objects down to. It will belong to one - // of the already sweep-compacted pages for this arena, but as compaction - // proceeds, it will not belong to the same page as the one being - // currently compacted. - // - // The compaction pointer is represented by the - // |(currentPage, allocationPoint)| pair, with |allocationPoint| - // being the offset into |currentPage|, making up the next - // available location. When the compaction of an arena page causes the - // compaction pointer to exhaust the current page it is compacting into, - // page compaction will advance the current page of the compaction - // pointer, as well as the allocation point. - // - // By construction, the page compaction can be performed without having - // to allocate any new pages. So to arrange for the page compaction's - // supply of freed, available pages, we chain them together after each - // has been "compacted from". The page compaction will then reuse those - // as needed, and once finished, the chained, available pages can be - // released back to the OS. - // - // To ease the passing of the compaction state when iterating over an - // arena's pages, package it up into a |CompactionContext|. - NormalPage::CompactionContext context; - context.compacted_pages_ = &swept_pages_; - - while (BasePage* page = unswept_pages_.Pop()) { - // Large objects do not belong to this arena. - DCHECK(!page->IsLargeObjectPage()); - NormalPage* normal_page = static_cast<NormalPage*>(page); - normal_page->MarkAsSwept(); - // If not the first page, add |normalPage| onto the available pages chain. - if (!context.current_page_) { - context.current_page_ = normal_page; - } else { - context.available_pages_.Push(normal_page); - } - normal_page->SweepAndCompact(context); - } - - // All pages were empty; nothing to compact. - if (!context.current_page_) { - heap.Compaction()->FinishedArenaCompaction(this, 0, 0); - return; - } - - size_t freed_size = 0; - size_t freed_page_count = 0; - - // If the current page hasn't been allocated into, add it to the available - // list, for subsequent release below. - size_t allocation_point = context.allocation_point_; - if (!allocation_point) { - context.available_pages_.Push(context.current_page_); - } else { - NormalPage* current_page = context.current_page_; - swept_pages_.Push(current_page); - if (allocation_point != current_page->PayloadSize()) { - // Put the remainder of the page onto the free list. - freed_size = current_page->PayloadSize() - allocation_point; - Address payload = current_page->Payload(); - SET_MEMORY_INACCESSIBLE(payload + allocation_point, freed_size); - current_page->ArenaForNormalPage()->AddToFreeList( - payload + allocation_point, freed_size); - } - } - - // Return available pages to the free page pool, decommitting them from - // the pagefile. -#if DEBUG_HEAP_COMPACTION - std::stringstream stream; -#endif - while (BasePage* available_pages = context.available_pages_.Pop()) { - size_t page_size = available_pages->size(); -#if DEBUG_HEAP_COMPACTION - if (!freed_page_count) - stream << "Releasing:"; - stream << " [" << available_pages << ", " - << static_cast<void*>(reinterpret_cast<char*>(available_pages) + - page_size) - << "]"; -#endif - freed_size += page_size; - freed_page_count++; -#if !(DCHECK_IS_ON() || defined(LEAK_SANITIZER) || \ - defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER)) - // Clear out the page before adding it to the free page pool, which - // decommits it. Recommitting the page must find a zeroed page later. - // We cannot assume that the OS will hand back a zeroed page across - // its "decommit" operation. - // - // If in a debug setting, the unused page contents will have been - // zapped already; leave it in that state. - DCHECK(!available_pages->IsLargeObjectPage()); - NormalPage* unused_page = static_cast<NormalPage*>(available_pages); - memset(unused_page->Payload(), 0, unused_page->PayloadSize()); -#endif - available_pages->RemoveFromHeap(); - } -#if DEBUG_HEAP_COMPACTION - if (freed_page_count) - LOG_HEAP_COMPACTION() << stream.str(); -#endif - heap.Compaction()->FinishedArenaCompaction(this, freed_page_count, - freed_size); - - VerifyObjectStartBitmap(); -} - -void NormalPageArena::VerifyObjectStartBitmap() { -#if DCHECK_IS_ON() - // Verifying object start bitmap requires iterability of pages. As compaction - // may set up a new we have to reset here. - SetAllocationPoint(nullptr, 0); - for (BasePage* page : swept_pages_) { - static_cast<NormalPage*>(page) - ->VerifyObjectStartBitmapIsConsistentWithPayload(); - } -#endif // DCHECK_IS_ON() -} - -void BaseArena::VerifyMarking() { -#if DCHECK_IS_ON() - // We cannot rely on other marking phases to clear the allocation area as - // for incremental marking the application is running between steps and - // might set up a new area. For large object arenas this is a no-op. - ResetAllocationPoint(); - - DCHECK(swept_unfinalized_pages_.IsEmpty()); - DCHECK(swept_unfinalized_empty_pages_.IsEmpty()); - // There may be objects on |swept_pages_| as pre-finalizers may allocate. - // These objects may point to other object on |swept_pages_| or marked objects - // on |unswept_pages_| but may never point to a dead (unmarked) object in - // |unswept_pages_|. - for (BasePage* page : swept_pages_) { - page->VerifyMarking(); - } - for (BasePage* page : unswept_pages_) { - page->VerifyMarking(); - } -#endif // DCHECK_IS_ON() -} - -#if DCHECK_IS_ON() -bool NormalPageArena::IsConsistentForGC() { - // A thread heap is consistent for sweeping if none of the pages to be swept - // contain a freelist block or the current allocation point. - FreeListEntry* entry = free_list_.FindEntry([this](FreeListEntry* entry) { - return PagesToBeSweptContains(entry->GetAddress()); - }); - if (entry) - return false; - - if (HasCurrentAllocationArea()) { - if (PagesToBeSweptContains(CurrentAllocationPoint())) - return false; - } - return true; -} - -bool NormalPageArena::PagesToBeSweptContains(ConstAddress address) const { - for (BasePage* page : unswept_pages_) { - if (page->Contains(address)) - return true; - } - return false; -} -#endif - -void NormalPageArena::AllocatePage() { - PageMemory* page_memory = - GetThreadState()->Heap().GetFreePagePool()->Take(ArenaIndex()); - - if (!page_memory) { - // Allocate a memory region for blinkPagesPerRegion pages that - // will each have the following layout. - // - // [ guard os page | ... payload ... | guard os page ] - // ^---{ aligned to blink page size } - PageMemoryRegion* region = PageMemoryRegion::AllocateNormalPages( - GetThreadState()->Heap().GetRegionTree()); - - // Setup the PageMemory object for each of the pages in the region. - for (size_t i = 0; i < kBlinkPagesPerRegion; ++i) { - PageMemory* memory = PageMemory::SetupPageMemoryInRegion( - region, i * kBlinkPageSize, BlinkPagePayloadSize()); - // Take the first possible page ensuring that this thread actually - // gets a page and add the rest to the page pool. - if (!page_memory) { - // If you hit the CHECK in the call to Commit(), it means that you're - // hitting the limit of the number of mmapped regions the OS can support - // (e.g., /proc/sys/vm/max_map_count in Linux) or on that Windows you - // have exceeded the max commit charge across all processes for the - // system. - memory->Commit(); - page_memory = memory; - } else { - GetThreadState()->Heap().GetFreePagePool()->Add(ArenaIndex(), memory); - } - } - } - NormalPage* page = - new (page_memory->WritableStart()) NormalPage(page_memory, this); - swept_pages_.PushLocked(page); - - ThreadHeap& heap = GetThreadState()->Heap(); - heap.stats_collector()->IncreaseAllocatedSpace(page->size()); - heap.page_bloom_filter()->Add(page->GetAddress()); -#if DCHECK_IS_ON() || defined(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER) - // Allow the following addToFreeList() to add the newly allocated memory - // to the free list. - ASAN_UNPOISON_MEMORY_REGION(page->Payload(), page->PayloadSize()); - Address address = page->Payload(); - for (size_t i = 0; i < page->PayloadSize(); i++) - address[i] = kReuseAllowedZapValue; - ASAN_POISON_MEMORY_REGION(page->Payload(), page->PayloadSize()); -#endif - AddToFreeList(page->Payload(), page->PayloadSize()); - SynchronizedStore(page); -} - -void NormalPageArena::FreePage(NormalPage* page) { - ThreadHeap& heap = GetThreadState()->Heap(); - heap.stats_collector()->DecreaseAllocatedSpace(page->size()); - heap.page_bloom_filter()->Remove(page->GetAddress()); - - PageMemory* memory = page->Storage(); - page->~NormalPage(); - GetThreadState()->Heap().GetFreePagePool()->Add(ArenaIndex(), memory); -} - -PlatformAwareObjectStartBitmap::PlatformAwareObjectStartBitmap(Address offset) - : ObjectStartBitmap(offset) {} - -ObjectStartBitmap::ObjectStartBitmap(Address offset) : offset_(offset) { - Clear(); -} - -void ObjectStartBitmap::Clear() { - memset(&object_start_bit_map_, 0, kReservedForBitmap); -} - -void NormalPageArena::PromptlyFreeObject(HeapObjectHeader* header) { - DCHECK(!GetThreadState()->IsMarkingInProgress()); - DCHECK(!GetThreadState()->SweepForbidden()); - Address address = reinterpret_cast<Address>(header); - Address payload = header->Payload(); - size_t size = header->size(); - size_t payload_size = header->PayloadSize(); - DCHECK_GT(size, 0u); -#if DCHECK_IS_ON() - DCHECK_EQ(PageFromObject(address), FindPageFromAddress(address)); -#endif - { - ThreadState::SweepForbiddenScope forbidden_scope(GetThreadState()); - header->Finalize(payload, payload_size); - if (IsObjectAllocatedAtAllocationPoint(header)) { - current_allocation_point_ -= size; - DCHECK_EQ(address, current_allocation_point_); - remaining_allocation_size_ += size; - SET_MEMORY_INACCESSIBLE(address, size); - // Memory that is part of the allocation point is not allowed to be part - // of the object start bit map. - reinterpret_cast<NormalPage*>(PageFromObject(header)) - ->object_start_bit_map() - ->ClearBit(address); - return; - } - DCHECK(!header->IsMarked()); - PromptlyFreeObjectInFreeList(header, size); - } -} - -void NormalPageArena::PromptlyFreeObjectInFreeList(HeapObjectHeader* header, - size_t size) { - DCHECK(!header->IsMarked()); - Address address = reinterpret_cast<Address>(header); - NormalPage* page = static_cast<NormalPage*>(PageFromObject(header)); - DCHECK(page->HasBeenSwept()); - Address payload = header->Payload(); - size_t payload_size = header->PayloadSize(); - // If the page has been swept a promptly freed object may be adjacent - // to other free list entries. We make the object available for future - // allocation right away by adding it to the free list and increase the - // promptly_freed_size_ counter which may result in coalescing later. - SET_MEMORY_INACCESSIBLE(payload, payload_size); - CHECK_MEMORY_INACCESSIBLE(payload, payload_size); - AddToFreeList(address, size); - promptly_freed_size_ += size; - GetThreadState()->Heap().stats_collector()->DecreaseAllocatedObjectSize(size); - page->DecreaseAllocatedBytes(size); -} - -bool NormalPageArena::ExpandObject(HeapObjectHeader* header, size_t new_size) { - // It's possible that Vector requests a smaller expanded size because - // Vector::shrinkCapacity can set a capacity smaller than the actual payload - // size. - if (header->PayloadSize() >= new_size) - return true; - size_t allocation_size = ThreadHeap::AllocationSizeFromSize(new_size); - DCHECK_GT(allocation_size, header->size()); - size_t expand_size = allocation_size - header->size(); - if (IsObjectAllocatedAtAllocationPoint(header) && - expand_size <= remaining_allocation_size_) { - current_allocation_point_ += expand_size; - DCHECK_GE(remaining_allocation_size_, expand_size); - remaining_allocation_size_ -= expand_size; - // Unpoison the memory used for the object (payload). - SET_MEMORY_ACCESSIBLE(header->PayloadEnd(), expand_size); - header->SetSize(allocation_size); -#if DCHECK_IS_ON() - DCHECK(FindPageFromAddress(header->PayloadEnd() - 1)); -#endif - return true; - } - return false; -} - -bool NormalPageArena::ShrinkObject(HeapObjectHeader* header, size_t new_size) { - DCHECK_GT(header->PayloadSize(), new_size); - size_t allocation_size = ThreadHeap::AllocationSizeFromSize(new_size); - DCHECK_GT(header->size(), allocation_size); - size_t shrink_size = header->size() - allocation_size; - if (IsObjectAllocatedAtAllocationPoint(header)) { - current_allocation_point_ -= shrink_size; - remaining_allocation_size_ += shrink_size; - SET_MEMORY_INACCESSIBLE(current_allocation_point_, shrink_size); - header->SetSize(allocation_size); - return true; - } - DCHECK_GE(shrink_size, sizeof(HeapObjectHeader)); - DCHECK_GT(header->GcInfoIndex(), 0u); - Address shrink_address = header->PayloadEnd() - shrink_size; - HeapObjectHeader* freed_header = new (NotNullTag::kNotNull, shrink_address) - HeapObjectHeader(shrink_size, header->GcInfoIndex()); - // Since only size has been changed, we don't need to update object starts. - PromptlyFreeObjectInFreeList(freed_header, shrink_size); -#if DCHECK_IS_ON() - DCHECK_EQ(PageFromObject(reinterpret_cast<Address>(header)), - FindPageFromAddress(reinterpret_cast<Address>(header))); -#endif - header->SetSize(allocation_size); - - return false; -} - -Address NormalPageArena::AllocateFromFreeList(size_t allocation_size, - size_t gc_info_index) { - FreeListEntry* entry = free_list_.Allocate(allocation_size); - if (!entry) - return nullptr; - - SetAllocationPoint(entry->GetAddress(), entry->size()); - DCHECK(HasCurrentAllocationArea()); - DCHECK_GE(RemainingAllocationSize(), allocation_size); - return AllocateObject(allocation_size, gc_info_index); -} - -Address NormalPageArena::LazySweepPages(size_t allocation_size, - size_t gc_info_index) { - DCHECK(!HasCurrentAllocationArea()); - Address result = nullptr; - // First, process unfinalized pages as finalizing a page is faster than - // sweeping. - while (BasePage* page = swept_unfinalized_pages_.PopLocked()) { - swept_pages_.PushLocked(page); - page->FinalizeSweep(SweepResult::kPageNotEmpty); - // For NormalPage, stop lazy sweeping once we find a slot to - // allocate a new object. - result = AllocateFromFreeList(allocation_size, gc_info_index); - if (result) - return result; - } - while (BasePage* page = unswept_pages_.PopLocked()) { - const bool is_empty = SweepUnsweptPage(page); - if (!is_empty) { - // For NormalPage, stop lazy sweeping once we find a slot to - // allocate a new object. - result = AllocateFromFreeList(allocation_size, gc_info_index); - if (result) - return result; - } - } - return result; -} - -void NormalPageArena::SetAllocationPoint(Address point, size_t size) { -#if DCHECK_IS_ON() - if (point) { - DCHECK(size); - BasePage* page = PageFromObject(point); - DCHECK(!page->IsLargeObjectPage()); - DCHECK_LE(size, static_cast<NormalPage*>(page)->PayloadSize()); - } -#endif - // Free and clear the old linear allocation area. - if (HasCurrentAllocationArea()) { - size_t remaining_size = RemainingAllocationSize(); - AddToFreeList(CurrentAllocationPoint(), remaining_size); - GetThreadState()->Heap().stats_collector()->DecreaseAllocatedObjectSize( - remaining_size); - static_cast<NormalPage*>(PageFromObject(CurrentAllocationPoint())) - ->DecreaseAllocatedBytes(remaining_size); - } - // Set up a new linear allocation area. - current_allocation_point_ = point; - remaining_allocation_size_ = size; - // Update last allocated region in ThreadHeap. This must also be done if the - // allocation point is set to 0 (before doing GC), so that the last allocated - // region is automatically reset after GC. - GetThreadState()->Heap().SetLastAllocatedRegion(point, size); - if (point) { - // Only, update allocated size and object start bitmap if the area is - // actually set up with a non-null address. - GetThreadState()->Heap().stats_collector()->IncreaseAllocatedObjectSize( - size); - NormalPage* page = static_cast<NormalPage*>(PageFromObject(point)); - page->IncreaseAllocatedBytes(size); - // Current allocation point can never be part of the object bitmap start - // because the area can grow or shrink. Will be added back before a GC when - // clearing the allocation point. - page->object_start_bit_map() - ->ClearBit<HeapObjectHeader::AccessMode::kAtomic>(point); - // Mark page as containing young objects. - page->SetAsYoung(true); - } -} - -Address NormalPageArena::OutOfLineAllocate(size_t allocation_size, - size_t gc_info_index) { - Address result = OutOfLineAllocateImpl(allocation_size, gc_info_index); - GetThreadState()->Heap().stats_collector()->AllocatedObjectSizeSafepoint(); - return result; -} - -Address NormalPageArena::OutOfLineAllocateImpl(size_t allocation_size, - size_t gc_info_index) { - DCHECK_GT(allocation_size, RemainingAllocationSize()); - DCHECK_GE(allocation_size, kAllocationGranularity); - - // 1. If this allocation is big enough, allocate a large object. - if (allocation_size >= kLargeObjectSizeThreshold) - return AllocateLargeObject(allocation_size, gc_info_index); - - // 2. Try to allocate from a free list. - Address result = AllocateFromFreeList(allocation_size, gc_info_index); - if (result) - return result; - - // 3. Reset the allocation point. - SetAllocationPoint(nullptr, 0); - - // 4. Lazily sweep pages of this heap until we find a freed area for - // this allocation or we finish sweeping all pages of this heap. - result = LazySweep(allocation_size, gc_info_index); - if (result) - return result; - - // 5. Complete sweeping. - GetThreadState()->CompleteSweep(); - - // 6. Check if we should trigger a GC. - GetThreadState()->ScheduleGCIfNeeded(); - - // 7. Add a new page to this heap. - AllocatePage(); - - // 8. Try to allocate from a free list. This allocation must succeed. - result = AllocateFromFreeList(allocation_size, gc_info_index); - CHECK(result); - return result; -} - -LargeObjectArena::LargeObjectArena(ThreadState* state, int index) - : BaseArena(state, index) {} - -Address LargeObjectArena::AllocateLargeObjectPage(size_t allocation_size, - size_t gc_info_index) { - // Caller already added space for object header and rounded up to allocation - // alignment - DCHECK(!(allocation_size & kAllocationMask)); - - // 1. Try to sweep large objects more than allocationSize bytes - // before allocating a new large object. - Address result = LazySweep(allocation_size, gc_info_index); - if (result) - return result; - - // 2. If we have failed in sweeping allocationSize bytes, - // we complete sweeping before allocating this large object. - GetThreadState()->CompleteSweep(); - - // 3. Check if we should trigger a GC. - GetThreadState()->ScheduleGCIfNeeded(); - - return DoAllocateLargeObjectPage(allocation_size, gc_info_index); -} - -Address LargeObjectArena::DoAllocateLargeObjectPage(size_t allocation_size, - size_t gc_info_index) { - size_t large_page_size = LargeObjectPage::PageHeaderSize() + allocation_size; -// If ASan is supported we add allocationGranularity bytes to the allocated -// space and poison that to detect overflows -#if defined(ADDRESS_SANITIZER) - large_page_size += kAllocationGranularity; -#endif - - PageMemory* page_memory = PageMemory::Allocate( - large_page_size, GetThreadState()->Heap().GetRegionTree()); - Address large_page_address = page_memory->WritableStart(); - Address header_address = - large_page_address + LargeObjectPage::PageHeaderSize(); -#if DCHECK_IS_ON() - // Verify that the allocated PageMemory is expectedly zeroed. - for (size_t i = 0; i < large_page_size; ++i) - DCHECK(!large_page_address[i]); -#endif - DCHECK_GT(gc_info_index, 0u); - LargeObjectPage* large_page = new (large_page_address) - LargeObjectPage(page_memory, this, allocation_size); - HeapObjectHeader* header = new (NotNullTag::kNotNull, header_address) - HeapObjectHeader(kLargeObjectSizeInHeader, gc_info_index); - Address result = header_address + sizeof(*header); - DCHECK(!(reinterpret_cast<uintptr_t>(result) & kAllocationMask)); - - // Poison the object header and allocationGranularity bytes after the object - ASAN_POISON_MEMORY_REGION(header, sizeof(*header)); - ASAN_POISON_MEMORY_REGION(large_page->GetAddress() + large_page->size(), - kAllocationGranularity); - - swept_pages_.PushLocked(large_page); - - // Update last allocated region in ThreadHeap. - GetThreadState()->Heap().SetLastAllocatedRegion(large_page->Payload(), - large_page->PayloadSize()); - - // Add all segments of kBlinkPageSize to the bloom filter so that the large - // object can be kept by derived pointers on stack. An alternative might be to - // prohibit derived pointers to large objects, but that is dangerous since the - // compiler is free to optimize on-stack base pointers away. - for (Address page_begin = RoundToBlinkPageStart(large_page->GetAddress()); - page_begin < large_page->PayloadEnd(); page_begin += kBlinkPageSize) { - GetThreadState()->Heap().page_bloom_filter()->Add(page_begin); - } - GetThreadState()->Heap().stats_collector()->IncreaseAllocatedSpace( - large_page->size()); - GetThreadState()->Heap().stats_collector()->IncreaseAllocatedObjectSize( - large_page->ObjectSize()); - large_page->IncreaseAllocatedBytes(large_page->ObjectSize()); - // Add page to the list of young pages. - large_page->SetAsYoung(true); - SynchronizedStore(large_page); - return result; -} - -void LargeObjectArena::FreeLargeObjectPage(LargeObjectPage* object) { - ASAN_UNPOISON_MEMORY_REGION(object->Payload(), object->PayloadSize()); - object->ObjectHeader()->Finalize(object->Payload(), object->PayloadSize()); - ThreadHeap& heap = GetThreadState()->Heap(); - heap.stats_collector()->DecreaseAllocatedSpace(object->size()); - heap.page_bloom_filter()->Remove(object->GetAddress()); - - // Unpoison the object header and allocationGranularity bytes after the - // object before freeing. - ASAN_UNPOISON_MEMORY_REGION(object->ObjectHeader(), sizeof(HeapObjectHeader)); - ASAN_UNPOISON_MEMORY_REGION(object->GetAddress() + object->size(), - kAllocationGranularity); - - PageMemory* memory = object->Storage(); - object->~LargeObjectPage(); - delete memory; -} - -Address LargeObjectArena::LazySweepPages(size_t allocation_size, - size_t gc_info_index) { - Address result = nullptr; - size_t swept_size = 0; - while (BasePage* page = unswept_pages_.PopLocked()) { - if (page->Sweep(FinalizeType::kInlined)) { - swept_size += static_cast<LargeObjectPage*>(page)->ObjectSize(); - page->RemoveFromHeap(); - // For LargeObjectPage, stop lazy sweeping once we have swept - // more than |allocation_size| bytes. - if (swept_size >= allocation_size) { - result = DoAllocateLargeObjectPage(allocation_size, gc_info_index); - DCHECK(result); - break; - } - } else { - swept_pages_.PushLocked(page); - page->MarkAsSwept(); - } - } - return result; -} - -FreeList::FreeList() : biggest_free_list_index_(0) { - Clear(); -} - -void FreeList::Add(Address address, size_t size) { - DCHECK_LT(size, BlinkPagePayloadSize()); - // The free list entries are only pointer aligned (but when we allocate - // from them we are 8 byte aligned due to the header size). - DCHECK(!((reinterpret_cast<uintptr_t>(address) + sizeof(HeapObjectHeader)) & - kAllocationMask)); - DCHECK(!(size & kAllocationMask)); - DCHECK(!PageFromObject(address)->IsLargeObjectPage()); - ASAN_UNPOISON_MEMORY_REGION(address, size); - FreeListEntry* entry; - if (size < sizeof(*entry)) { - // Create a dummy header with only a size and freelist bit set. - DCHECK_GE(size, sizeof(HeapObjectHeader)); - // Free list encode the size to mark the lost memory as freelist memory. - new (NotNullTag::kNotNull, address) - HeapObjectHeader(size, kGcInfoIndexForFreeListHeader); - ASAN_POISON_MEMORY_REGION(address, size); - // This memory gets lost. Sweeping can reclaim it. - return; - } - entry = new (NotNullTag::kNotNull, address) FreeListEntry(size); - -#if DCHECK_IS_ON() || defined(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER) - // The following logic delays reusing free lists for (at least) one GC - // cycle. This is helpful to detect use-after-free errors that could be caused - // by lazy sweeping etc. - size_t allowed_count = 0; - size_t forbidden_count = 0; - GetAllowedAndForbiddenCounts(address, size, allowed_count, forbidden_count); - size_t entry_count = size - sizeof(FreeListEntry); - if (forbidden_count == entry_count) { - // If all values in the memory region are reuseForbiddenZapValue, - // we flip them to reuseAllowedZapValue. This allows the next - // addToFreeList() to add the memory region to the free list - // (unless someone concatenates the memory region with another memory - // region that contains reuseForbiddenZapValue.) - for (size_t i = sizeof(FreeListEntry); i < size; i++) - address[i] = kReuseAllowedZapValue; - ASAN_POISON_MEMORY_REGION(address, size); - // Don't add the memory region to the free list in this addToFreeList(). - return; - } - if (allowed_count != entry_count) { - // If the memory region mixes reuseForbiddenZapValue and - // reuseAllowedZapValue, we (conservatively) flip all the values - // to reuseForbiddenZapValue. These values will be changed to - // reuseAllowedZapValue in the next addToFreeList(). - for (size_t i = sizeof(FreeListEntry); i < size; i++) - address[i] = kReuseForbiddenZapValue; - ASAN_POISON_MEMORY_REGION(address, size); - // Don't add the memory region to the free list in this addToFreeList(). - return; - } -// We reach here only when all the values in the memory region are -// reuseAllowedZapValue. In this case, we are allowed to add the memory -// region to the free list and reuse it for another object. -#endif - ASAN_POISON_MEMORY_REGION(address, size); - - const int index = BucketIndexForSize(size); - entry->Link(&free_list_heads_[index]); - if (index > biggest_free_list_index_) { - biggest_free_list_index_ = index; - } - if (!entry->Next()) { - free_list_tails_[index] = entry; - } -} - -void FreeList::MoveFrom(FreeList* other) { -#if DCHECK_IS_ON() - const size_t expected_size = FreeListSize() + other->FreeListSize(); -#endif - - // Newly created entries get added to the head. - for (size_t index = 0; index < kBlinkPageSizeLog2; ++index) { - FreeListEntry* other_tail = other->free_list_tails_[index]; - FreeListEntry*& this_head = this->free_list_heads_[index]; - if (other_tail) { - other_tail->Append(this_head); - if (!this_head) { - this->free_list_tails_[index] = other_tail; - } - this_head = other->free_list_heads_[index]; - other->free_list_heads_[index] = nullptr; - other->free_list_tails_[index] = nullptr; - } - } - - biggest_free_list_index_ = - std::max(biggest_free_list_index_, other->biggest_free_list_index_); - other->biggest_free_list_index_ = 0; - -#if DCHECK_IS_ON() - DCHECK_EQ(expected_size, FreeListSize()); -#endif - DCHECK(other->IsEmpty()); -} - -FreeListEntry* FreeList::Allocate(size_t allocation_size) { - // Try reusing a block from the largest bin. The underlying reasoning - // being that we want to amortize this slow allocation call by carving - // off as a large a free block as possible in one go; a block that will - // service this block and let following allocations be serviced quickly - // by bump allocation. - size_t bucket_size = static_cast<size_t>(1) << biggest_free_list_index_; - int index = biggest_free_list_index_; - for (; index > 0; --index, bucket_size >>= 1) { - DCHECK(IsConsistent(index)); - FreeListEntry* entry = free_list_heads_[index]; - if (allocation_size > bucket_size) { - // Final bucket candidate; check initial entry if it is able - // to service this allocation. Do not perform a linear scan, - // as it is considered too costly. - if (!entry || entry->size() < allocation_size) - break; - } - if (entry) { - if (!entry->Next()) { - DCHECK_EQ(entry, free_list_tails_[index]); - free_list_tails_[index] = nullptr; - } - entry->Unlink(&free_list_heads_[index]); - biggest_free_list_index_ = index; - return entry; - } - } - biggest_free_list_index_ = index; - return nullptr; -} - -#if DCHECK_IS_ON() || defined(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER) || \ - defined(MEMORY_SANITIZER) -NO_SANITIZE_MEMORY -NOINLINE void FreeList::GetAllowedAndForbiddenCounts(Address address, - size_t size, - size_t& allowed_count, - size_t& forbidden_count) { - for (size_t i = sizeof(FreeListEntry); i < size; i++) { - if (address[i] == kReuseAllowedZapValue) - allowed_count++; - else if (address[i] == kReuseForbiddenZapValue) - forbidden_count++; - else - NOTREACHED(); - } -} - -NO_SANITIZE_ADDRESS -NO_SANITIZE_MEMORY -NOINLINE void FreeList::ZapFreedMemory(Address address, size_t size) { - for (size_t i = 0; i < size; i++) { - // See the comment in addToFreeList(). - if (address[i] != kReuseAllowedZapValue) - address[i] = kReuseForbiddenZapValue; - } -} - -NOINLINE void FreeList::CheckFreedMemoryIsZapped(Address address, size_t size) { - for (size_t i = 0; i < size; i++) { - DCHECK(address[i] == kReuseAllowedZapValue || - address[i] == kReuseForbiddenZapValue); - } -} -#endif - -size_t FreeList::FreeListSize() const { - size_t free_size = 0; - for (unsigned i = 0; i < kBlinkPageSizeLog2; ++i) { - FreeListEntry* entry = free_list_heads_[i]; - while (entry) { - free_size += entry->size(); - entry = entry->Next(); - } - } -#if DEBUG_HEAP_FREELIST - if (free_size) { - LOG_HEAP_FREELIST_VERBOSE() << "FreeList(" << this << "): " << free_size; - for (unsigned i = 0; i < kBlinkPageSizeLog2; ++i) { - FreeListEntry* entry = free_list_heads_[i]; - size_t bucket = 0; - size_t count = 0; - while (entry) { - bucket += entry->size(); - count++; - entry = entry->Next(); - } - if (bucket) { - LOG_HEAP_FREELIST_VERBOSE() - << "[" << (0x1 << i) << ", " << (0x1 << (i + 1)) << "]: " << bucket - << " (" << count << ")"; - } - } - } -#endif - return free_size; -} - -void FreeList::Clear() { - biggest_free_list_index_ = 0; - for (size_t i = 0; i < kBlinkPageSizeLog2; ++i) { - free_list_heads_[i] = nullptr; - free_list_tails_[i] = nullptr; - } -} - -bool FreeList::IsEmpty() const { - if (biggest_free_list_index_) - return false; - for (size_t i = 0; i < kBlinkPageSizeLog2; ++i) { - if (free_list_heads_[i]) { - DCHECK(free_list_tails_[i]); - return false; - } - } - return true; -} - -int FreeList::BucketIndexForSize(size_t size) { - DCHECK_GT(size, 0u); - int index = -1; - while (size) { - size >>= 1; - index++; - } - return index; -} - -void FreeList::CollectStatistics( - ThreadState::Statistics::FreeListStatistics* stats) { - Vector<size_t> bucket_size; - Vector<size_t> free_count; - Vector<size_t> free_size; - for (size_t i = 0; i < kBlinkPageSizeLog2; ++i) { - size_t entry_count = 0; - size_t entry_size = 0; - for (FreeListEntry* entry = free_list_heads_[i]; entry; - entry = entry->Next()) { - ++entry_count; - entry_size += entry->size(); - } - bucket_size.push_back(1 << i); - free_count.push_back(entry_count); - free_size.push_back(entry_size); - } - *stats = {std::move(bucket_size), std::move(free_count), - std::move(free_size)}; -} - -BasePage::BasePage(PageMemory* storage, BaseArena* arena, PageType page_type) - : storage_(storage), - arena_(arena), - thread_state_(arena->GetThreadState()), - page_type_(page_type) { -#if DCHECK_IS_ON() - DCHECK(IsPageHeaderAddress(reinterpret_cast<Address>(this))); -#endif -} - -NormalPage::NormalPage(PageMemory* storage, BaseArena* arena) - : BasePage(storage, arena, PageType::kNormalPage), - object_start_bit_map_(Payload()) { -#if DCHECK_IS_ON() - DCHECK(IsPageHeaderAddress(reinterpret_cast<Address>(this))); -#endif // DCHECK_IS_ON() -} - -NormalPage::~NormalPage() { -#if DCHECK_IS_ON() - DCHECK(IsPageHeaderAddress(reinterpret_cast<Address>(this))); -#endif -} - -size_t NormalPage::ObjectPayloadSizeForTesting() { - size_t object_payload_size = 0; - Address header_address = Payload(); - DCHECK_NE(header_address, PayloadEnd()); - do { - HeapObjectHeader* header = - reinterpret_cast<HeapObjectHeader*>(header_address); - if (!header->IsFree()) { - object_payload_size += header->PayloadSize(); - } - DCHECK_LT(header->size(), BlinkPagePayloadSize()); - header_address += header->size(); - DCHECK_LE(header_address, PayloadEnd()); - } while (header_address < PayloadEnd()); - return object_payload_size; -} - -void NormalPage::RemoveFromHeap() { - ArenaForNormalPage()->FreePage(this); -} - -#if !DCHECK_IS_ON() && !defined(LEAK_SANITIZER) && !defined(ADDRESS_SANITIZER) -static void DiscardPages(Address begin, Address end) { - uintptr_t begin_address = - base::RoundUpToSystemPage(reinterpret_cast<uintptr_t>(begin)); - uintptr_t end_address = - base::RoundDownToSystemPage(reinterpret_cast<uintptr_t>(end)); - if (begin_address < end_address) { - base::DiscardSystemPages(reinterpret_cast<void*>(begin_address), - end_address - begin_address); - } -} -#endif - -void NormalPage::ToBeFinalizedObject::Finalize() { - const size_t size = header->size(); - // This is a fast version of header->PayloadSize(). - const size_t payload_size = size - sizeof(HeapObjectHeader); - const Address payload = header->Payload(); - // For ASan, unpoison the object before calling the finalizer. The - // finalized object will be zero-filled and poison'ed afterwards. - // Given all other unmarked objects are poisoned, ASan will detect - // an error if the finalizer touches any other on-heap object that - // die at the same GC cycle. - ASAN_UNPOISON_MEMORY_REGION(payload, payload_size); - - header->Finalize(payload, payload_size); - // This memory will be added to the freelist. Maintain the invariant - // that memory on the freelist is zero filled. - SET_MEMORY_INACCESSIBLE(reinterpret_cast<Address>(header), size); -} - -void NormalPage::FinalizeSweep(SweepResult action) { - // Call finalizers. - for (ToBeFinalizedObject& object : to_be_finalized_objects_) { - object.Finalize(); - } - to_be_finalized_objects_.clear(); -#if BUILDFLAG(BLINK_HEAP_YOUNG_GENERATION) - // Copy object start bit map. - DCHECK(cached_object_start_bit_map_); - object_start_bit_map_ = *cached_object_start_bit_map_; - cached_object_start_bit_map_.reset(); -#endif - // Merge freelists or unmap the page. - if (action == SweepResult::kPageNotEmpty) { - MergeFreeLists(); - MarkAsSwept(); - } else { - DCHECK(action == SweepResult::kPageEmpty); - RemoveFromHeap(); - } -} - -void NormalPage::AddToFreeList(Address start, - size_t size, - FinalizeType finalize_type, - bool found_finalizer) { - // If a free allocation block contains an object that is yet to be - // finalized, push it in a separate freelist to preserve the guarantee - // that all freelist entries are zeroed out. - if (found_finalizer && finalize_type == FinalizeType::kDeferred) { - FutureFreelistEntry entry{start, size}; - unfinalized_freelist_.push_back(std::move(entry)); - } else { - cached_freelist_.Add(start, size); -#if BUILDFLAG(BLINK_HEAP_YOUNG_GENERATION) - cached_object_start_bit_map_->SetBit(start); -#else - object_start_bit_map_.SetBit(start); -#endif -#if !DCHECK_IS_ON() && !defined(LEAK_SANITIZER) && !defined(ADDRESS_SANITIZER) - if (Arena()->GetThreadState()->IsMemoryReducingGC()) { - DiscardPages(start + sizeof(FreeListEntry), start + size); - } -#endif - } -} - -void NormalPage::MergeFreeLists() { - NormalPageArena* arena = ArenaForNormalPage(); - arena->AddToFreeList(&cached_freelist_); - DCHECK(cached_freelist_.IsEmpty()); - - for (const FutureFreelistEntry& entry : unfinalized_freelist_) { - arena->AddToFreeList(entry.start, entry.size); -#if !DCHECK_IS_ON() && !defined(LEAK_SANITIZER) && !defined(ADDRESS_SANITIZER) - if (Arena()->GetThreadState()->IsMemoryReducingGC()) { - DiscardPages(entry.start + sizeof(FreeListEntry), - entry.start + entry.size); - } -#endif - } - unfinalized_freelist_.clear(); -} - -bool NormalPage::Sweep(FinalizeType finalize_type) { - PlatformAwareObjectStartBitmap* bitmap; -#if BUILDFLAG(BLINK_HEAP_YOUNG_GENERATION) - cached_object_start_bit_map_ = - std::make_unique<PlatformAwareObjectStartBitmap>(Payload()); - bitmap = cached_object_start_bit_map_.get(); -#else - object_start_bit_map()->Clear(); - bitmap = object_start_bit_map(); -#endif - cached_freelist_.Clear(); - unfinalized_freelist_.clear(); - Address start_of_gap = Payload(); - size_t live_bytes = 0; - bool found_finalizer = false; - for (Address header_address = start_of_gap; header_address < PayloadEnd();) { - HeapObjectHeader* header = - reinterpret_cast<HeapObjectHeader*>(header_address); - const size_t size = header->size(); - DCHECK_GT(size, 0u); - DCHECK_LT(size, BlinkPagePayloadSize()); - - if (header->IsFree<HeapObjectHeader::AccessMode::kAtomic>()) { - // Zero the memory in the free list header to maintain the - // invariant that memory on the free list is zero filled. - // The rest of the memory is already on the free list and is - // therefore already zero filled. - SET_MEMORY_INACCESSIBLE(header_address, - std::min(size, sizeof(FreeListEntry))); - CHECK_MEMORY_INACCESSIBLE(header_address, size); - header_address += size; - continue; - } - if (!header->IsMarked<HeapObjectHeader::AccessMode::kAtomic>()) { - // The following accesses to the header are safe non-atomically, because - // we just established the invariant that the object is not marked. - ToBeFinalizedObject object{header}; - if (finalize_type == FinalizeType::kInlined || - !header->HasNonTrivialFinalizer()) { - // In case the header doesn't have a finalizer, we eagerly call a - // freehook. - // TODO(bikineev): It may be unsafe to do this concurrently. - object.Finalize(); - } else { - to_be_finalized_objects_.push_back(std::move(object)); - found_finalizer = true; - } - header_address += size; - continue; - } - if (start_of_gap != header_address) { - AddToFreeList(start_of_gap, header_address - start_of_gap, finalize_type, - found_finalizer); - found_finalizer = false; - } - bitmap->SetBit(header_address); -#if !BUILDFLAG(BLINK_HEAP_YOUNG_GENERATION) - header->Unmark<HeapObjectHeader::AccessMode::kAtomic>(); -#endif - live_bytes += size; - header_address += size; - start_of_gap = header_address; - } - SetAllocatedBytes(live_bytes); - // Only add the memory to the free list if the page is not completely empty - // and we are not at the end of the page. Empty pages are not added to the - // free list as the pages are removed immediately. - if (start_of_gap != Payload() && start_of_gap != PayloadEnd()) { - AddToFreeList(start_of_gap, PayloadEnd() - start_of_gap, finalize_type, - found_finalizer); - } - return start_of_gap == Payload(); -} - -void NormalPage::SweepAndCompact(CompactionContext& context) { - object_start_bit_map()->Clear(); - NormalPage*& current_page = context.current_page_; - size_t& allocation_point = context.allocation_point_; - SetAllocatedBytes(0u); - - NormalPageArena* page_arena = ArenaForNormalPage(); -#if defined(ADDRESS_SANITIZER) - bool is_vector_arena = - ThreadHeap::IsVectorArenaIndex(page_arena->ArenaIndex()); -#endif - HeapCompact* compact = page_arena->GetThreadState()->Heap().Compaction(); - for (Address header_address = Payload(); header_address < PayloadEnd();) { - HeapObjectHeader* header = - reinterpret_cast<HeapObjectHeader*>(header_address); - size_t size = header->size(); - DCHECK_GT(size, 0u); - DCHECK_LT(size, BlinkPagePayloadSize()); - - if (header->IsFree()) { - // Unpoison the freelist entry so that we - // can compact into it as wanted. - ASAN_UNPOISON_MEMORY_REGION(header_address, size); - header_address += size; - continue; - } - // This is a fast version of header->PayloadSize(). - size_t payload_size = size - sizeof(HeapObjectHeader); - Address payload = header->Payload(); - if (!header->IsMarked()) { - // For ASan, unpoison the object before calling the finalizer. The - // finalized object will be zero-filled and poison'ed afterwards. - // Given all other unmarked objects are poisoned, ASan will detect - // an error if the finalizer touches any other on-heap object that - // die at the same GC cycle. - ASAN_UNPOISON_MEMORY_REGION(header_address, size); - // Compaction is currently launched only from AtomicPhaseEpilogue, so it's - // guaranteed to be on the mutator thread - no need to postpone - // finalization. - header->Finalize(payload, payload_size); - -// As compaction is under way, leave the freed memory accessible -// while compacting the rest of the page. We just zap the payload -// to catch out other finalizers trying to access it. -#if DCHECK_IS_ON() || defined(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER) || \ - defined(MEMORY_SANITIZER) - FreeList::ZapFreedMemory(payload, payload_size); -#endif - header_address += size; - continue; - } -#if !BUILDFLAG(BLINK_HEAP_YOUNG_GENERATION) - header->Unmark(); -#endif - // Allocate and copy over the live object. - Address compact_frontier = current_page->Payload() + allocation_point; - if (compact_frontier + size > current_page->PayloadEnd()) { - // Can't fit on current allocation page; add remaining onto the - // freelist and advance to next available page. - // - // TODO(sof): be more clever & compact later objects into - // |currentPage|'s unused slop. - context.compacted_pages_->Push(current_page); - size_t free_size = current_page->PayloadSize() - allocation_point; - if (free_size) { - SET_MEMORY_INACCESSIBLE(compact_frontier, free_size); - current_page->ArenaForNormalPage()->AddToFreeList(compact_frontier, - free_size); - } - - current_page = static_cast<NormalPage*>(context.available_pages_.Pop()); - allocation_point = 0; - compact_frontier = current_page->Payload(); - } - if (LIKELY(compact_frontier != header_address)) { -#if defined(ADDRESS_SANITIZER) - // Unpoison the header + if it is a vector backing - // store object, let go of the container annotations. - // Do that by unpoisoning the payload entirely. - ASAN_UNPOISON_MEMORY_REGION(header, sizeof(HeapObjectHeader)); - if (is_vector_arena) { - ASAN_UNPOISON_MEMORY_REGION(payload, payload_size); - } -#endif - // Use a non-overlapping copy, if possible. - if (current_page == this) - memmove(compact_frontier, header_address, size); - else - memcpy(compact_frontier, header_address, size); - compact->Relocate(payload, compact_frontier + sizeof(HeapObjectHeader)); - } - current_page->object_start_bit_map()->SetBit(compact_frontier); - current_page->IncreaseAllocatedBytes(size); - header_address += size; - allocation_point += size; - DCHECK(allocation_point <= current_page->PayloadSize()); - } - -#if DCHECK_IS_ON() || defined(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER) || \ - defined(MEMORY_SANITIZER) - // Zap the unused portion, until it is either compacted into or freed. - if (current_page != this) { - FreeList::ZapFreedMemory(Payload(), PayloadSize()); - } else { - FreeList::ZapFreedMemory(Payload() + allocation_point, - PayloadSize() - allocation_point); - } -#endif -} - -void NormalPage::MakeConsistentForMutator() { - object_start_bit_map()->Clear(); - Address start_of_gap = Payload(); - NormalPageArena* normal_arena = ArenaForNormalPage(); - size_t live_bytes = 0; - for (Address header_address = Payload(); header_address < PayloadEnd();) { - HeapObjectHeader* header = - reinterpret_cast<HeapObjectHeader*>(header_address); - size_t size = header->size(); - DCHECK_LT(size, BlinkPagePayloadSize()); - if (header->IsFree()) { - // Zero the memory in the free list header to maintain the - // invariant that memory on the free list is zero filled. - // The rest of the memory is already on the free list and is - // therefore already zero filled. - SET_MEMORY_INACCESSIBLE(header_address, size < sizeof(FreeListEntry) - ? size - : sizeof(FreeListEntry)); - CHECK_MEMORY_INACCESSIBLE(header_address, size); - header_address += size; - continue; - } - if (start_of_gap != header_address) - normal_arena->AddToFreeList(start_of_gap, header_address - start_of_gap); - if (header->IsMarked()) { - header->Unmark(); - } - object_start_bit_map()->SetBit(header_address); - live_bytes += size; - header_address += size; - start_of_gap = header_address; - DCHECK_LE(header_address, PayloadEnd()); - } - SetAllocatedBytes(live_bytes); - if (start_of_gap != PayloadEnd()) - normal_arena->AddToFreeList(start_of_gap, PayloadEnd() - start_of_gap); - - VerifyObjectStartBitmapIsConsistentWithPayload(); -} - -// This is assumed to be called from the atomic pause, so no concurrency should -// be involved here. -void NormalPage::Unmark() { - const Address current_allocation_point = - ArenaForNormalPage()->CurrentAllocationPoint(); - const size_t allocation_area_size = - ArenaForNormalPage()->RemainingAllocationSize(); - for (Address header_address = Payload(); header_address < PayloadEnd();) { - // Since unmarking can happen inside IncrementalMarkingStart, the current - // allocation point can be set and we need to skip over it. - if (header_address == current_allocation_point && allocation_area_size) { - header_address += allocation_area_size; - continue; - } - HeapObjectHeader* header = - reinterpret_cast<HeapObjectHeader*>(header_address); - if (header->IsMarked()) { - header->Unmark(); - } - header_address += header->size(); - } - ClearCardTable(); -} - -#if defined(ADDRESS_SANITIZER) -void NormalPage::PoisonUnmarkedObjects() { - for (Address header_address = Payload(); header_address < PayloadEnd();) { - HeapObjectHeader* header = - reinterpret_cast<HeapObjectHeader*>(header_address); - DCHECK_LT(header->size(), BlinkPagePayloadSize()); - // Check if a free list entry first since we cannot call - // isMarked on a free list entry. - if (header->IsFree()) { - header_address += header->size(); - continue; - } - if (!header->IsMarked()) { - ASAN_POISON_MEMORY_REGION(header->Payload(), header->PayloadSize()); - } - header_address += header->size(); - } -} -#endif - -void NormalPage::VerifyObjectStartBitmapIsConsistentWithPayload() { -#if DCHECK_IS_ON() - HeapObjectHeader* current_header = - reinterpret_cast<HeapObjectHeader*>(Payload()); - object_start_bit_map()->Iterate([this, - ¤t_header](Address object_address) { - const HeapObjectHeader* object_header = - reinterpret_cast<HeapObjectHeader*>(object_address); - DCHECK_EQ(object_header, current_header); - current_header = reinterpret_cast<HeapObjectHeader*>(object_address + - object_header->size()); - // Skip over allocation area. - if (reinterpret_cast<Address>(current_header) == - ArenaForNormalPage()->CurrentAllocationPoint()) { - current_header = reinterpret_cast<HeapObjectHeader*>( - ArenaForNormalPage()->CurrentAllocationPoint() + - ArenaForNormalPage()->RemainingAllocationSize()); - } - }); -#endif // DCHECK_IS_ON() -} - -void NormalPage::VerifyMarking() { - DCHECK(!ArenaForNormalPage()->CurrentAllocationPoint()); - MarkingVerifier verifier(ArenaForNormalPage()->GetThreadState()); - for (Address header_address = Payload(); header_address < PayloadEnd();) { - HeapObjectHeader* header = - reinterpret_cast<HeapObjectHeader*>(header_address); - verifier.VerifyObject(header); - header_address += header->size(); - } -} - -void LargeObjectPage::VerifyMarking() { - MarkingVerifier verifier(Arena()->GetThreadState()); - verifier.VerifyObject(ObjectHeader()); -} - -HeapObjectHeader* NormalPage::ConservativelyFindHeaderFromAddress( - ConstAddress address) const { - if (!ContainedInObjectPayload(address)) - return nullptr; - if (ArenaForNormalPage()->IsInCurrentAllocationPointRegion(address)) - return nullptr; - HeapObjectHeader* header = reinterpret_cast<HeapObjectHeader*>( - object_start_bit_map()->FindHeader(address)); - if (header->IsFree()) - return nullptr; - DCHECK_LT(0u, header->GcInfoIndex()); - DCHECK_GT(header->PayloadEnd(), address); - return header; -} - -void NormalPage::CollectStatistics( - ThreadState::Statistics::ArenaStatistics* arena_stats) { - HeapObjectHeader* header = nullptr; - size_t live_size = 0; - for (Address header_address = Payload(); header_address < PayloadEnd(); - header_address += header->size()) { - header = reinterpret_cast<HeapObjectHeader*>(header_address); - if (!header->IsFree()) { - // All non-free objects, dead or alive, are considered as live for the - // purpose of taking a snapshot. - live_size += header->size(); - if (!NameClient::HideInternalName()) { - // Detailed names available. - uint32_t gc_info_index = header->GcInfoIndex(); - arena_stats->object_stats.type_count[gc_info_index]++; - arena_stats->object_stats.type_bytes[gc_info_index] += header->size(); - if (arena_stats->object_stats.type_name[gc_info_index].empty()) { - arena_stats->object_stats.type_name[gc_info_index] = header->Name(); - } - } - } - } - DCHECK_EQ(live_size, AllocatedBytes()); - arena_stats->committed_size_bytes += kBlinkPageSize; - arena_stats->used_size_bytes += live_size; - arena_stats->page_stats.emplace_back( - ThreadState::Statistics::PageStatistics{kBlinkPageSize, live_size}); -} - -#if DCHECK_IS_ON() -bool NormalPage::Contains(ConstAddress addr) const { - Address blink_page_start = RoundToBlinkPageStart(GetAddress()); - // Page is at aligned address plus guard page size. - DCHECK_EQ(blink_page_start, GetAddress() - BlinkGuardPageSize()); - return blink_page_start <= addr && addr < blink_page_start + kBlinkPageSize; -} -#endif - -LargeObjectPage::LargeObjectPage(PageMemory* storage, - BaseArena* arena, - size_t object_size) - : BasePage(storage, arena, PageType::kLargeObjectPage), - object_size_(object_size) -#ifdef ANNOTATE_CONTIGUOUS_CONTAINER - , - is_vector_backing_page_(false) -#endif -{ -} - -size_t LargeObjectPage::ObjectPayloadSizeForTesting() { - return PayloadSize(); -} - -void LargeObjectPage::RemoveFromHeap() { - static_cast<LargeObjectArena*>(Arena())->FreeLargeObjectPage(this); -} - -bool LargeObjectPage::Sweep(FinalizeType) { - if (!ObjectHeader()->IsMarked()) { - SetAllocatedBytes(0u); - return true; - } -#if !BUILDFLAG(BLINK_HEAP_YOUNG_GENERATION) - ObjectHeader()->Unmark(); -#endif - DCHECK_EQ(AllocatedBytes(), ObjectSize()); - return false; -} - -void LargeObjectPage::Unmark() { - HeapObjectHeader* header = ObjectHeader(); - if (header->IsMarked()) { - header->Unmark(); - } - SetRemembered(false); -} - -void LargeObjectPage::MakeConsistentForMutator() { - Unmark(); - DCHECK_EQ(AllocatedBytes(), ObjectSize()); -} - -void LargeObjectPage::FinalizeSweep(SweepResult action) { - if (action == SweepResult::kPageNotEmpty) { - MarkAsSwept(); - } else { - DCHECK(action == SweepResult::kPageEmpty); - RemoveFromHeap(); - } -} - -#if defined(ADDRESS_SANITIZER) -void LargeObjectPage::PoisonUnmarkedObjects() { - HeapObjectHeader* header = ObjectHeader(); - if (!header->IsMarked()) { - ASAN_POISON_MEMORY_REGION(header->Payload(), header->PayloadSize()); - } -} -#endif - -void LargeObjectPage::CollectStatistics( - ThreadState::Statistics::ArenaStatistics* arena_stats) { - HeapObjectHeader* header = ObjectHeader(); - // All non-free objects, dead or alive, are considered as live for the - // purpose of taking a snapshot. - size_t live_size = ObjectSize(); - if (!NameClient::HideInternalName()) { - // Detailed names available. - uint32_t gc_info_index = header->GcInfoIndex(); - arena_stats->object_stats.type_count[gc_info_index]++; - arena_stats->object_stats.type_bytes[gc_info_index] += live_size; - } - DCHECK_EQ(live_size, AllocatedBytes()); - arena_stats->committed_size_bytes += size(); - arena_stats->used_size_bytes += live_size; - arena_stats->page_stats.emplace_back( - ThreadState::Statistics::PageStatistics{size(), live_size}); -} - -#if DCHECK_IS_ON() -bool LargeObjectPage::Contains(ConstAddress object) const { - return RoundToBlinkPageStart(GetAddress()) <= object && - object < RoundToBlinkPageEnd(GetAddress() + size()); -} -#endif - -} // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/impl/heap_page.h b/third_party/blink/renderer/platform/heap/impl/heap_page.h deleted file mode 100644 index f68c999..0000000 --- a/third_party/blink/renderer/platform/heap/impl/heap_page.h +++ /dev/null
@@ -1,1632 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_HEAP_PAGE_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_HEAP_PAGE_H_ - -#include <stdint.h> -#include <array> -#include <atomic> - -#include "base/bits.h" -#include "base/compiler_specific.h" -#include "base/dcheck_is_on.h" -#include "build/build_config.h" -#include "third_party/blink/renderer/platform/heap/blink_gc.h" -#include "third_party/blink/renderer/platform/heap/garbage_collected.h" -#include "third_party/blink/renderer/platform/heap/heap_buildflags.h" -#include "third_party/blink/renderer/platform/heap/impl/gc_info.h" -#include "third_party/blink/renderer/platform/heap/impl/thread_state_statistics.h" -#include "third_party/blink/renderer/platform/heap/impl/unsanitized_atomic.h" -#include "third_party/blink/renderer/platform/heap/thread_state.h" -#include "third_party/blink/renderer/platform/heap/visitor.h" -#include "third_party/blink/renderer/platform/platform_export.h" -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" -#include "third_party/blink/renderer/platform/wtf/allocator/partitions.h" -#include "third_party/blink/renderer/platform/wtf/container_annotations.h" -#include "third_party/blink/renderer/platform/wtf/forward.h" -#include "third_party/blink/renderer/platform/wtf/sanitizers.h" -#include "third_party/blink/renderer/platform/wtf/threading_primitives.h" - -namespace blink { - -// TODO(palmer): Document the reason for 17. -constexpr size_t kBlinkPageSizeLog2 = 17; -constexpr size_t kBlinkPageSize = 1 << kBlinkPageSizeLog2; -constexpr size_t kBlinkPageOffsetMask = kBlinkPageSize - 1; -constexpr size_t kBlinkPageBaseMask = ~kBlinkPageOffsetMask; - -// We allocate pages at random addresses but in groups of kBlinkPagesPerRegion -// at a given random address. We group pages to not spread out too much over the -// address space which would blow away the page tables and lead to bad -// performance. -constexpr size_t kBlinkPagesPerRegion = 10; - -// TODO(nya): Replace this with something like #if ENABLE_NACL. -#if defined(ARCH_CPU_PPC64) -// NaCl's system page size is 64 KiB. This causes a problem in Oilpan's heap -// layout because Oilpan allocates two guard pages for each Blink page (whose -// size is kBlinkPageSize = 2^17 = 128 KiB). So we don't use guard pages in -// NaCl. -// The same issue holds for ppc64 systems, which use a 64k page size. -PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR ALWAYS_INLINE size_t -BlinkGuardPageSize() { - return 0; -} -#else -PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR ALWAYS_INLINE size_t -BlinkGuardPageSize() { - return base::SystemPageSize(); -} -#endif - -// Double precision floats are more efficient when 8-byte aligned, so we 8-byte -// align all allocations (even on 32 bit systems). -static_assert(8 == sizeof(double), "We expect sizeof(double) to be 8"); -constexpr size_t kAllocationGranularity = sizeof(double); -constexpr size_t kAllocationMask = kAllocationGranularity - 1; -constexpr size_t kLargeObjectSizeThreshold = kBlinkPageSize / 2; - -// A zap value used for freed memory that is allowed to be added to the free -// list in the next call to AddToFreeList. -constexpr uint8_t kReuseAllowedZapValue = 0x2a; -// A zap value used for freed memory that is forbidden to be added to the free -// list in the next call to AddToFreeList. -constexpr uint8_t kReuseForbiddenZapValue = 0x2c; - -// In non-production builds, memory is zapped when it's freed. The zapped memory -// is zeroed out when the memory is reused in ThreadHeap::AllocateObject. -// -// In production builds, memory is not zapped (for performance). The memory is -// just zeroed out when it is added to the free list. -#if defined(MEMORY_SANITIZER) -// TODO(kojii): We actually need __msan_poison/unpoison here, but it'll be -// added later. -#define SET_MEMORY_INACCESSIBLE(address, size) \ - FreeList::ZapFreedMemory(address, size); -#define SET_MEMORY_ACCESSIBLE(address, size) memset((address), 0, (size)) -#define CHECK_MEMORY_INACCESSIBLE(address, size) \ - ASAN_UNPOISON_MEMORY_REGION(address, size); \ - FreeList::CheckFreedMemoryIsZapped(address, size); \ - ASAN_POISON_MEMORY_REGION(address, size) -#elif DCHECK_IS_ON() || defined(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER) -#define SET_MEMORY_INACCESSIBLE(address, size) \ - FreeList::ZapFreedMemory(address, size); \ - ASAN_POISON_MEMORY_REGION(address, size) -#define SET_MEMORY_ACCESSIBLE(address, size) \ - ASAN_UNPOISON_MEMORY_REGION(address, size); \ - memset((address), 0, (size)) -#define CHECK_MEMORY_INACCESSIBLE(address, size) \ - ASAN_UNPOISON_MEMORY_REGION(address, size); \ - FreeList::CheckFreedMemoryIsZapped(address, size); \ - ASAN_POISON_MEMORY_REGION(address, size) -#else -#define SET_MEMORY_INACCESSIBLE(address, size) memset((address), 0, (size)) -#define SET_MEMORY_ACCESSIBLE(address, size) \ - do { \ - } while (false) -#define CHECK_MEMORY_INACCESSIBLE(address, size) \ - do { \ - } while (false) -#endif - -class NormalPageArena; -class PageMemory; -class BaseArena; -class ThreadHeap; - -// HeapObjectHeader is a 32-bit object that has the following layout: -// -// | padding (32 bits) | Only present on 64-bit platforms. -// | gc_info_index (14 bits) | -// | unused (1 bit) | -// | in construction (1 bit) | true: bit not set; false bit set -// -// | size (14 bits) | Actually 17 bits because sizes are aligned. -// | unused (1 bit) | -// | mark bit (1 bit) | -// -// Notes: -// - 14 bits for |gc_info_index} (type information) are enough as there are -// fewer than 2^14 types allocated in Blink. -// - |size| for regular objects is encoded with 14 bits but can actually -// represent sizes up to |kBlinkPageSize| (2^17) because allocations are -// always 8 byte aligned (see kAllocationGranularity). -// - |size| for large objects is encoded as 0. The size of a large object is -// stored in |LargeObjectPage::PayloadSize()|. -// - |mark bit| and |in construction| bits are located in separate variables and -// therefore can be accessed concurrently. Since tsan works with word-size -// objects they still should be accessed atomically. -constexpr uint16_t kHeaderMarkBitMask = 1; -constexpr uint16_t kHeaderSizeShift = 2; -constexpr uint16_t kHeaderSizeMask = - static_cast<uint16_t>(((1 << 14) - 1) << kHeaderSizeShift); - -constexpr uint16_t kHeaderIsInConstructionMask = 1; -constexpr uint16_t kHeaderGCInfoIndexShift = 2; -constexpr uint16_t kHeaderGCInfoSize = static_cast<uint16_t>(1 << 14); -constexpr uint16_t kHeaderGCInfoIndexMask = - static_cast<uint16_t>((kHeaderGCInfoSize - 1) << kHeaderGCInfoIndexShift); - -constexpr uint16_t kLargeObjectSizeInHeader = 0; -constexpr uint16_t kGcInfoIndexForFreeListHeader = 0; -constexpr size_t kNonLargeObjectPageSizeMax = 1 << kBlinkPageSizeLog2; - -static_assert(kHeaderGCInfoSize == GCInfoTable::kMaxIndex, - "GCInfoTable size and and header GCInfo index size must match"); - -static_assert( - kNonLargeObjectPageSizeMax >= kBlinkPageSize, - "max size supported by HeapObjectHeader must at least be kBlinkPageSize"); - -namespace internal { - -NO_SANITIZE_ADDRESS constexpr uint16_t EncodeSize(size_t size) { - // Essentially, gets optimized to >> 1. - return static_cast<uint16_t>((size << kHeaderSizeShift) / - kAllocationGranularity); -} - -NO_SANITIZE_ADDRESS constexpr size_t DecodeSize(uint16_t encoded) { - // Essentially, gets optimized to << 1. - return ((encoded & kHeaderSizeMask) >> kHeaderSizeShift) * - kAllocationGranularity; -} - -} // namespace internal - -class PLATFORM_EXPORT HeapObjectHeader { - DISALLOW_NEW(); - - public: - enum class AccessMode : uint8_t { kNonAtomic, kAtomic }; - - static HeapObjectHeader* FromPayload(const void*); - template <AccessMode = AccessMode::kNonAtomic> - static HeapObjectHeader* FromInnerAddress(const void*); - - // Checks sanity of the header given a payload pointer. - static void CheckFromPayload(const void*); - - // If |gc_info_index| is 0, this header is interpreted as a free list header. - HeapObjectHeader(size_t, size_t); - - template <AccessMode mode = AccessMode::kNonAtomic> - NO_SANITIZE_ADDRESS bool IsFree() const { - return GcInfoIndex<mode>() == kGcInfoIndexForFreeListHeader; - } - - template <AccessMode mode = AccessMode::kNonAtomic> - NO_SANITIZE_ADDRESS uint32_t GcInfoIndex() const { - const uint16_t encoded = - LoadEncoded<mode, EncodedHalf::kHigh, std::memory_order_acquire>(); - return (encoded & kHeaderGCInfoIndexMask) >> kHeaderGCInfoIndexShift; - } - - template <AccessMode = AccessMode::kNonAtomic> - size_t size() const; - void SetSize(size_t size); - - template <AccessMode = AccessMode::kNonAtomic> - bool IsLargeObject() const; - - template <AccessMode = AccessMode::kNonAtomic> - bool IsMarked() const; - template <AccessMode = AccessMode::kNonAtomic> - void Unmark(); - template <AccessMode = AccessMode::kNonAtomic> - bool TryMark(); - - template <AccessMode = AccessMode::kNonAtomic> - bool IsOld() const; - - template <AccessMode = AccessMode::kNonAtomic> - bool IsInConstruction() const; - template <AccessMode = AccessMode::kNonAtomic> - void MarkFullyConstructed(); - - // The payload starts directly after the HeapObjectHeader, and the payload - // size does not include the sizeof(HeapObjectHeader). - Address Payload() const; - size_t PayloadSize() const; - template <AccessMode = AccessMode::kNonAtomic> - Address PayloadEnd() const; - - void Finalize(Address, size_t); - - // Returns true if object has finalizer. - bool HasNonTrivialFinalizer() const; - - // Returns a human-readable name of this object. - const char* Name() const; - - private: - enum class EncodedHalf : uint8_t { kLow, kHigh }; - - template <AccessMode, - EncodedHalf part, - std::memory_order = std::memory_order_seq_cst> - uint16_t LoadEncoded() const; - template <AccessMode mode, - EncodedHalf part, - std::memory_order = std::memory_order_seq_cst> - void StoreEncoded(uint16_t bits, uint16_t mask); - -#if defined(ARCH_CPU_64_BITS) - uint32_t padding_ = 0; -#endif // defined(ARCH_CPU_64_BITS) - uint16_t encoded_high_; - uint16_t encoded_low_; -}; - -class FreeListEntry final : public HeapObjectHeader { - public: - NO_SANITIZE_ADDRESS - explicit FreeListEntry(size_t size) - : HeapObjectHeader(size, kGcInfoIndexForFreeListHeader), next_(nullptr) {} - - Address GetAddress() { return reinterpret_cast<Address>(this); } - - NO_SANITIZE_ADDRESS - void Unlink(FreeListEntry** previous_next) { - *previous_next = next_; - next_ = nullptr; - } - - NO_SANITIZE_ADDRESS - void Link(FreeListEntry** previous_next) { - next_ = *previous_next; - *previous_next = this; - } - - NO_SANITIZE_ADDRESS - FreeListEntry* Next() const { return next_; } - - NO_SANITIZE_ADDRESS - void Append(FreeListEntry* next) { - DCHECK(!next_); - next_ = next; - } - - private: - FreeListEntry* next_; - - friend class FreeList; -}; - -class FreeList { - DISALLOW_NEW(); - - public: - // Returns a bucket number for inserting a |FreeListEntry| of a given size. - // All entries in the given bucket, n, have size >= 2^n. - static int BucketIndexForSize(size_t); - -#if DCHECK_IS_ON() || defined(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER) || \ - defined(MEMORY_SANITIZER) - static void GetAllowedAndForbiddenCounts(Address, size_t, size_t&, size_t&); - static void ZapFreedMemory(Address, size_t); - static void CheckFreedMemoryIsZapped(Address, size_t); -#endif - - FreeList(); - - FreeListEntry* Allocate(size_t); - void Add(Address, size_t); - void MoveFrom(FreeList*); - void Clear(); - - bool IsEmpty() const; - size_t FreeListSize() const; - - void CollectStatistics(ThreadState::Statistics::FreeListStatistics*); - - template <typename Predicate> - FreeListEntry* FindEntry(Predicate pred) { - for (size_t i = 0; i < kBlinkPageSizeLog2; ++i) { - for (FreeListEntry* entry = free_list_heads_[i]; entry; - entry = entry->Next()) { - if (pred(entry)) { - return entry; - } - } - } - return nullptr; - } - - private: - bool IsConsistent(size_t index) const { - return (!free_list_heads_[index] && !free_list_tails_[index]) || - (free_list_heads_[index] && free_list_tails_[index] && - !free_list_tails_[index]->Next()); - } - - // All |FreeListEntry|s in the nth list have size >= 2^n. - FreeListEntry* free_list_heads_[kBlinkPageSizeLog2]; - FreeListEntry* free_list_tails_[kBlinkPageSizeLog2]; - int biggest_free_list_index_; -}; - -// Blink heap pages are set up with a guard page before and after the payload. -PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR ALWAYS_INLINE size_t -BlinkPagePayloadSize() { - return kBlinkPageSize - 2 * BlinkGuardPageSize(); -} - -// Blink heap pages are aligned to the Blink heap page size. Therefore, the -// start of a Blink page can be obtained by rounding down to the Blink page -// size. -inline Address RoundToBlinkPageStart(Address address) { - return reinterpret_cast<Address>(reinterpret_cast<uintptr_t>(address) & - kBlinkPageBaseMask); -} - -inline Address RoundToBlinkPageEnd(Address address) { - return reinterpret_cast<Address>(reinterpret_cast<uintptr_t>(address - 1) & - kBlinkPageBaseMask) + - kBlinkPageSize; -} - -// Masks an address down to the enclosing Blink page base address. -inline Address BlinkPageAddress(Address address) { - return reinterpret_cast<Address>(reinterpret_cast<uintptr_t>(address) & - kBlinkPageBaseMask); -} - -inline bool VTableInitialized(const void* object_pointer) { - return !!(*reinterpret_cast<const ConstAddress*>(object_pointer)); -} - -#if DCHECK_IS_ON() - -// Sanity check for a page header address: the address of the page header should -// be 1 OS page size away from being Blink page size-aligned. -inline bool IsPageHeaderAddress(Address address) { - return !((reinterpret_cast<uintptr_t>(address) & kBlinkPageOffsetMask) - - BlinkGuardPageSize()); -} - -#endif - -// |FinalizeType| specifies when finalization should take place. -// In case of concurrent sweeper we defer finalization to be done -// on the main thread. -enum class FinalizeType : uint8_t { kInlined, kDeferred }; - -// |SweepResult| indicates if page turned out to be empty after sweeping. -enum class SweepResult : uint8_t { kPageEmpty, kPageNotEmpty }; - -// |PageType| indicates whether a page is used for normal objects or whether it -// holds a large object. -enum class PageType : uint8_t { kNormalPage, kLargeObjectPage }; - -// |BasePage| is a base class for |NormalPage| and |LargeObjectPage|. -// -// - |NormalPage| is a page whose size is |kBlinkPageSize|. A |NormalPage| can -// contain multiple objects. An object whose size is smaller than -// |kLargeObjectSizeThreshold| is stored in a |NormalPage|. -// -// - |LargeObjectPage| is a page that contains only one object. The object size -// is arbitrary. An object whose size is larger than |kBlinkPageSize| is -// stored as a single project in |LargeObjectPage|. -// -// Note: An object whose size is between |kLargeObjectSizeThreshold| and -// |kBlinkPageSize| can go to either of |NormalPage| or |LargeObjectPage|. -class BasePage { - DISALLOW_NEW(); - - public: - BasePage(PageMemory*, BaseArena*, PageType); - virtual ~BasePage() = default; - - // Virtual methods are slow. So performance-sensitive methods should be - // defined as non-virtual methods on |NormalPage| and |LargeObjectPage|. The - // following methods are not performance-sensitive. - virtual size_t ObjectPayloadSizeForTesting() = 0; - virtual void RemoveFromHeap() = 0; - // Sweeps a page. Returns true when that page is empty and false otherwise. - // Does not create free list entries for empty pages. - virtual bool Sweep(FinalizeType) = 0; - virtual void MakeConsistentForMutator() = 0; - virtual void Unmark() = 0; - - // Calls finalizers after sweeping is done. - virtual void FinalizeSweep(SweepResult) = 0; - -#if defined(ADDRESS_SANITIZER) - virtual void PoisonUnmarkedObjects() = 0; -#endif - - virtual void CollectStatistics( - ThreadState::Statistics::ArenaStatistics* arena_stats) = 0; - -#if DCHECK_IS_ON() - virtual bool Contains(ConstAddress) const = 0; -#endif - virtual size_t size() const = 0; - - Address GetAddress() const { - return reinterpret_cast<Address>(const_cast<BasePage*>(this)); - } - PageMemory* Storage() const { return storage_; } - BaseArena* Arena() const { return arena_; } - ThreadState* thread_state() const { return thread_state_; } - - // Returns true if this page has been swept by the ongoing sweep; false - // otherwise. - bool HasBeenSwept() const { return swept_; } - - void MarkAsSwept() { - DCHECK(!swept_); - swept_ = true; - } - - void MarkAsUnswept() { - DCHECK(swept_); - swept_ = false; - } - - // Returns true if this page is a large object page; false otherwise. - bool IsLargeObjectPage() const { - return page_type_ == PageType::kLargeObjectPage; - } - - // Young pages are pages that contain at least a single young object. - bool IsYoung() const { return is_young_; } - - void SetAsYoung(bool young) { is_young_ = young; } - - // The number of bytes that allocated on the page and are not freed yet. - size_t AllocatedBytes() { return allocated_bytes_; } - - void SetAllocatedBytes(size_t bytes) { allocated_bytes_ = bytes; } - - void IncreaseAllocatedBytes(size_t bytes) { allocated_bytes_ += bytes; } - - void DecreaseAllocatedBytes(size_t bytes) { - DCHECK_GE(allocated_bytes_, bytes); - allocated_bytes_ -= bytes; - } - - virtual void VerifyMarking() = 0; - - private: - void SynchronizedLoad() { -#if defined(THREAD_SANITIZER) - WTF::AsAtomicPtr(&page_type_)->load(std::memory_order_acquire); -#endif - } - void SynchronizedStore() { - std::atomic_thread_fence(std::memory_order_seq_cst); -#if defined(THREAD_SANITIZER) - WTF::AsAtomicPtr(&page_type_)->store(page_type_, std::memory_order_release); -#endif - } - - PageMemory* const storage_; - BaseArena* const arena_; - ThreadState* const thread_state_; - - // The counter is updated by the sweeper and the allocator. - // It is the sum of objects marked at the last GC and objects allocated on - // the page since the last GC. - size_t allocated_bytes_ = 0; - - // Track the sweeping state of a page. Set to false at the start of a sweep, - // true upon completion of sweeping that page. - bool swept_ = true; - bool is_young_ = false; - - PageType page_type_; - - friend class BaseArena; - friend class HeapObjectHeader; - friend class ThreadHeap; -}; - -class PageStack : Vector<BasePage*> { - using Base = Vector<BasePage*>; - - public: - PageStack() = default; - - void Push(BasePage* page) { push_back(page); } - - BasePage* Pop() { - if (IsEmpty()) - return nullptr; - BasePage* top = back(); - pop_back(); - return top; - } - - BasePage* Top() const { - if (IsEmpty()) - return nullptr; - return back(); - } - - using Base::begin; - using Base::end; - - using Base::clear; - using Base::erase; - - using Base::IsEmpty; - using Base::size; -}; - -class PageStackThreadSafe : public PageStack { - public: - void PushLocked(BasePage* page) { - WTF::MutexLocker locker(mutex_); - Push(page); - } - - BasePage* PopLocked() { - WTF::MutexLocker locker(mutex_); - return Pop(); - } - - bool IsEmptyLocked() const { - WTF::MutexLocker locker(mutex_); - return IsEmpty(); - } - - // Explicit unsafe move assignment. - void MoveFrom(PageStack&& other) { PageStack::operator=(std::move(other)); } - - private: - mutable WTF::Mutex mutex_; -}; - -// A bitmap for recording object starts. Objects have to be allocated at -// minimum granularity of kGranularity. -// -// Depends on internals such as: -// - kBlinkPageSize -// - kAllocationGranularity -class PLATFORM_EXPORT ObjectStartBitmap { - USING_FAST_MALLOC(ObjectStartBitmap); - - public: - // Granularity of addresses added to the bitmap. - static constexpr size_t Granularity() { return kAllocationGranularity; } - - // Maximum number of entries in the bitmap. - static constexpr size_t MaxEntries() { - return kReservedForBitmap * kCellSize; - } - - explicit ObjectStartBitmap(Address offset); - - // Finds an object header based on a - // address_maybe_pointing_to_the_middle_of_object. Will search for an object - // start in decreasing address order. - template < - HeapObjectHeader::AccessMode = HeapObjectHeader::AccessMode::kNonAtomic> - Address FindHeader( - ConstAddress address_maybe_pointing_to_the_middle_of_object) const; - - template < - HeapObjectHeader::AccessMode = HeapObjectHeader::AccessMode::kNonAtomic> - inline void SetBit(Address); - template < - HeapObjectHeader::AccessMode = HeapObjectHeader::AccessMode::kNonAtomic> - inline void ClearBit(Address); - template < - HeapObjectHeader::AccessMode = HeapObjectHeader::AccessMode::kNonAtomic> - inline bool CheckBit(Address) const; - - // Iterates all object starts recorded in the bitmap. - // - // The callback is of type - // void(Address) - // and is passed the object start address as parameter. - template <typename Callback> - inline void Iterate(Callback) const; - - // Clear the object start bitmap. - void Clear(); - - private: - template < - HeapObjectHeader::AccessMode = HeapObjectHeader::AccessMode::kNonAtomic> - void store(size_t cell_index, uint8_t value); - template < - HeapObjectHeader::AccessMode = HeapObjectHeader::AccessMode::kNonAtomic> - uint8_t load(size_t cell_index) const; - - static const size_t kCellSize = sizeof(uint8_t) * 8; - static const size_t kCellMask = sizeof(uint8_t) * 8 - 1; - static const size_t kBitmapSize = - (kBlinkPageSize + ((kCellSize * kAllocationGranularity) - 1)) / - (kCellSize * kAllocationGranularity); - static const size_t kReservedForBitmap = - ((kBitmapSize + kAllocationMask) & ~kAllocationMask); - - inline void ObjectStartIndexAndBit(Address, size_t*, size_t*) const; - - Address offset_; - // The bitmap contains a bit for every kGranularity aligned address on a - // a NormalPage, i.e., for a page of size kBlinkPageSize. - uint8_t object_start_bit_map_[kReservedForBitmap]; -}; - -// A platform aware version of ObjectStartBitmap to provide platform specific -// optimizations (e.g. Use non-atomic stores on ARMv7 when not marking). -class PLATFORM_EXPORT PlatformAwareObjectStartBitmap - : public ObjectStartBitmap { - USING_FAST_MALLOC(PlatformAwareObjectStartBitmap); - - public: - explicit PlatformAwareObjectStartBitmap(Address offset); - - template < - HeapObjectHeader::AccessMode = HeapObjectHeader::AccessMode::kNonAtomic> - inline void SetBit(Address); - template < - HeapObjectHeader::AccessMode = HeapObjectHeader::AccessMode::kNonAtomic> - inline void ClearBit(Address); - - private: - template <HeapObjectHeader::AccessMode> - static bool ShouldForceNonAtomic(); -}; - -class PLATFORM_EXPORT NormalPage final : public BasePage { - public: - NormalPage(PageMemory*, BaseArena*); - ~NormalPage() override; - - Address Payload() const { return GetAddress() + PageHeaderSize(); } - static PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR ALWAYS_INLINE size_t - PayloadSize() { - return (BlinkPagePayloadSize() - PageHeaderSize()) & ~kAllocationMask; - } - Address PayloadEnd() const { return Payload() + PayloadSize(); } - bool ContainedInObjectPayload(ConstAddress address) const { - return Payload() <= address && address < PayloadEnd(); - } - - size_t ObjectPayloadSizeForTesting() override; - void RemoveFromHeap() override; - bool Sweep(FinalizeType) override; - void MakeConsistentForMutator() override; - void Unmark() override; - void FinalizeSweep(SweepResult) override; -#if defined(ADDRESS_SANITIZER) - void PoisonUnmarkedObjects() override; -#endif - - void CollectStatistics( - ThreadState::Statistics::ArenaStatistics* arena_stats) override; - -#if DCHECK_IS_ON() - // Returns true for the whole |kBlinkPageSize| page that the page is on, even - // for the header, and the unmapped guard page at the start. That ensures the - // result can be used to populate the negative page cache. - bool Contains(ConstAddress) const override; -#endif - size_t size() const override { return kBlinkPageSize; } - static constexpr size_t PageHeaderSize() { - // Compute the amount of padding we have to add to a header to make the size - // of the header plus the padding a multiple of 8 bytes. - constexpr size_t kPaddingSize = - (sizeof(NormalPage) + kAllocationGranularity - - (sizeof(HeapObjectHeader) % kAllocationGranularity)) % - kAllocationGranularity; - return sizeof(NormalPage) + kPaddingSize; - } - - inline NormalPageArena* ArenaForNormalPage() const; - - // Context object holding the state of the arena page compaction pass, passed - // in when compacting individual pages. - class CompactionContext { - STACK_ALLOCATED(); - - public: - // Page compacting into. - NormalPage* current_page_ = nullptr; - // Offset into |current_page_| to the next free address. - size_t allocation_point_ = 0; - // Vector of available pages to use for compaction. Page compaction picks - // the next one when the current one is exhausted. - PageStack available_pages_; - // Vector of pages that have been compacted. Page compaction will add - // compacted pages once the current one becomes exhausted. - PageStack* compacted_pages_; - }; - - void SweepAndCompact(CompactionContext&); - - // Object start bitmap of this page. - PlatformAwareObjectStartBitmap* object_start_bit_map() { - return &object_start_bit_map_; - } - const PlatformAwareObjectStartBitmap* object_start_bit_map() const { - return &object_start_bit_map_; - } - - // Verifies that the object start bitmap only contains a bit iff the object - // is also reachable through iteration on the page. - void VerifyObjectStartBitmapIsConsistentWithPayload(); - - // Uses the object_start_bit_map_ to find an object for a given address. The - // returned header is either nullptr, indicating that no object could be - // found, or it is pointing to valid object or free list entry. - // This method is called only during stack scanning when there are no - // concurrent markers, thus no atomics required. - HeapObjectHeader* ConservativelyFindHeaderFromAddress(ConstAddress) const; - - // Uses the object_start_bit_map_ to find an object for a given address. It is - // assumed that the address points into a valid heap object. Use the - // conservative version if that assumption does not hold. - template < - HeapObjectHeader::AccessMode = HeapObjectHeader::AccessMode::kNonAtomic> - HeapObjectHeader* FindHeaderFromAddress(ConstAddress) const; - - void VerifyMarking() override; - - // Marks a card corresponding to address. - void MarkCard(Address address); - - // Iterates over all objects in marked cards. - template <typename Function> - void IterateCardTable(Function function) const; - - // Clears all bits in the card table. - void ClearCardTable() { card_table_.Clear(); } - - private: - // Data structure that divides a page in a number of cards each of 512 bytes - // size. Marked cards are stored in bytes, not bits, to make write barrier - // faster and reduce chances of false sharing. This gives only ~0.1% of memory - // overhead. Also, since there are guard pages before and after a Blink page, - // some of card bits are wasted and unneeded. - class CardTable final { - public: - struct value_type { - uint8_t bit; - size_t index; - }; - - struct iterator { - iterator& operator++() { - ++index; - return *this; - } - value_type operator*() const { return {table->table_[index], index}; } - bool operator!=(iterator other) const { - return table != other.table || index != other.index; - } - - size_t index = 0; - const CardTable* table = nullptr; - }; - - using const_iterator = iterator; - - static constexpr size_t kBitsPerCard = 9; - static constexpr size_t kCardSize = 1 << kBitsPerCard; - - const_iterator begin() const { return {FirstPayloadCard(), this}; } - const_iterator end() const { return {LastPayloadCard(), this}; } - - void Mark(size_t card) { - DCHECK_LE(FirstPayloadCard(), card); - DCHECK_GT(LastPayloadCard(), card); - table_[card] = 1; - } - - bool IsMarked(size_t card) const { - DCHECK_LE(FirstPayloadCard(), card); - DCHECK_GT(LastPayloadCard(), card); - return table_[card]; - } - - void Clear() { std::fill(table_.begin(), table_.end(), 0); } - - private: - static PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR ALWAYS_INLINE size_t - FirstPayloadCard() { - return (BlinkGuardPageSize() + NormalPage::PageHeaderSize()) / kCardSize; - } - static PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR ALWAYS_INLINE size_t - LastPayloadCard() { - return (BlinkGuardPageSize() + BlinkPagePayloadSize()) / kCardSize; - } - - std::array<uint8_t, kBlinkPageSize / kCardSize> table_{}; - }; - - struct ToBeFinalizedObject { - HeapObjectHeader* header; - void Finalize(); - }; - struct FutureFreelistEntry { - Address start; - size_t size; - }; - - template <typename Function> - void IterateOnCard(Function function, size_t card_number) const; - - void MergeFreeLists(); - void AddToFreeList(Address start, - size_t size, - FinalizeType finalize_type, - bool found_finalizer); - - CardTable card_table_; - PlatformAwareObjectStartBitmap object_start_bit_map_; -#if BUILDFLAG(BLINK_HEAP_YOUNG_GENERATION) - std::unique_ptr<PlatformAwareObjectStartBitmap> cached_object_start_bit_map_; -#endif - Vector<ToBeFinalizedObject> to_be_finalized_objects_; - FreeList cached_freelist_; - Vector<FutureFreelistEntry> unfinalized_freelist_; - - friend class CardTableTest; -}; - -// Large allocations are allocated as separate objects and linked in a list. -// -// In order to use the same memory allocation routines for everything allocated -// in the heap, large objects are considered heap pages containing only one -// object. -class PLATFORM_EXPORT LargeObjectPage final : public BasePage { - public: - static size_t PageHeaderSize() { - // Compute the amount of padding we have to add to a header to make the size - // of the header plus the padding a multiple of 8 bytes. - size_t padding_size = - (sizeof(LargeObjectPage) + kAllocationGranularity - - (sizeof(HeapObjectHeader) % kAllocationGranularity)) % - kAllocationGranularity; - return sizeof(LargeObjectPage) + padding_size; - } - - LargeObjectPage(PageMemory*, BaseArena*, size_t); - - // LargeObjectPage has the following memory layout: - // this -> +------------------+ - // | Header | PageHeaderSize() - // ObjectHeader() -> +------------------+ - // | HeapObjectHeader | sizeof(HeapObjectHeader) - // Payload() -> +------------------+ - // | Object payload | PayloadSize() - // | | - // PayloadEnd() -> +------------------+ - // - // ObjectSize(): PayloadSize() + sizeof(HeapObjectHeader) - // size(): ObjectSize() + PageHeaderSize() - - HeapObjectHeader* ObjectHeader() const { - Address header_address = GetAddress() + PageHeaderSize(); - return reinterpret_cast<HeapObjectHeader*>(header_address); - } - - // Returns the size of the page that is allocatable for objects. This differs - // from PayloadSize() as it also includes the HeapObjectHeader. - size_t ObjectSize() const { return object_size_; } - - // Returns the size of the page including the header. - size_t size() const override { return PageHeaderSize() + object_size_; } - - // Returns the payload start of the underlying object. - Address Payload() const { return ObjectHeader()->Payload(); } - - // Returns the payload size of the underlying object. - size_t PayloadSize() const { return object_size_ - sizeof(HeapObjectHeader); } - - // Points to the payload end of the underlying object. - Address PayloadEnd() const { return Payload() + PayloadSize(); } - - bool ContainedInObjectPayload(ConstAddress address) const { - return Payload() <= address && address < PayloadEnd(); - } - - size_t ObjectPayloadSizeForTesting() override; - void RemoveFromHeap() override; - bool Sweep(FinalizeType) override; - void MakeConsistentForMutator() override; - void Unmark() override; - void FinalizeSweep(SweepResult) override; - - void CollectStatistics( - ThreadState::Statistics::ArenaStatistics* arena_stats) override; - - void VerifyMarking() override; - -#if defined(ADDRESS_SANITIZER) - void PoisonUnmarkedObjects() override; -#endif - -#if DCHECK_IS_ON() - // Returns true for any address that is on one of the pages that this large - // object uses. That ensures that we can use a negative result to populate the - // negative page cache. - bool Contains(ConstAddress) const override; -#endif - -#ifdef ANNOTATE_CONTIGUOUS_CONTAINER - void SetIsVectorBackingPage() { is_vector_backing_page_ = true; } - bool IsVectorBackingPage() const { return is_vector_backing_page_; } -#endif - - // Remembers the page as containing inter-generational pointers. - void SetRemembered(bool remembered) { is_remembered_ = remembered; } - bool IsRemembered() const { return is_remembered_; } - - private: - // The size of the underlying object including HeapObjectHeader. - size_t object_size_; -#ifdef ANNOTATE_CONTIGUOUS_CONTAINER - bool is_vector_backing_page_; -#endif - bool is_remembered_ = false; -}; - -// Each thread has a number of thread arenas (e.g., Generic arenas, typed arenas -// for |Node|, arenas for collection backings, etc.) and |BaseArena| represents -// each thread arena. -// -// |BaseArena| is a parent class of |NormalPageArena| and |LargeObjectArena|. -// |NormalPageArena| represents a part of a heap that contains |NormalPage|s, -// and |LargeObjectArena| represents a part of a heap that contains -// |LargeObjectPage|s. -class PLATFORM_EXPORT BaseArena { - USING_FAST_MALLOC(BaseArena); - - public: - BaseArena(ThreadState*, int); - virtual ~BaseArena(); - void RemoveAllPages(); - - void CollectStatistics(std::string, ThreadState::Statistics*); - virtual void CollectFreeListStatistics( - ThreadState::Statistics::FreeListStatistics*) {} - size_t AllocatedBytes(); - -#if DCHECK_IS_ON() - BasePage* FindPageFromAddress(ConstAddress) const; -#endif - virtual void ClearFreeLists() {} - virtual void MakeIterable() {} - virtual void MakeConsistentForGC(); - void MakeConsistentForMutator(); - void Unmark(); -#if DCHECK_IS_ON() - virtual bool IsConsistentForGC() = 0; -#endif - size_t ObjectPayloadSizeForTesting(); - void PrepareForSweep(BlinkGC::CollectionType); -#if defined(ADDRESS_SANITIZER) - void PoisonUnmarkedObjects(); -#endif - Address LazySweep(size_t, size_t gc_info_index); - bool SweepUnsweptPage(BasePage*); - bool SweepUnsweptPageOnConcurrentThread(BasePage*); - // Returns true if we have swept all pages within the deadline. Returns false - // otherwise. - bool LazySweepWithDeadline(base::TimeTicks deadline); - // Returns true if the arena has been fully swept. - bool ConcurrentSweepOnePage(); - void CompleteSweep(); - void InvokeFinalizersOnSweptPages(); - - ThreadState* GetThreadState() { return thread_state_; } - int ArenaIndex() const { return index_; } - - Address AllocateLargeObject(size_t allocation_size, size_t gc_info_index); - - // Resets the allocation point if it exists for an arena. - virtual void ResetAllocationPoint() {} - - void VerifyMarking(); - virtual void VerifyObjectStartBitmap() {} - - protected: - bool SweepingCompleted() const { return unswept_pages_.IsEmptyLocked(); } - bool SweepingAndFinalizationCompleted() const { - return unswept_pages_.IsEmptyLocked() && - swept_unfinalized_pages_.IsEmptyLocked() && - swept_unfinalized_empty_pages_.IsEmptyLocked(); - } - - // Pages for allocation. - PageStackThreadSafe swept_pages_; - // Pages that are being swept. - PageStackThreadSafe unswept_pages_; - // Pages that have been swept but contain unfinalized objects. - PageStackThreadSafe swept_unfinalized_pages_; - // Pages that have been swept and need to be removed from the heap. - PageStackThreadSafe swept_unfinalized_empty_pages_; - - protected: - void SynchronizedStore(BasePage* page) { page->SynchronizedStore(); } - - private: - virtual Address LazySweepPages(size_t, size_t gc_info_index) = 0; - - ThreadState* thread_state_; - - // Index into the page pools. This is used to ensure that the pages of the - // same type go into the correct page pool and thus avoid type confusion. - // - // TODO(palmer): Should this be size_t? - int index_; -}; - -class PLATFORM_EXPORT NormalPageArena final : public BaseArena { - public: - NormalPageArena(ThreadState*, int index); - void AddToFreeList(Address address, size_t size); - void AddToFreeList(FreeList* other) { free_list_.MoveFrom(other); } - void ClearFreeLists() override; - void CollectFreeListStatistics( - ThreadState::Statistics::FreeListStatistics*) override; - void MakeIterable() override; - -#if DCHECK_IS_ON() - bool IsConsistentForGC() override; - bool PagesToBeSweptContains(ConstAddress) const; -#endif - - Address AllocateObject(size_t allocation_size, size_t gc_info_index); - - void FreePage(NormalPage*); - - void PromptlyFreeObject(HeapObjectHeader*); - void PromptlyFreeObjectInFreeList(HeapObjectHeader*, size_t); - bool ExpandObject(HeapObjectHeader*, size_t); - bool ShrinkObject(HeapObjectHeader*, size_t); - size_t promptly_freed_size() const { return promptly_freed_size_; } - - bool IsObjectAllocatedAtAllocationPoint(HeapObjectHeader* header) { - return header->PayloadEnd() == current_allocation_point_; - } - - size_t ArenaSize(); - size_t FreeListSize(); - - void SweepAndCompact(); - - void ResetAllocationPoint() override { SetAllocationPoint(nullptr, 0); } - - void VerifyObjectStartBitmap() override; - - Address CurrentAllocationPoint() const { return current_allocation_point_; } - - bool IsInCurrentAllocationPointRegion(ConstAddress address) const { - return HasCurrentAllocationArea() && - (CurrentAllocationPoint() <= address) && - (address < (CurrentAllocationPoint() + RemainingAllocationSize())); - } - - size_t RemainingAllocationSize() const { return remaining_allocation_size_; } - - void MakeConsistentForGC() override; - - template <typename Function> - void IterateAndClearCardTables(Function function); - - private: - void AllocatePage(); - - // OutOfLineAllocate represent the slow-path allocation. The suffixed version - // contains just allocation code while the other version also invokes a - // safepoint where allocated bytes are reported to observers. - Address OutOfLineAllocate(size_t allocation_size, size_t gc_info_index); - Address OutOfLineAllocateImpl(size_t allocation_size, size_t gc_info_index); - - Address AllocateFromFreeList(size_t, size_t gc_info_index); - - Address LazySweepPages(size_t, size_t gc_info_index) override; - - bool HasCurrentAllocationArea() const { - return CurrentAllocationPoint() && RemainingAllocationSize(); - } - void SetAllocationPoint(Address, size_t); - - FreeList free_list_; - Address current_allocation_point_; - size_t remaining_allocation_size_; - - // The size of promptly freed objects in the heap. This counter is set to - // zero before sweeping when clearing the free list and after coalescing. - // It will increase for promptly freed objects on already swept pages. - size_t promptly_freed_size_; -}; - -class LargeObjectArena final : public BaseArena { - public: - LargeObjectArena(ThreadState*, int index); - Address AllocateLargeObjectPage(size_t, size_t gc_info_index); - void FreeLargeObjectPage(LargeObjectPage*); - -#if DCHECK_IS_ON() - bool IsConsistentForGC() override { return true; } -#endif - - template <typename Function> - void IterateAndClearRememberedPages(Function function); - - private: - Address DoAllocateLargeObjectPage(size_t, size_t gc_info_index); - Address LazySweepPages(size_t, size_t gc_info_index) override; -}; - -// Mask an address down to the enclosing Oilpan heap base page. All Oilpan heap -// pages are aligned at |kBlinkPageBase| plus the size of a guard page. This -// will work only for 1) a pointer pointing to a non-large object and 2) a -// pointer pointing to the beginning of a large object. -// -// FIXME: Remove PLATFORM_EXPORT once we get a proper public interface to our -// typed arenas. This is only exported to enable tests in HeapTest.cpp. -PLATFORM_EXPORT ALWAYS_INLINE BasePage* PageFromObject(const void* object) { - Address address = reinterpret_cast<Address>(const_cast<void*>(object)); - BasePage* page = reinterpret_cast<BasePage*>(BlinkPageAddress(address) + - BlinkGuardPageSize()); -#if DCHECK_IS_ON() - DCHECK(page->Contains(address)); -#endif - return page; -} - -inline HeapObjectHeader* HeapObjectHeader::FromPayload(const void* payload) { - Address addr = reinterpret_cast<Address>(const_cast<void*>(payload)); - HeapObjectHeader* header = - reinterpret_cast<HeapObjectHeader*>(addr - sizeof(HeapObjectHeader)); - return header; -} - -template <HeapObjectHeader::AccessMode mode> -inline HeapObjectHeader* HeapObjectHeader::FromInnerAddress( - const void* address) { - BasePage* const page = PageFromObject(address); - page->SynchronizedLoad(); - return page->IsLargeObjectPage() - ? static_cast<LargeObjectPage*>(page)->ObjectHeader() - : static_cast<NormalPage*>(page)->FindHeaderFromAddress<mode>( - reinterpret_cast<ConstAddress>(address)); -} - -inline void HeapObjectHeader::CheckFromPayload(const void* payload) { - (void)FromPayload(payload); -} - -template <HeapObjectHeader::AccessMode mode> -NO_SANITIZE_ADDRESS inline size_t HeapObjectHeader::size() const { - // Size is immutable after construction while either marking or sweeping - // is running so relaxed load (if mode == kAtomic) is enough. - uint16_t encoded_low_value = - LoadEncoded<mode, EncodedHalf::kLow, std::memory_order_relaxed>(); - const size_t result = internal::DecodeSize(encoded_low_value); - // Large objects should not refer to header->size() but use - // LargeObjectPage::PayloadSize(). - DCHECK(result != kLargeObjectSizeInHeader); - DCHECK(!PageFromObject(this)->IsLargeObjectPage()); - return result; -} - -NO_SANITIZE_ADDRESS inline void HeapObjectHeader::SetSize(size_t size) { - DCHECK(!PageFromObject(Payload())->thread_state()->IsIncrementalMarking()); - DCHECK_LT(size, kNonLargeObjectPageSizeMax); - encoded_low_ = static_cast<uint16_t>(internal::EncodeSize(size) | - (encoded_low_ & ~kHeaderSizeMask)); -} - -template <HeapObjectHeader::AccessMode mode> -NO_SANITIZE_ADDRESS inline bool HeapObjectHeader::IsLargeObject() const { - uint16_t encoded_low_value = - LoadEncoded<mode, EncodedHalf::kLow, std::memory_order_relaxed>(); - return internal::DecodeSize(encoded_low_value) == kLargeObjectSizeInHeader; -} - -template <HeapObjectHeader::AccessMode mode> -NO_SANITIZE_ADDRESS inline bool HeapObjectHeader::IsInConstruction() const { - return (LoadEncoded<mode, EncodedHalf::kHigh, std::memory_order_acquire>() & - kHeaderIsInConstructionMask) == 0; -} - -template <HeapObjectHeader::AccessMode mode> -NO_SANITIZE_ADDRESS inline void HeapObjectHeader::MarkFullyConstructed() { - DCHECK(IsInConstruction()); - StoreEncoded<mode, EncodedHalf::kHigh, std::memory_order_release>( - kHeaderIsInConstructionMask, kHeaderIsInConstructionMask); -} - -inline Address HeapObjectHeader::Payload() const { - return reinterpret_cast<Address>(const_cast<HeapObjectHeader*>(this)) + - sizeof(HeapObjectHeader); -} - -template <HeapObjectHeader::AccessMode mode> -inline Address HeapObjectHeader::PayloadEnd() const { - return reinterpret_cast<Address>(const_cast<HeapObjectHeader*>(this)) + - size<mode>(); -} - -NO_SANITIZE_ADDRESS inline size_t HeapObjectHeader::PayloadSize() const { - const size_t size = internal::DecodeSize(encoded_low_); - if (UNLIKELY(size == kLargeObjectSizeInHeader)) { - DCHECK(PageFromObject(this)->IsLargeObjectPage()); - return static_cast<LargeObjectPage*>(PageFromObject(this))->PayloadSize(); - } - DCHECK(!PageFromObject(this)->IsLargeObjectPage()); - return size - sizeof(HeapObjectHeader); -} - -template <HeapObjectHeader::AccessMode mode> -NO_SANITIZE_ADDRESS inline bool HeapObjectHeader::IsMarked() const { - const uint16_t encoded = - LoadEncoded<mode, EncodedHalf::kLow, std::memory_order_relaxed>(); - return encoded & kHeaderMarkBitMask; -} - -template <HeapObjectHeader::AccessMode mode> -NO_SANITIZE_ADDRESS inline bool HeapObjectHeader::IsOld() const { - // Oilpan uses the sticky-mark-bits technique to encode old objects. - return IsMarked<mode>(); -} - -template <HeapObjectHeader::AccessMode mode> -NO_SANITIZE_ADDRESS inline void HeapObjectHeader::Unmark() { - DCHECK(IsMarked<mode>()); - StoreEncoded<mode, EncodedHalf::kLow, std::memory_order_relaxed>( - 0u, kHeaderMarkBitMask); -} - -// The function relies on size bits being unmodified when the function is -// called, i.e. SetSize() and TryMark() can't be called concurrently. -template <HeapObjectHeader::AccessMode mode> -NO_SANITIZE_ADDRESS inline bool HeapObjectHeader::TryMark() { - if (mode == AccessMode::kNonAtomic) { - if (encoded_low_ & kHeaderMarkBitMask) - return false; - encoded_low_ |= kHeaderMarkBitMask; - return true; - } - auto* atomic_encoded = internal::AsUnsanitizedAtomic(&encoded_low_); - uint16_t old_value = atomic_encoded->load(std::memory_order_relaxed); - if (old_value & kHeaderMarkBitMask) - return false; - const uint16_t new_value = old_value | kHeaderMarkBitMask; - return atomic_encoded->compare_exchange_strong(old_value, new_value, - std::memory_order_relaxed); -} - -inline Address NormalPageArena::AllocateObject(size_t allocation_size, - size_t gc_info_index) { - if (LIKELY(allocation_size <= remaining_allocation_size_)) { - Address header_address = current_allocation_point_; - current_allocation_point_ += allocation_size; - remaining_allocation_size_ -= allocation_size; - DCHECK_GT(gc_info_index, 0u); - new (NotNullTag::kNotNull, header_address) - HeapObjectHeader(allocation_size, gc_info_index); - DCHECK(!PageFromObject(header_address)->IsLargeObjectPage()); - static_cast<NormalPage*>(PageFromObject(header_address)) - ->object_start_bit_map() - ->SetBit<HeapObjectHeader::AccessMode::kAtomic>(header_address); - Address result = header_address + sizeof(HeapObjectHeader); - DCHECK(!(reinterpret_cast<uintptr_t>(result) & kAllocationMask)); - - SET_MEMORY_ACCESSIBLE(result, allocation_size - sizeof(HeapObjectHeader)); -#if DCHECK_IS_ON() - DCHECK(FindPageFromAddress(header_address + allocation_size - 1)); -#endif - return result; - } - return OutOfLineAllocate(allocation_size, gc_info_index); -} - -inline NormalPageArena* NormalPage::ArenaForNormalPage() const { - return static_cast<NormalPageArena*>(Arena()); -} - -// Iterates over all card tables and clears them. -template <typename Function> -inline void NormalPageArena::IterateAndClearCardTables(Function function) { - for (BasePage* page : swept_pages_) { - auto* normal_page = static_cast<NormalPage*>(page); - normal_page->IterateCardTable(function); - normal_page->ClearCardTable(); - } -} - -// Iterates over all pages that may contain inter-generational pointers. -template <typename Function> -inline void LargeObjectArena::IterateAndClearRememberedPages( - Function function) { - for (BasePage* page : swept_pages_) { - auto* large_page = static_cast<LargeObjectPage*>(page); - if (large_page->IsRemembered()) { - function(large_page->ObjectHeader()); - large_page->SetRemembered(false); - } - } -} - -// static -template <HeapObjectHeader::AccessMode mode> -bool PlatformAwareObjectStartBitmap::ShouldForceNonAtomic() { -#if defined(ARCH_CPU_ARMEL) - // Use non-atomic accesses on ARMv7 when marking is not active. - if (mode == HeapObjectHeader::AccessMode::kAtomic) { - if (LIKELY(!ThreadState::Current()->IsAnyIncrementalMarking())) - return true; - } -#endif // defined(ARCH_CPU_ARMEL) - return false; -} - -template <HeapObjectHeader::AccessMode mode> -inline void PlatformAwareObjectStartBitmap::SetBit(Address header_address) { - if (ShouldForceNonAtomic<mode>()) { - ObjectStartBitmap::SetBit<HeapObjectHeader::AccessMode::kNonAtomic>( - header_address); - return; - } - ObjectStartBitmap::SetBit<mode>(header_address); -} - -template <HeapObjectHeader::AccessMode mode> -inline void PlatformAwareObjectStartBitmap::ClearBit(Address header_address) { - if (ShouldForceNonAtomic<mode>()) { - ObjectStartBitmap::ClearBit<HeapObjectHeader::AccessMode::kNonAtomic>( - header_address); - return; - } - ObjectStartBitmap::ClearBit<mode>(header_address); -} - -template <HeapObjectHeader::AccessMode mode> -inline void ObjectStartBitmap::store(size_t cell_index, uint8_t value) { - if (mode == HeapObjectHeader::AccessMode::kNonAtomic) { - object_start_bit_map_[cell_index] = value; - return; - } - WTF::AsAtomicPtr(&object_start_bit_map_[cell_index]) - ->store(value, std::memory_order_release); -} - -template <HeapObjectHeader::AccessMode mode> -inline uint8_t ObjectStartBitmap::load(size_t cell_index) const { - if (mode == HeapObjectHeader::AccessMode::kNonAtomic) { - return object_start_bit_map_[cell_index]; - } - return WTF::AsAtomicPtr(&object_start_bit_map_[cell_index]) - ->load(std::memory_order_acquire); -} - -template <HeapObjectHeader::AccessMode mode> -inline void ObjectStartBitmap::SetBit(Address header_address) { - size_t cell_index, object_bit; - ObjectStartIndexAndBit(header_address, &cell_index, &object_bit); - // Only the mutator thread writes to the bitmap during concurrent marking, - // so no need for CAS here. - store<mode>(cell_index, - static_cast<uint8_t>(load(cell_index) | (1 << object_bit))); -} - -template <HeapObjectHeader::AccessMode mode> -inline void ObjectStartBitmap::ClearBit(Address header_address) { - size_t cell_index, object_bit; - ObjectStartIndexAndBit(header_address, &cell_index, &object_bit); - store<mode>(cell_index, - static_cast<uint8_t>(load(cell_index) & ~(1 << object_bit))); -} - -template <HeapObjectHeader::AccessMode mode> -inline bool ObjectStartBitmap::CheckBit(Address header_address) const { - size_t cell_index, object_bit; - ObjectStartIndexAndBit(header_address, &cell_index, &object_bit); - return load<mode>(cell_index) & (1 << object_bit); -} - -inline void ObjectStartBitmap::ObjectStartIndexAndBit(Address header_address, - size_t* cell_index, - size_t* bit) const { - const size_t object_offset = header_address - offset_; - DCHECK(!(object_offset & kAllocationMask)); - const size_t object_start_number = object_offset / kAllocationGranularity; - *cell_index = object_start_number / kCellSize; -#if DCHECK_IS_ON() - const size_t bitmap_size = kBitmapSize; - DCHECK_LT(*cell_index, bitmap_size); -#endif - *bit = object_start_number & kCellMask; -} - -template <typename Callback> -inline void ObjectStartBitmap::Iterate(Callback callback) const { - for (size_t cell_index = 0; cell_index < kReservedForBitmap; cell_index++) { - uint8_t value = load(cell_index); - while (value) { - const int trailing_zeroes = base::bits::CountTrailingZeroBits(value); - const size_t object_start_number = - (cell_index * kCellSize) + trailing_zeroes; - const Address object_address = - offset_ + (kAllocationGranularity * object_start_number); - callback(object_address); - // Clear current object bit in temporary value to advance iteration. - value &= ~(1 << (object_start_number & kCellMask)); - } - } -} - -template <HeapObjectHeader::AccessMode mode> -Address ObjectStartBitmap::FindHeader( - ConstAddress address_maybe_pointing_to_the_middle_of_object) const { - size_t object_offset = - address_maybe_pointing_to_the_middle_of_object - offset_; - size_t object_start_number = object_offset / kAllocationGranularity; - size_t cell_index = object_start_number / kCellSize; -#if DCHECK_IS_ON() - const size_t bitmap_size = kReservedForBitmap; - DCHECK_LT(cell_index, bitmap_size); -#endif - size_t bit = object_start_number & kCellMask; - uint8_t byte = load<mode>(cell_index) & ((1 << (bit + 1)) - 1); - while (!byte) { - DCHECK_LT(0u, cell_index); - byte = load<mode>(--cell_index); - } - int leading_zeroes = base::bits::CountLeadingZeroBits(byte); - object_start_number = - (cell_index * kCellSize) + (kCellSize - 1) - leading_zeroes; - object_offset = object_start_number * kAllocationGranularity; - return object_offset + offset_; -} - -NO_SANITIZE_ADDRESS inline HeapObjectHeader::HeapObjectHeader( - size_t size, - size_t gc_info_index) { - // sizeof(HeapObjectHeader) must be equal to or smaller than - // |kAllocationGranularity|, because |HeapObjectHeader| is used as a header - // for a freed entry. Given that the smallest entry size is - // |kAllocationGranurarity|, |HeapObjectHeader| must fit into the size. - static_assert( - sizeof(HeapObjectHeader) <= kAllocationGranularity, - "size of HeapObjectHeader must be smaller than kAllocationGranularity"); - - DCHECK_LT(gc_info_index, GCInfoTable::kMaxIndex); - DCHECK_LT(size, kNonLargeObjectPageSizeMax); - DCHECK_EQ(0u, size & kAllocationMask); - // Relaxed memory order is enough as in construction is created/synchronized - // as follows: - // - Page allocator gets zeroed page and uses page initialization fence. - // - Sweeper zeroes memory and synchronizes via global lock. - internal::AsUnsanitizedAtomic(&encoded_high_) - ->store(static_cast<uint16_t>(gc_info_index << kHeaderGCInfoIndexShift), - std::memory_order_relaxed); - encoded_low_ = internal::EncodeSize(size); - DCHECK(IsInConstruction()); -} - -template <HeapObjectHeader::AccessMode mode, - HeapObjectHeader::EncodedHalf part, - std::memory_order memory_order> -NO_SANITIZE_ADDRESS inline uint16_t HeapObjectHeader::LoadEncoded() const { - const uint16_t& half = - part == EncodedHalf::kLow ? encoded_low_ : encoded_high_; - if (mode == AccessMode::kNonAtomic) - return half; - return internal::AsUnsanitizedAtomic(&half)->load(memory_order); -} - -// Sets bits selected by the mask to the given value. Please note that atomicity -// of the whole operation is not guaranteed. -template <HeapObjectHeader::AccessMode mode, - HeapObjectHeader::EncodedHalf part, - std::memory_order memory_order> -NO_SANITIZE_ADDRESS inline void HeapObjectHeader::StoreEncoded(uint16_t bits, - uint16_t mask) { - DCHECK_EQ(static_cast<uint16_t>(0u), bits & ~mask); - uint16_t& half = part == EncodedHalf::kLow ? encoded_low_ : encoded_high_; - if (mode == AccessMode::kNonAtomic) { - half = (half & ~mask) | bits; - return; - } - // We don't perform CAS loop here assuming that the data is constant and no - // one except for us can change this half concurrently. - auto* atomic_encoded = internal::AsUnsanitizedAtomic(&half); - uint16_t value = atomic_encoded->load(std::memory_order_relaxed); - value = (value & ~mask) | bits; - atomic_encoded->store(value, memory_order); -} - -template <HeapObjectHeader::AccessMode mode> -HeapObjectHeader* NormalPage::FindHeaderFromAddress( - ConstAddress address) const { - DCHECK(ContainedInObjectPayload(address)); - HeapObjectHeader* header = reinterpret_cast<HeapObjectHeader*>( - object_start_bit_map()->FindHeader<mode>(address)); - DCHECK_LT(0u, header->GcInfoIndex<mode>()); - DCHECK_GT(header->PayloadEnd<HeapObjectHeader::AccessMode::kAtomic>(), - address); - return header; -} - -template <typename Function> -void NormalPage::IterateCardTable(Function function) const { - // TODO(bikineev): Consider introducing a "dirty" per-page bit to avoid - // the loop (this may in turn pessimize barrier implementation). - for (auto card : card_table_) { - if (UNLIKELY(card.bit)) { - IterateOnCard(function, card.index); - } - } -} - -// Iterates over all objects in the specified marked card. Please note that -// since objects are not aligned by the card boundary, it starts from the -// object which may reside on a previous card. -template <typename Function> -void NormalPage::IterateOnCard(Function function, size_t card_number) const { -#if DCHECK_IS_ON() - DCHECK(card_table_.IsMarked(card_number)); - DCHECK(ArenaForNormalPage()->IsConsistentForGC()); -#endif - - const Address card_begin = RoundToBlinkPageStart(GetAddress()) + - (card_number << CardTable::kBitsPerCard); - const Address card_end = card_begin + CardTable::kCardSize; - // Generational barrier marks cards corresponding to slots (not source - // objects), therefore the potential source object may reside on a - // previous card. - HeapObjectHeader* header = reinterpret_cast<HeapObjectHeader*>( - card_number == card_table_.begin().index - ? Payload() - : object_start_bit_map_.FindHeader(card_begin)); - for (; header < reinterpret_cast<HeapObjectHeader*>(card_end); - reinterpret_cast<Address&>(header) += header->size()) { - if (!header->IsFree()) { - function(header); - } - } -} - -inline void NormalPage::MarkCard(Address address) { -#if DCHECK_IS_ON() - DCHECK(Contains(address)); -#endif - const size_t byte = reinterpret_cast<size_t>(address) & kBlinkPageOffsetMask; - const size_t card = byte / CardTable::kCardSize; - card_table_.Mark(card); -} - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_HEAP_PAGE_H_
diff --git a/third_party/blink/renderer/platform/heap/impl/heap_stats_collector.cc b/third_party/blink/renderer/platform/heap/impl/heap_stats_collector.cc deleted file mode 100644 index bb4180f..0000000 --- a/third_party/blink/renderer/platform/heap/impl/heap_stats_collector.cc +++ /dev/null
@@ -1,279 +0,0 @@ -// 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/heap/heap_stats_collector.h" - -#include <cmath> - -#include "base/check_op.h" -#include "third_party/blink/renderer/platform/wtf/allocator/partitions.h" - -namespace blink { - -void ThreadHeapStatsCollector::IncreaseCompactionFreedSize(size_t bytes) { - DCHECK(is_started_); - current_.compaction_freed_bytes += bytes; - current_.compaction_recorded_events = true; -} - -void ThreadHeapStatsCollector::IncreaseCompactionFreedPages(size_t pages) { - DCHECK(is_started_); - current_.compaction_freed_pages += pages; - current_.compaction_recorded_events = true; -} - -void ThreadHeapStatsCollector::IncreaseAllocatedObjectSize(size_t bytes) { - // The current GC may not have been started. This is ok as recording considers - // the whole time range between garbage collections. - pos_delta_allocated_bytes_since_prev_gc_ += bytes; -} - -void ThreadHeapStatsCollector::IncreaseAllocatedObjectSizeForTesting( - size_t bytes) { - IncreaseAllocatedObjectSize(bytes); - AllocatedObjectSizeSafepointImpl(); -} - -void ThreadHeapStatsCollector::DecreaseAllocatedObjectSize(size_t bytes) { - // See IncreaseAllocatedObjectSize. - neg_delta_allocated_bytes_since_prev_gc_ += bytes; -} - -void ThreadHeapStatsCollector::DecreaseAllocatedObjectSizeForTesting( - size_t bytes) { - DecreaseAllocatedObjectSize(bytes); - AllocatedObjectSizeSafepointImpl(); -} - -void ThreadHeapStatsCollector::AllocatedObjectSizeSafepoint() { - if (std::abs(pos_delta_allocated_bytes_since_prev_gc_ - - neg_delta_allocated_bytes_since_prev_gc_) > kUpdateThreshold) { - AllocatedObjectSizeSafepointImpl(); - } -} - -void ThreadHeapStatsCollector::AllocatedObjectSizeSafepointImpl() { - allocated_bytes_since_prev_gc_ += - static_cast<int64_t>(pos_delta_allocated_bytes_since_prev_gc_) - - static_cast<int64_t>(neg_delta_allocated_bytes_since_prev_gc_); - - // These observer methods may start or finalize GC. In case they trigger a - // final GC pause, the delta counters are reset there and the following - // observer calls are called with '0' updates. - ForAllObservers([this](ThreadHeapStatsObserver* observer) { - // Recompute delta here so that a GC finalization is able to clear the - // delta for other observer calls. - int64_t delta = pos_delta_allocated_bytes_since_prev_gc_ - - neg_delta_allocated_bytes_since_prev_gc_; - if (delta < 0) { - observer->DecreaseAllocatedObjectSize(static_cast<size_t>(-delta)); - } else { - observer->IncreaseAllocatedObjectSize(static_cast<size_t>(delta)); - } - }); - pos_delta_allocated_bytes_since_prev_gc_ = 0; - neg_delta_allocated_bytes_since_prev_gc_ = 0; -} - -void ThreadHeapStatsCollector::IncreaseAllocatedSpace(size_t bytes) { - allocated_space_bytes_ += bytes; - ForAllObservers([bytes](ThreadHeapStatsObserver* observer) { - observer->IncreaseAllocatedSpace(bytes); - }); -} - -void ThreadHeapStatsCollector::DecreaseAllocatedSpace(size_t bytes) { - allocated_space_bytes_ -= bytes; - ForAllObservers([bytes](ThreadHeapStatsObserver* observer) { - observer->DecreaseAllocatedSpace(bytes); - }); -} - -ThreadHeapStatsCollector::Event::Event() { - static std::atomic<size_t> counter{0}; - unique_id = counter.fetch_add(1); -} - -void ThreadHeapStatsCollector::NotifyMarkingStarted( - BlinkGC::CollectionType collection_type, - BlinkGC::GCReason reason, - bool is_forced_gc) { - DCHECK(!is_started_); - DCHECK(current_.marking_time().is_zero()); - is_started_ = true; - current_.reason = reason; - current_.collection_type = collection_type; - current_.is_forced_gc = is_forced_gc; -} - -void ThreadHeapStatsCollector::NotifyMarkingCompleted(size_t marked_bytes) { - allocated_bytes_since_prev_gc_ += - static_cast<int64_t>(pos_delta_allocated_bytes_since_prev_gc_) - - static_cast<int64_t>(neg_delta_allocated_bytes_since_prev_gc_); - current_.marked_bytes = marked_bytes; - current_.object_size_in_bytes_before_sweeping = object_size_in_bytes(); - current_.allocated_space_in_bytes_before_sweeping = allocated_space_bytes(); - current_.partition_alloc_bytes_before_sweeping = - WTF::Partitions::TotalSizeOfCommittedPages(); - allocated_bytes_since_prev_gc_ = 0; - pos_delta_allocated_bytes_since_prev_gc_ = 0; - neg_delta_allocated_bytes_since_prev_gc_ = 0; - - ForAllObservers([marked_bytes](ThreadHeapStatsObserver* observer) { - observer->ResetAllocatedObjectSize(marked_bytes); - }); - - is_sweeping_ = true; -} - -void ThreadHeapStatsCollector::NotifySweepingCompleted() { - is_started_ = false; - current_.live_object_rate = - current_.object_size_in_bytes_before_sweeping - ? static_cast<double>(current().marked_bytes) / - current_.object_size_in_bytes_before_sweeping - : 0.0; - current_.gc_nested_in_v8 = gc_nested_in_v8_; - gc_nested_in_v8_ = base::TimeDelta(); - // Reset the current state. - static_assert(std::is_trivially_copyable<Event>::value, - "Event should be trivially copyable"); - previous_ = std::move(current_); - current_ = Event(); - is_sweeping_ = false; -} - -void ThreadHeapStatsCollector::UpdateReason(BlinkGC::GCReason reason) { - current_.reason = reason; -} - -size_t ThreadHeapStatsCollector::object_size_in_bytes() const { - const Event& event = is_sweeping_ ? current_ : previous_; - DCHECK_GE( - static_cast<int64_t>(event.marked_bytes) + allocated_bytes_since_prev_gc_, - 0); - return static_cast<size_t>(static_cast<int64_t>(event.marked_bytes) + - allocated_bytes_since_prev_gc_); -} - -base::TimeDelta ThreadHeapStatsCollector::Event::roots_marking_time() const { - return scope_data[kVisitRoots]; -} - -base::TimeDelta ThreadHeapStatsCollector::Event::incremental_marking_time() - const { - return scope_data[kIncrementalMarkingStartMarking] + - scope_data[kIncrementalMarkingStep] + scope_data[kUnifiedMarkingStep]; -} - -base::TimeDelta -ThreadHeapStatsCollector::Event::worklist_processing_time_foreground() const { - return scope_data[kMarkProcessWorklists]; -} - -base::TimeDelta ThreadHeapStatsCollector::Event::flushing_v8_references_time() - const { - return scope_data[kMarkFlushV8References]; -} - -base::TimeDelta ThreadHeapStatsCollector::Event::atomic_marking_time() const { - return scope_data[kAtomicPauseMarkPrologue] + - scope_data[kAtomicPauseMarkRoots] + - scope_data[kAtomicPauseMarkTransitiveClosure] + - scope_data[kAtomicPauseMarkEpilogue]; -} - -base::TimeDelta ThreadHeapStatsCollector::Event::atomic_sweep_and_compact_time() - const { - return scope_data[ThreadHeapStatsCollector::kAtomicPauseSweepAndCompact]; -} - -base::TimeDelta ThreadHeapStatsCollector::Event::foreground_marking_time() - const { - return incremental_marking_time() + atomic_marking_time(); -} - -base::TimeDelta ThreadHeapStatsCollector::Event::background_marking_time() - const { - return base::TimeDelta::FromMicroseconds(base::subtle::NoBarrier_Load( - &concurrent_scope_data[kConcurrentMarkingStep])); -} - -base::TimeDelta ThreadHeapStatsCollector::Event::marking_time() const { - return foreground_marking_time() + background_marking_time(); -} - -base::TimeDelta ThreadHeapStatsCollector::Event::gc_cycle_time() const { - // Note that scopes added here also have to have a proper BlinkGCInV8Scope - // scope if they are nested in a V8 scope. - return incremental_marking_time() + atomic_marking_time() + - atomic_sweep_and_compact_time() + foreground_sweeping_time(); -} - -base::TimeDelta ThreadHeapStatsCollector::Event::atomic_pause_time() const { - return atomic_marking_time() + atomic_sweep_and_compact_time(); -} - -base::TimeDelta ThreadHeapStatsCollector::Event::foreground_sweeping_time() - const { - return scope_data[kCompleteSweep] + scope_data[kLazySweepInIdle] + - scope_data[kLazySweepOnAllocation]; -} - -base::TimeDelta ThreadHeapStatsCollector::Event::background_sweeping_time() - const { - return base::TimeDelta::FromMicroseconds( - concurrent_scope_data[kConcurrentSweepingStep]); -} - -base::TimeDelta ThreadHeapStatsCollector::Event::sweeping_time() const { - return foreground_sweeping_time() + background_sweeping_time(); -} - -int64_t ThreadHeapStatsCollector::allocated_bytes_since_prev_gc() const { - return allocated_bytes_since_prev_gc_; -} - -size_t ThreadHeapStatsCollector::marked_bytes() const { - return current_.marked_bytes; -} - -base::TimeDelta ThreadHeapStatsCollector::marking_time_so_far() const { - return current_.marking_time(); -} - -base::TimeDelta ThreadHeapStatsCollector::worklist_processing_time_foreground() - const { - return current_.worklist_processing_time_foreground(); -} - -base::TimeDelta ThreadHeapStatsCollector::flushing_v8_references_time() const { - return current_.flushing_v8_references_time(); -} - -size_t ThreadHeapStatsCollector::allocated_space_bytes() const { - return allocated_space_bytes_; -} - -void ThreadHeapStatsCollector::RegisterObserver( - ThreadHeapStatsObserver* observer) { - DCHECK(!observers_.Contains(observer)); - observers_.push_back(observer); -} - -void ThreadHeapStatsCollector::UnregisterObserver( - ThreadHeapStatsObserver* observer) { - wtf_size_t index = observers_.Find(observer); - DCHECK_NE(WTF::kNotFound, index); - observers_.EraseAt(index); -} - -template <typename Callback> -void ThreadHeapStatsCollector::ForAllObservers(Callback callback) { - for (ThreadHeapStatsObserver* observer : observers_) { - callback(observer); - } -} - -} // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/impl/heap_stats_collector.h b/third_party/blink/renderer/platform/heap/impl/heap_stats_collector.h deleted file mode 100644 index b252157..0000000 --- a/third_party/blink/renderer/platform/heap/impl/heap_stats_collector.h +++ /dev/null
@@ -1,473 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_HEAP_STATS_COLLECTOR_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_HEAP_STATS_COLLECTOR_H_ - -#include <stddef.h> - -#include "base/atomicops.h" -#include "base/gtest_prod_util.h" -#include "third_party/blink/renderer/platform/heap/blink_gc.h" -#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h" -#include "third_party/blink/renderer/platform/platform_export.h" -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" - -namespace blink { - -// Interface for observing changes to heap sizing. -class PLATFORM_EXPORT ThreadHeapStatsObserver { - public: - // Called upon allocating/releasing chunks of memory that contain objects. - // - // Must not trigger GC or allocate. - virtual void IncreaseAllocatedSpace(size_t) = 0; - virtual void DecreaseAllocatedSpace(size_t) = 0; - - // Called once per GC cycle with the accurate number of live |bytes|. - // - // Must not trigger GC or allocate. - virtual void ResetAllocatedObjectSize(size_t bytes) = 0; - - // Called after observing at least - // |ThreadHeapStatsCollector::kUpdateThreshold| changed bytes through - // allocation or explicit free. Reports both, negative and positive - // increments, to allow observer to decide whether absolute values or only the - // deltas is interesting. - // - // May trigger GC but most not allocate. - virtual void IncreaseAllocatedObjectSize(size_t) = 0; - virtual void DecreaseAllocatedObjectSize(size_t) = 0; -}; - -#define FOR_ALL_SCOPES(V) \ - V(AtomicPauseCompaction) \ - V(AtomicPauseMarkEpilogue) \ - V(AtomicPauseMarkPrologue) \ - V(AtomicPauseMarkRoots) \ - V(AtomicPauseMarkTransitiveClosure) \ - V(AtomicPauseSweepAndCompact) \ - V(CompleteSweep) \ - V(IncrementalMarkingFinalize) \ - V(IncrementalMarkingStartMarking) \ - V(IncrementalMarkingStep) \ - V(IncrementalMarkingWithDeadline) \ - V(InvokePreFinalizers) \ - V(LazySweepInIdle) \ - V(LazySweepOnAllocation) \ - V(MarkBailOutObjects) \ - V(MarkInvokeEphemeronCallbacks) \ - V(MarkFlushV8References) \ - V(MarkFlushEphemeronPairs) \ - V(MarkProcessWorklists) \ - V(MarkProcessMarkingWorklist) \ - V(MarkProcessWriteBarrierWorklist) \ - V(MarkProcessNotFullyconstructeddWorklist) \ - V(MarkNotFullyConstructedObjects) \ - V(MarkWeakProcessing) \ - V(UnifiedMarkingStep) \ - V(VisitCrossThreadPersistents) \ - V(VisitPersistentRoots) \ - V(VisitPersistents) \ - V(VisitRoots) \ - V(VisitStackRoots) \ - V(VisitRememberedSets) - -#define FOR_ALL_CONCURRENT_SCOPES(V) \ - V(ConcurrentMarkInvokeEphemeronCallbacks) \ - V(ConcurrentMarkingStep) \ - V(ConcurrentSweepingStep) - -// Manages counters and statistics across garbage collection cycles. -// -// Usage: -// ThreadHeapStatsCollector stats_collector; -// stats_collector.NotifyMarkingStarted(<BlinkGC::CollectionType>, -// <BlinkGC::GCReason>); -// // Use tracer. -// stats_collector.NotifySweepingCompleted(); -// // Previous event is available using stats_collector.previous(). -class PLATFORM_EXPORT ThreadHeapStatsCollector { - USING_FAST_MALLOC(ThreadHeapStatsCollector); - - public: - // These ids will form human readable names when used in Scopes. - enum Id { -#define DECLARE_ENUM(name) k##name, - FOR_ALL_SCOPES(DECLARE_ENUM) -#undef DECLARE_ENUM - kNumScopeIds, - }; - - enum ConcurrentId { -#define DECLARE_ENUM(name) k##name, - FOR_ALL_CONCURRENT_SCOPES(DECLARE_ENUM) -#undef DECLARE_ENUM - kNumConcurrentScopeIds - }; - - constexpr static const char* ToString(Id id, BlinkGC::CollectionType type) { - switch (id) { -#define CASE(name) \ - case k##name: \ - return type == BlinkGC::CollectionType::kMajor ? "BlinkGC." #name \ - : "BlinkGC." #name \ - ".Minor"; - FOR_ALL_SCOPES(CASE) -#undef CASE - default: - NOTREACHED(); - } - return nullptr; - } - - constexpr static const char* ToString(ConcurrentId id, - BlinkGC::CollectionType type) { - switch (id) { -#define CASE(name) \ - case k##name: \ - return type == BlinkGC::CollectionType::kMajor ? "BlinkGC." #name \ - : "BlinkGC." #name \ - ".Minor"; - FOR_ALL_CONCURRENT_SCOPES(CASE) -#undef CASE - default: - NOTREACHED(); - } - return nullptr; - } - - enum TraceCategory { kEnabled, kDisabled }; - enum ScopeContext { kMutatorThread, kConcurrentThread }; - - // Trace a particular scope. Will emit a trace event and record the time in - // the corresponding ThreadHeapStatsCollector. - template <TraceCategory trace_category = kDisabled, - ScopeContext scope_category = kMutatorThread> - class PLATFORM_EXPORT InternalScope { - DISALLOW_NEW(); - - using IdType = - std::conditional_t<scope_category == kMutatorThread, Id, ConcurrentId>; - - public: - template <typename... Args> - InternalScope(ThreadHeapStatsCollector* tracer, IdType id, Args... args) - : tracer_(tracer), start_time_(base::TimeTicks::Now()), id_(id) { - StartTrace(args...); - } - InternalScope(const InternalScope&) = delete; - InternalScope& operator=(const InternalScope&) = delete; - - ~InternalScope() { - StopTrace(); - IncreaseScopeTime(id_); - } - - private: - inline constexpr static const char* TraceCategory(); - - inline void StartTrace(); - template <typename Value1> - inline void StartTrace(const char* k1, Value1 v1); - template <typename Value1, typename Value2> - inline void StartTrace(const char* k1, - Value1 v1, - const char* k2, - Value2 v2); - inline void StopTrace(); - - inline void IncreaseScopeTime(Id); - inline void IncreaseScopeTime(ConcurrentId); - - ThreadHeapStatsCollector* const tracer_; - const base::TimeTicks start_time_; - const IdType id_; - }; - - using Scope = InternalScope<kDisabled>; - using EnabledScope = InternalScope<kEnabled>; - using ConcurrentScope = InternalScope<kDisabled, kConcurrentThread>; - using EnabledConcurrentScope = InternalScope<kEnabled, kConcurrentThread>; - - // BlinkGCInV8Scope keeps track of time spent in Blink's GC when called by V8. - // This is necessary to avoid double-accounting of Blink's time when computing - // the overall time (V8 + Blink) spent in GC on the main thread. - class PLATFORM_EXPORT BlinkGCInV8Scope { - DISALLOW_NEW(); - - public: - template <typename... Args> - BlinkGCInV8Scope(ThreadHeapStatsCollector* tracer) - : tracer_(tracer), start_time_(base::TimeTicks::Now()) {} - BlinkGCInV8Scope(const BlinkGCInV8Scope&) = delete; - BlinkGCInV8Scope& operator=(const BlinkGCInV8Scope&) = delete; - - ~BlinkGCInV8Scope() { - if (tracer_) - tracer_->gc_nested_in_v8_ += base::TimeTicks::Now() - start_time_; - } - - private: - ThreadHeapStatsCollector* const tracer_; - const base::TimeTicks start_time_; - }; - - // POD to hold interesting data accumulated during a garbage collection cycle. - // The event is always fully populated when looking at previous events but - // is only be partially populated when looking at the current event. See - // members on when they are available. - // - // Note that all getters include time for stand-alone as well as unified heap - // GCs. E.g., |atomic_marking_time()| report the marking time of the atomic - // phase, independent of whether the GC was a stand-alone or unified heap GC. - struct PLATFORM_EXPORT Event { - Event(); - - // Overall time spent in the GC cycle. This includes marking time as well as - // sweeping time. - base::TimeDelta gc_cycle_time() const; - - // Time spent in the final atomic pause of a GC cycle. - base::TimeDelta atomic_pause_time() const; - - // Time spent in the final atomic pause for marking the heap. - base::TimeDelta atomic_marking_time() const; - - // Time spent in the final atomic pause in sweeping and compacting the heap. - base::TimeDelta atomic_sweep_and_compact_time() const; - - // Time spent marking the roots. - base::TimeDelta roots_marking_time() const; - - // Time spent incrementally marking the heap. - base::TimeDelta incremental_marking_time() const; - - // Time spent processing worklist in the foreground thread. - base::TimeDelta worklist_processing_time_foreground() const; - - // Time spent flushing v8 references (this is done only in the foreground) - base::TimeDelta flushing_v8_references_time() const; - - // Time spent in foreground tasks marking the heap. - base::TimeDelta foreground_marking_time() const; - - // Time spent in background tasks marking the heap. - base::TimeDelta background_marking_time() const; - - // Overall time spent marking the heap. - base::TimeDelta marking_time() const; - - // Time spent in foreground tasks sweeping the heap. - base::TimeDelta foreground_sweeping_time() const; - - // Time spent in background tasks sweeping the heap. - base::TimeDelta background_sweeping_time() const; - - // Overall time spent sweeping the heap. - base::TimeDelta sweeping_time() const; - - // Marked bytes collected during sweeping. - size_t unique_id = -1; - size_t marked_bytes = 0; - size_t compaction_freed_bytes = 0; - size_t compaction_freed_pages = 0; - bool compaction_recorded_events = false; - base::TimeDelta scope_data[kNumScopeIds]; - base::subtle::Atomic32 concurrent_scope_data[kNumConcurrentScopeIds]{0}; - BlinkGC::GCReason reason = static_cast<BlinkGC::GCReason>(0); - BlinkGC::CollectionType collection_type = BlinkGC::CollectionType::kMajor; - size_t object_size_in_bytes_before_sweeping = 0; - size_t allocated_space_in_bytes_before_sweeping = 0; - size_t partition_alloc_bytes_before_sweeping = 0; - double live_object_rate = 0; - base::TimeDelta gc_nested_in_v8; - bool is_forced_gc = true; - }; - - // Indicates a new garbage collection cycle. - void NotifyMarkingStarted(BlinkGC::CollectionType, - BlinkGC::GCReason, - bool is_forced_gc); - - // Indicates that marking of the current garbage collection cycle is - // completed. - void NotifyMarkingCompleted(size_t marked_bytes); - - // Indicates the end of a garbage collection cycle. This means that sweeping - // is finished at this point. - void NotifySweepingCompleted(); - - void IncreaseScopeTime(Id id, base::TimeDelta time) { - DCHECK(is_started_); - current_.scope_data[id] += time; - } - - void IncreaseConcurrentScopeTime(ConcurrentId id, base::TimeDelta time) { - using Atomic32 = base::subtle::Atomic32; - DCHECK(is_started_); - const int64_t ms = time.InMicroseconds(); - DCHECK(ms <= std::numeric_limits<Atomic32>::max()); - base::subtle::NoBarrier_AtomicIncrement(¤t_.concurrent_scope_data[id], - static_cast<Atomic32>(ms)); - } - - void UpdateReason(BlinkGC::GCReason); - void IncreaseCompactionFreedSize(size_t); - void IncreaseCompactionFreedPages(size_t); - void IncreaseAllocatedObjectSize(size_t); - void DecreaseAllocatedObjectSize(size_t); - void IncreaseAllocatedSpace(size_t); - void DecreaseAllocatedSpace(size_t); - void IncreaseWrapperCount(size_t); - void DecreaseWrapperCount(size_t); - void IncreaseCollectedWrapperCount(size_t); - - // Called by the GC when it hits a point where allocated memory may be - // reported and garbage collection is possible. This is necessary, as - // increments and decrements are reported as close to their actual - // allocation/reclamation as possible. - void AllocatedObjectSizeSafepoint(); - - // Size of objects on the heap. Based on marked bytes in the previous cycle - // and newly allocated bytes since the previous cycle. - size_t object_size_in_bytes() const; - - size_t marked_bytes() const; - base::TimeDelta marking_time_so_far() const; - - base::TimeDelta worklist_processing_time_foreground() const; - - base::TimeDelta flushing_v8_references_time() const; - - int64_t allocated_bytes_since_prev_gc() const; - - size_t allocated_space_bytes() const; - - size_t wrapper_count() const; - size_t collected_wrapper_count() const; - - bool is_started() const { return is_started_; } - - // Statistics for the previously running garbage collection. - const Event& previous() const { return previous_; } - - void RegisterObserver(ThreadHeapStatsObserver* observer); - void UnregisterObserver(ThreadHeapStatsObserver* observer); - - void IncreaseAllocatedObjectSizeForTesting(size_t); - void DecreaseAllocatedObjectSizeForTesting(size_t); - - private: - // Observers are implemented using virtual calls. Avoid notifications below - // reasonably interesting sizes. - static constexpr int64_t kUpdateThreshold = 1024; - - // Invokes |callback| for all registered observers. - template <typename Callback> - void ForAllObservers(Callback callback); - - void AllocatedObjectSizeSafepointImpl(); - - // Statistics for the currently running garbage collection. Note that the - // Event may not be fully populated yet as some phase may not have been run. - const Event& current() const { return current_; } - - Event current_; - Event previous_; - - // Allocated bytes since the last garbage collection. These bytes are reset - // after marking as they are accounted in marked_bytes then. - int64_t allocated_bytes_since_prev_gc_ = 0; - int64_t pos_delta_allocated_bytes_since_prev_gc_ = 0; - int64_t neg_delta_allocated_bytes_since_prev_gc_ = 0; - - // Allocated space in bytes for all arenas. - size_t allocated_space_bytes_ = 0; - - bool is_started_ = false; - bool is_sweeping_ = false; - - // base::TimeDelta for RawScope. These don't need to be nested within a - // garbage collection cycle to make them easier to use. - base::TimeDelta gc_nested_in_v8_; - - Vector<ThreadHeapStatsObserver*> observers_; - - FRIEND_TEST_ALL_PREFIXES(ThreadHeapStatsCollectorTest, InitialEmpty); - FRIEND_TEST_ALL_PREFIXES(ThreadHeapStatsCollectorTest, IncreaseScopeTime); - FRIEND_TEST_ALL_PREFIXES(ThreadHeapStatsCollectorTest, StopResetsCurrent); -}; - -template <ThreadHeapStatsCollector::TraceCategory trace_category, - ThreadHeapStatsCollector::ScopeContext scope_category> -constexpr const char* -ThreadHeapStatsCollector::InternalScope<trace_category, - scope_category>::TraceCategory() { - switch (trace_category) { - case kEnabled: - return "blink_gc,devtools.timeline"; - case kDisabled: - return TRACE_DISABLED_BY_DEFAULT("blink_gc"); - } -} - -template <ThreadHeapStatsCollector::TraceCategory trace_category, - ThreadHeapStatsCollector::ScopeContext scope_category> -void ThreadHeapStatsCollector::InternalScope<trace_category, - scope_category>::StartTrace() { - TRACE_EVENT_BEGIN0(TraceCategory(), - ToString(id_, tracer_->current_.collection_type)); -} - -template <ThreadHeapStatsCollector::TraceCategory trace_category, - ThreadHeapStatsCollector::ScopeContext scope_category> -template <typename Value1> -void ThreadHeapStatsCollector::InternalScope<trace_category, scope_category>:: - StartTrace(const char* k1, Value1 v1) { - TRACE_EVENT_BEGIN1(TraceCategory(), - ToString(id_, tracer_->current_.collection_type), k1, v1); -} - -template <ThreadHeapStatsCollector::TraceCategory trace_category, - ThreadHeapStatsCollector::ScopeContext scope_category> -template <typename Value1, typename Value2> -void ThreadHeapStatsCollector::InternalScope<trace_category, scope_category>:: - StartTrace(const char* k1, Value1 v1, const char* k2, Value2 v2) { - TRACE_EVENT_BEGIN2(TraceCategory(), - ToString(id_, tracer_->current_.collection_type), k1, v1, - k2, v2); -} - -template <ThreadHeapStatsCollector::TraceCategory trace_category, - ThreadHeapStatsCollector::ScopeContext scope_category> -void ThreadHeapStatsCollector::InternalScope<trace_category, - scope_category>::StopTrace() { - TRACE_EVENT_END2(TraceCategory(), - ToString(id_, tracer_->current_.collection_type), "epoch", - tracer_->current_.unique_id, "forced", - tracer_->current_.is_forced_gc); -} - -template <ThreadHeapStatsCollector::TraceCategory trace_category, - ThreadHeapStatsCollector::ScopeContext scope_category> -void ThreadHeapStatsCollector::InternalScope<trace_category, scope_category>:: - IncreaseScopeTime(Id) { - tracer_->IncreaseScopeTime(id_, base::TimeTicks::Now() - start_time_); -} - -template <ThreadHeapStatsCollector::TraceCategory trace_category, - ThreadHeapStatsCollector::ScopeContext scope_category> -void ThreadHeapStatsCollector::InternalScope<trace_category, scope_category>:: - IncreaseScopeTime(ConcurrentId) { - tracer_->IncreaseConcurrentScopeTime(id_, - base::TimeTicks::Now() - start_time_); -} - -#undef FOR_ALL_SCOPES -#undef FOR_ALL_CONCURRENT_SCOPES - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_HEAP_STATS_COLLECTOR_H_
diff --git a/third_party/blink/renderer/platform/heap/impl/heap_test_utilities.cc b/third_party/blink/renderer/platform/heap/impl/heap_test_utilities.cc deleted file mode 100644 index 3d487a099..0000000 --- a/third_party/blink/renderer/platform/heap/impl/heap_test_utilities.cc +++ /dev/null
@@ -1,108 +0,0 @@ -/* - * Copyright 2017 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/heap/heap_test_utilities.h" - -#include "third_party/blink/renderer/platform/heap/heap.h" -#include "third_party/blink/renderer/platform/heap/impl/heap_compact.h" - -namespace blink { - -// static -void TestSupportingGC::PreciselyCollectGarbage( - BlinkGC::SweepingType sweeping_type) { - ThreadState::Current()->CollectGarbageForTesting( - BlinkGC::CollectionType::kMajor, BlinkGC::kNoHeapPointersOnStack, - BlinkGC::kAtomicMarking, sweeping_type, - BlinkGC::GCReason::kForcedGCForTesting); -} - -// static -void TestSupportingGC::ConservativelyCollectGarbage( - BlinkGC::SweepingType sweeping_type) { - ThreadState::Current()->CollectGarbageForTesting( - BlinkGC::CollectionType::kMajor, BlinkGC::kHeapPointersOnStack, - BlinkGC::kAtomicMarking, sweeping_type, - BlinkGC::GCReason::kForcedGCForTesting); -} - -TestSupportingGC::~TestSupportingGC() { - // Complete sweeping before |task_environment_| is destroyed. - if (ThreadState::Current()->IsSweepingInProgress()) - ThreadState::Current()->CompleteSweep(); -} - -void TestSupportingGC::ClearOutOldGarbage() { - PreciselyCollectGarbage(); - ThreadHeap& heap = ThreadState::Current()->Heap(); - while (true) { - size_t used = heap.ObjectPayloadSizeForTesting(); - PreciselyCollectGarbage(); - if (heap.ObjectPayloadSizeForTesting() >= used) - break; - } -} - -void CompactionTestDriver::ForceCompactionForNextGC() { - ThreadState::Current()->EnableCompactionForNextGCForTesting(); -} - -IncrementalMarkingTestDriver::~IncrementalMarkingTestDriver() { - if (thread_state_->IsIncrementalMarking()) - FinishGC(); -} - -void IncrementalMarkingTestDriver::StartGC() { - thread_state_->IncrementalMarkingStartForTesting(); -} - -bool IncrementalMarkingTestDriver::TriggerSingleMarkingStep( - BlinkGC::StackState stack_state) { - CHECK(thread_state_->IsIncrementalMarking()); - if (thread_state_->GetGCState() == - ThreadState::kIncrementalMarkingStepScheduled) { - thread_state_->IncrementalMarkingStep(stack_state); - return true; - } - return false; -} - -void IncrementalMarkingTestDriver::TriggerMarkingSteps( - BlinkGC::StackState stack_state) { - CHECK(thread_state_->IsIncrementalMarking()); - while (TriggerSingleMarkingStep(stack_state)) { - } -} - -void IncrementalMarkingTestDriver::FinishGC(bool complete_sweep) { - CHECK(thread_state_->IsIncrementalMarking()); - IncrementalMarkingTestDriver::TriggerMarkingSteps( - BlinkGC::StackState::kNoHeapPointersOnStack); - CHECK_EQ(ThreadState::kIncrementalMarkingFinalizeScheduled, - thread_state_->GetGCState()); - thread_state_->ForceNoFollowupFullGCForTesting(); - thread_state_->IncrementalMarkingFinalize(); - CHECK(!thread_state_->IsIncrementalMarking()); - if (complete_sweep) { - thread_state_->CompleteSweep(); - } -} - -size_t IncrementalMarkingTestDriver::GetHeapCompactLastFixupCount() const { - HeapCompact* compaction = ThreadState::Current()->Heap().Compaction(); - return compaction->LastFixupCountForTesting(); -} - -void ConcurrentMarkingTestDriver::TriggerMarkingSteps( - BlinkGC::StackState stack_state) { - if (thread_state_->GetGCState() == - ThreadState::kIncrementalMarkingStepScheduled) { - thread_state_->SkipIncrementalMarkingForTesting(); - TriggerSingleMarkingStep(); - } -} - -} // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/impl/heap_test_utilities.h b/third_party/blink/renderer/platform/heap/impl/heap_test_utilities.h deleted file mode 100644 index 3158d586..0000000 --- a/third_party/blink/renderer/platform/heap/impl/heap_test_utilities.h +++ /dev/null
@@ -1,105 +0,0 @@ -/* - * Copyright 2017 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. - */ - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_HEAP_TEST_UTILITIES_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_HEAP_TEST_UTILITIES_H_ - -#include "base/callback.h" -#include "base/test/task_environment.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/renderer/platform/heap/heap.h" - -namespace blink { - -class HeapPointersOnStackScope final { - STACK_ALLOCATED(); - - public: - explicit HeapPointersOnStackScope(ThreadState* state) : state_(state) { - DCHECK(!state_->heap_pointers_on_stack_forced_); - state_->heap_pointers_on_stack_forced_ = true; - } - ~HeapPointersOnStackScope() { - DCHECK(state_->heap_pointers_on_stack_forced_); - state_->heap_pointers_on_stack_forced_ = false; - } - - private: - ThreadState* const state_; -}; - -class TestSupportingGC : public testing::Test { - public: - // Performs a precise garbage collection with eager sweeping. - static void PreciselyCollectGarbage( - BlinkGC::SweepingType sweeping_type = BlinkGC::kEagerSweeping); - - // Performs a conservative garbage collection. - static void ConservativelyCollectGarbage( - BlinkGC::SweepingType sweeping_type = BlinkGC::kEagerSweeping); - - ~TestSupportingGC() override; - - // Performs multiple rounds of garbage collections until no more memory can be - // freed. This is useful to avoid other garbage collections having to deal - // with stale memory. - void ClearOutOldGarbage(); - - protected: - base::test::TaskEnvironment task_environment_; -}; - -// Test driver for compaction. -class CompactionTestDriver { - public: - explicit CompactionTestDriver(ThreadState* thread_state) - : thread_state_(thread_state) {} - - void ForceCompactionForNextGC(); - - protected: - ThreadState* const thread_state_; -}; - -// Test driver for incremental marking. Assumes that no stack handling is -// required. -class IncrementalMarkingTestDriver { - public: - explicit IncrementalMarkingTestDriver(ThreadState* thread_state) - : thread_state_(thread_state) {} - ~IncrementalMarkingTestDriver(); - - void StartGC(); - virtual void TriggerMarkingSteps( - BlinkGC::StackState stack_state = - BlinkGC::StackState::kNoHeapPointersOnStack); - void FinishGC(bool complete_sweep = true); - - size_t GetHeapCompactLastFixupCount() const; - - protected: - bool TriggerSingleMarkingStep( - BlinkGC::StackState stack_state = - BlinkGC::StackState::kNoHeapPointersOnStack); - - ThreadState* const thread_state_; -}; - -// Test driver for concurrent marking. Assumes that no stack handling is -// required. -class ConcurrentMarkingTestDriver : public IncrementalMarkingTestDriver { - public: - explicit ConcurrentMarkingTestDriver(ThreadState* thread_state) - : IncrementalMarkingTestDriver(thread_state) {} - - void TriggerMarkingSteps( - BlinkGC::StackState stack_state = - BlinkGC::StackState::kNoHeapPointersOnStack) override; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_HEAP_TEST_UTILITIES_H_
diff --git a/third_party/blink/renderer/platform/heap/impl/marking_scheduling_oracle.cc b/third_party/blink/renderer/platform/heap/impl/marking_scheduling_oracle.cc deleted file mode 100644 index e75cd530..0000000 --- a/third_party/blink/renderer/platform/heap/impl/marking_scheduling_oracle.cc +++ /dev/null
@@ -1,99 +0,0 @@ -// Copyright 2020 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/heap/impl/marking_scheduling_oracle.h" - -#include "base/cxx17_backports.h" - -namespace blink { - -constexpr double MarkingSchedulingOracle::kEstimatedMarkingTimeMs; -constexpr base::TimeDelta - MarkingSchedulingOracle::kDefaultIncrementalMarkingStepDuration; -constexpr size_t MarkingSchedulingOracle::kMinimumMarkedBytesInStep; -constexpr base::TimeDelta - MarkingSchedulingOracle::kMaximumIncrementalMarkingStepDuration; - -MarkingSchedulingOracle::MarkingSchedulingOracle() - : incremental_marking_start_time_(base::TimeTicks::Now()) {} - -void MarkingSchedulingOracle::UpdateIncrementalMarkingStats( - size_t overall_marked_bytes, - base::TimeDelta overall_marking_time, - base::TimeDelta non_contributing_time) { - incrementally_marked_bytes_ = overall_marked_bytes; - // |non_contributing_time| is time spent during |overall_marking_time| which - // does not contribute to |overall_marked_bytes| and is thus ignored so that - // it doesn't affect the marking speed. - DCHECK_LE(non_contributing_time, overall_marking_time); - incremental_marking_time_so_far_ = - overall_marking_time - non_contributing_time; -} - -void MarkingSchedulingOracle::AddConcurrentlyMarkedBytes(size_t marked_bytes) { - concurrently_marked_bytes_.fetch_add(marked_bytes, std::memory_order_relaxed); -} - -size_t MarkingSchedulingOracle::GetConcurrentlyMarkedBytes() { - return concurrently_marked_bytes_.load(std::memory_order_relaxed); -} - -size_t MarkingSchedulingOracle::GetOverallMarkedBytes() { - return incrementally_marked_bytes_ + GetConcurrentlyMarkedBytes(); -} - -double MarkingSchedulingOracle::GetElapsedTimeInMs(base::TimeTicks start_time) { - if (elapsed_time_for_testing_ != kNoSetElapsedTimeForTesting) { - double elapsed_time = elapsed_time_for_testing_; - elapsed_time_for_testing_ = kNoSetElapsedTimeForTesting; - return elapsed_time; - } - return (base::TimeTicks::Now() - start_time).InMillisecondsF(); -} - -base::TimeDelta MarkingSchedulingOracle::GetMinimumStepDuration() { - DCHECK_LT(0u, incrementally_marked_bytes_); - DCHECK(!incremental_marking_time_so_far_.is_zero()); - base::TimeDelta minimum_duration = incremental_marking_time_so_far_ * - kMinimumMarkedBytesInStep / - incrementally_marked_bytes_; - return std::min(minimum_duration, kMaximumIncrementalMarkingStepDuration); -} - -base::TimeDelta MarkingSchedulingOracle::GetNextIncrementalStepDurationForTask( - size_t estimated_live_bytes) { - if ((incrementally_marked_bytes_ == 0) || - incremental_marking_time_so_far_.is_zero()) { - // Impossible to estimate marking speed. Fallback to default duration. - return kDefaultIncrementalMarkingStepDuration; - } - double elapsed_time_in_ms = - GetElapsedTimeInMs(incremental_marking_start_time_); - size_t actual_marked_bytes = GetOverallMarkedBytes(); - double expected_marked_bytes = - estimated_live_bytes * elapsed_time_in_ms / kEstimatedMarkingTimeMs; - base::TimeDelta minimum_duration = GetMinimumStepDuration(); - if (expected_marked_bytes < actual_marked_bytes) { - // Marking is ahead of schedule, incremental marking doesn't need to - // do anything. - return minimum_duration; - } - // Assuming marking will take |kEstimatedMarkingTime|, overall there will - // be |estimated_live_bytes| live bytes to mark, and that marking speed is - // constant, after |elapsed_time| the number of marked_bytes should be - // |estimated_live_bytes| * (|elapsed_time| / |kEstimatedMarkingTime|), - // denoted as |expected_marked_bytes|. If |actual_marked_bytes| is less, - // i.e. marking is behind schedule, incremental marking should help "catch - // up" by marking (|expected_marked_bytes| - |actual_marked_bytes|). - // Assuming constant marking speed, duration of the next incremental step - // should be as follows: - const base::TimeDelta marking_time_to_catch_up = - incremental_marking_time_so_far_ * - (expected_marked_bytes - actual_marked_bytes) / - incrementally_marked_bytes_; - return base::clamp(marking_time_to_catch_up, minimum_duration, - kMaximumIncrementalMarkingStepDuration); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/impl/marking_scheduling_oracle.h b/third_party/blink/renderer/platform/heap/impl/marking_scheduling_oracle.h deleted file mode 100644 index 19c9e0b..0000000 --- a/third_party/blink/renderer/platform/heap/impl/marking_scheduling_oracle.h +++ /dev/null
@@ -1,65 +0,0 @@ -// Copyright 2020 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. - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_MARKING_SCHEDULING_ORACLE_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_MARKING_SCHEDULING_ORACLE_H_ - -#include <atomic> - -#include "base/time/time.h" -#include "third_party/blink/renderer/platform/heap/blink_gc.h" - -namespace blink { - -class PLATFORM_EXPORT MarkingSchedulingOracle { - public: - // Estimated duration of GC cycle in milliseconds. - static constexpr double kEstimatedMarkingTimeMs = 500.0; - - // Duration of one incremental marking step. Should be short enough that it - // doesn't cause jank even though it is scheduled as a normal task. - static constexpr base::TimeDelta kDefaultIncrementalMarkingStepDuration = - base::TimeDelta::FromMillisecondsD(0.5); - - // Minimum number of bytes that should be marked during an incremental - // marking step. - static constexpr size_t kMinimumMarkedBytesInStep = 64 * 1024; - - // Maximum duration of one incremental marking step. Should be short enough - // that it doesn't cause jank even though it is scheduled as a normal task. - static constexpr base::TimeDelta kMaximumIncrementalMarkingStepDuration = - base::TimeDelta::FromMillisecondsD(2.0); - - explicit MarkingSchedulingOracle(); - - void UpdateIncrementalMarkingStats(size_t, base::TimeDelta, base::TimeDelta); - void AddConcurrentlyMarkedBytes(size_t); - - size_t GetConcurrentlyMarkedBytes(); - size_t GetOverallMarkedBytes(); - - base::TimeDelta GetNextIncrementalStepDurationForTask(size_t); - - void SetElapsedTimeForTesting(double elapsed_time) { - elapsed_time_for_testing_ = elapsed_time; - } - - private: - double GetElapsedTimeInMs(base::TimeTicks); - base::TimeDelta GetMinimumStepDuration(); - - base::TimeTicks incremental_marking_start_time_; - base::TimeDelta incremental_marking_time_so_far_; - - size_t incrementally_marked_bytes_ = 0; - std::atomic_size_t concurrently_marked_bytes_{0}; - - // Using -1 as sentinel to denote - static constexpr double kNoSetElapsedTimeForTesting = -1; - double elapsed_time_for_testing_ = kNoSetElapsedTimeForTesting; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_MARKING_SCHEDULING_ORACLE_H_
diff --git a/third_party/blink/renderer/platform/heap/impl/marking_verifier.cc b/third_party/blink/renderer/platform/heap/impl/marking_verifier.cc deleted file mode 100644 index bf9ee20..0000000 --- a/third_party/blink/renderer/platform/heap/impl/marking_verifier.cc +++ /dev/null
@@ -1,83 +0,0 @@ -// Copyright 2019 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/heap/impl/marking_verifier.h" - -#include "base/logging.h" -#include "third_party/blink/renderer/platform/heap/garbage_collected.h" -#include "third_party/blink/renderer/platform/heap/impl/heap_page.h" - -namespace blink { - -void MarkingVerifier::VerifyObject(HeapObjectHeader* header) { - // Verify only non-free marked objects. - if (header->IsFree() || !header->IsMarked()) - return; - - const GCInfo& info = GCInfo::From(header->GcInfoIndex()); - const bool can_verify = - !info.has_v_table || blink::VTableInitialized(header->Payload()); - if (can_verify) { - parent_ = header; - info.trace(this, header->Payload()); - } -} - -void MarkingVerifier::Visit(const void* object, TraceDescriptor desc) { - VerifyChild(object, desc.base_object_payload); -} - -void MarkingVerifier::VisitWeak(const void* object, - const void* object_weak_ref, - TraceDescriptor desc, - WeakCallback callback) { - // Weak objects should have been cleared at this point. As a consequence, all - // objects found through weak references have to point to live objects at this - // point. - VerifyChild(object, desc.base_object_payload); -} - -void MarkingVerifier::VisitWeakContainer(const void* object, - const void* const*, - TraceDescriptor, - TraceDescriptor weak_desc, - WeakCallback, - const void*) { - if (!object) - return; - - // Contents of weak backing stores are found themselves through page - // iteration and are treated strongly that way, similar to how they are - // treated strongly when found through stack scanning. The verification - // here only makes sure that the backing itself is properly marked. Weak - // backing stores found through - VerifyChild(object, weak_desc.base_object_payload); -} - -void MarkingVerifier::VerifyChild(const void* object, - const void* base_object_payload) { - CHECK(object); - // Verification may check objects that are currently under construction and - // would require vtable access to figure out their headers. A nullptr in - // |base_object_payload| indicates that a mixin object is in construction - // and the vtable cannot be used to get to the object header. - const HeapObjectHeader* const child_header = - (base_object_payload) ? HeapObjectHeader::FromPayload(base_object_payload) - : HeapObjectHeader::FromInnerAddress(object); - // These checks ensure that any children reachable from marked parents are - // also marked. If you hit these checks then marking is in an inconsistent - // state meaning that there are unmarked objects reachable from marked - // ones. - CHECK(child_header); - if (!child_header->IsMarked()) { - CHECK(!PageFromObject(child_header->Payload())->HasBeenSwept()); - LOG(FATAL) << "MarkingVerifier: Encountered unmarked object. " << std::endl - << std::endl - << "Hint: " << std::endl - << parent_->Name() << std::endl - << "\\-> " << child_header->Name() << std::endl; - } -} - -} // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/impl/marking_verifier.h b/third_party/blink/renderer/platform/heap/impl/marking_verifier.h deleted file mode 100644 index ee4266a..0000000 --- a/third_party/blink/renderer/platform/heap/impl/marking_verifier.h +++ /dev/null
@@ -1,43 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_MARKING_VERIFIER_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_MARKING_VERIFIER_H_ - -#include "third_party/blink/renderer/platform/heap/visitor.h" - -namespace blink { - -class HeapObjectHeader; - -// Marking verifier that checks that a child is marked if its parent is marked. -class MarkingVerifier final : public Visitor { - public: - explicit MarkingVerifier(ThreadState* state) : Visitor(state) {} - ~MarkingVerifier() override = default; - - void VerifyObject(HeapObjectHeader* header); - - void Visit(const void* object, TraceDescriptor desc) final; - void VisitWeak(const void* object, - const void* object_weak_ref, - TraceDescriptor desc, - WeakCallback callback) final; - - void VisitWeakContainer(const void*, - const void* const*, - TraceDescriptor, - TraceDescriptor, - WeakCallback, - const void*) final; - - private: - void VerifyChild(const void* object, const void* base_object_payload); - - HeapObjectHeader* parent_ = nullptr; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_MARKING_VERIFIER_H_
diff --git a/third_party/blink/renderer/platform/heap/impl/marking_visitor.cc b/third_party/blink/renderer/platform/heap/impl/marking_visitor.cc deleted file mode 100644 index 91300b48..0000000 --- a/third_party/blink/renderer/platform/heap/impl/marking_visitor.cc +++ /dev/null
@@ -1,370 +0,0 @@ -// 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/heap/impl/marking_visitor.h" - -#include "third_party/blink/renderer/platform/heap/blink_gc.h" -#include "third_party/blink/renderer/platform/heap/heap.h" -#include "third_party/blink/renderer/platform/heap/impl/heap_page.h" -#include "third_party/blink/renderer/platform/heap/thread_state.h" - -namespace blink { - -MarkingVisitorBase::MarkingVisitorBase(ThreadState* state, - MarkingMode marking_mode, - int task_id) - : Visitor(state), - marking_worklist_(Heap().GetMarkingWorklist(), task_id), - write_barrier_worklist_(Heap().GetWriteBarrierWorklist(), task_id), - not_fully_constructed_worklist_(Heap().GetNotFullyConstructedWorklist(), - task_id), - weak_callback_worklist_(Heap().GetWeakCallbackWorklist(), task_id), - movable_reference_worklist_(Heap().GetMovableReferenceWorklist(), - task_id), - discovered_ephemeron_pairs_worklist_( - Heap().GetDiscoveredEphemeronPairsWorklist(), - task_id), - ephemeron_pairs_to_process_worklist_( - Heap().GetEphemeronPairsToProcessWorklist(), - task_id), - weak_containers_worklist_(Heap().GetWeakContainersWorklist()), - marking_mode_(marking_mode), - task_id_(task_id) {} - -void MarkingVisitorBase::FlushCompactionWorklists() { - if (marking_mode_ != kGlobalMarkingWithCompaction) - return; - movable_reference_worklist_.FlushToGlobal(); -} - -void MarkingVisitorBase::RegisterWeakCallback(WeakCallback callback, - const void* object) { - weak_callback_worklist_.Push({callback, object}); -} - -void MarkingVisitorBase::RegisterMovableSlot(const void* const* slot) { - if (marking_mode_ != kGlobalMarkingWithCompaction) - return; - if (Heap().ShouldRegisterMovingAddress()) { - movable_reference_worklist_.Push(slot); - } -} - -void MarkingVisitorBase::VisitWeak(const void* object, - const void* object_weak_ref, - TraceDescriptor desc, - WeakCallback callback) { - HeapObjectHeader* header = - HeapObjectHeader::FromPayload(desc.base_object_payload); - if (header->IsInConstruction<HeapObjectHeader::AccessMode::kAtomic>()) { - not_fully_constructed_worklist_.Push(desc.base_object_payload); - return; - } - // Filter out already marked values. The write barrier for WeakMember - // ensures that any newly set value after this point is kept alive and does - // not require the callback. - if (header->IsMarked<HeapObjectHeader::AccessMode::kAtomic>()) - return; - RegisterWeakCallback(callback, object_weak_ref); -} - -void MarkingVisitorBase::VisitEphemeron(const void* key, - TraceDescriptor value_desc) { - HeapObjectHeader* key_header = HeapObjectHeader::FromPayload(key); - if (!key_header->IsInConstruction<HeapObjectHeader::AccessMode::kAtomic>() && - !key_header->IsMarked<HeapObjectHeader::AccessMode::kAtomic>()) { - // In construction keys are considered as marked because they are - // guaranteed to be marked by the end of GC (e.g. by write barrier - // on insertion to HashTable). - discovered_ephemeron_pairs_worklist_.Push({key, value_desc}); - return; - } - value_desc.callback(this, value_desc.base_object_payload); -} - -void MarkingVisitorBase::VisitWeakContainer( - const void* object, - const void* const*, - TraceDescriptor, - TraceDescriptor weak_desc, - WeakCallback weak_callback, - const void* weak_callback_parameter) { - // In case there's no object present, weakness processing is omitted. The GC - // relies on the fact that in such cases touching the weak data structure will - // strongify its references. - if (!object) - return; - - HeapObjectHeader* header = HeapObjectHeader::FromPayload(object); - // We shouldn't trace an in-construction backing store of a weak container. - // If this container is an ephemeron, we will try to iterate over it's - // bucket which is unsafe when the backing store is in construction. - if (header->IsInConstruction<HeapObjectHeader::AccessMode::kAtomic>()) { - not_fully_constructed_worklist_.Push(object); - return; - } - - // Only trace the container initially. Its buckets will be processed after - // marking. The interesting cases are: - // - The backing of the container is dropped using clear(): The backing can - // still be compacted but empty/deleted buckets will only be destroyed once - // the backing is reclaimed by the garbage collector on the next cycle. - // - The container expands/shrinks: Buckets are moved to the new backing - // store and strongified, resulting in all buckets being alive. The old - // backing store is marked but only contains empty/deleted buckets as all - // non-empty/deleted buckets have been moved to the new backing store. - MarkHeaderNoTracing(header); - AccountMarkedBytes(header); - weak_containers_worklist_->Push(header); - - // Register final weak processing of the backing store. - RegisterWeakCallback(weak_callback, weak_callback_parameter); - // Register ephemeron callbacks if necessary. - if (weak_desc.callback) - weak_desc.callback(this, weak_desc.base_object_payload); -} - -void MarkingVisitorBase::DynamicallyMarkAddress(ConstAddress address) { - constexpr HeapObjectHeader::AccessMode mode = - HeapObjectHeader::AccessMode::kAtomic; - HeapObjectHeader* const header = - HeapObjectHeader::FromInnerAddress<mode>(address); - DCHECK(header); - DCHECK(!header->IsInConstruction<mode>()); - if (MarkHeaderNoTracing(header)) { - marking_worklist_.Push({reinterpret_cast<void*>(header->Payload()), - GCInfo::From(header->GcInfoIndex<mode>()).trace}); - } -} - -// static -bool MarkingVisitor::MarkValue(void* value, - BasePage* base_page, - ThreadState* thread_state) { - HeapObjectHeader* header; - if (LIKELY(!base_page->IsLargeObjectPage())) { - header = reinterpret_cast<HeapObjectHeader*>( - static_cast<NormalPage*>(base_page)->FindHeaderFromAddress( - reinterpret_cast<Address>(value))); - } else { - LargeObjectPage* large_page = static_cast<LargeObjectPage*>(base_page); - header = large_page->ObjectHeader(); - } - - if (!header->TryMark<HeapObjectHeader::AccessMode::kAtomic>()) - return false; - - MarkingVisitor* visitor = thread_state->CurrentVisitor(); - if (UNLIKELY( - header->IsInConstruction<HeapObjectHeader::AccessMode::kAtomic>())) { - // It is assumed that objects on not_fully_constructed_worklist_ are not - // marked. - header->Unmark<HeapObjectHeader::AccessMode::kAtomic>(); - visitor->not_fully_constructed_worklist_.Push(header->Payload()); - return true; - } - - visitor->write_barrier_worklist_.Push(header); - return true; -} - -// static -bool MarkingVisitor::WriteBarrierSlow(void* value) { - if (!value || internal::IsHashTableDeleteValue(value)) - return false; - - // It is guaranteed that managed references point to either GarbageCollected - // or GarbageCollectedMixin. Mixins are restricted to regular objects sizes. - // It is thus possible to get to the page header by aligning properly. - BasePage* base_page = PageFromObject(value); - - ThreadState* const thread_state = base_page->thread_state(); - if (!thread_state->IsIncrementalMarking()) - return false; - - return MarkValue(value, base_page, thread_state); -} - -void MarkingVisitor::GenerationalBarrierSlow(Address slot, - ThreadState* thread_state) { - BasePage* slot_page = thread_state->Heap().LookupPageForAddress(slot); - DCHECK(slot_page); - - if (UNLIKELY(slot_page->IsLargeObjectPage())) { - auto* large_page = static_cast<LargeObjectPage*>(slot_page); - if (UNLIKELY(large_page->ObjectHeader()->IsOld())) { - large_page->SetRemembered(true); - } - return; - } - - auto* normal_page = static_cast<NormalPage*>(slot_page); - const HeapObjectHeader* source_header = reinterpret_cast<HeapObjectHeader*>( - normal_page->object_start_bit_map()->FindHeader(slot)); - DCHECK_LT(0u, source_header->GcInfoIndex()); - DCHECK_GT(source_header->PayloadEnd(), slot); - if (UNLIKELY(source_header->IsOld())) { - normal_page->MarkCard(slot); - } -} - -void MarkingVisitor::RetraceObjectSlow(const void* object) { - if (!object) - return; - - // Trace object only if it is marked and thus has been traced before. The - // marker may be active on the backing store which requires atomic mark bit - // access. - if (!HeapObjectHeader::FromPayload(object) - ->IsMarked<HeapObjectHeader::AccessMode::kAtomic>()) { - return; - } - - ThreadState* const thread_state = ThreadState::Current(); - if (!thread_state->IsIncrementalMarking()) - return; - - // |value| is pointing to the start of a backing store. - HeapObjectHeader* header = HeapObjectHeader::FromPayload(object); - CHECK(header->IsMarked()); - DCHECK(thread_state->CurrentVisitor()); - // No weak handling for write barriers. Modifying weakly reachable objects - // strongifies them for the current cycle. - - GCInfo::From(header->GcInfoIndex()) - .trace(thread_state->CurrentVisitor(), object); -} - -constexpr size_t MarkingVisitor::RecentlyRetracedWeakContainers::kMaxCacheSize; - -bool MarkingVisitor::RecentlyRetracedWeakContainers::Contains( - const HeapObjectHeader* header) { - return std::find(recently_retraced_cache_.begin(), - recently_retraced_cache_.end(), - header) != recently_retraced_cache_.end(); -} - -void MarkingVisitor::RecentlyRetracedWeakContainers::Insert( - const HeapObjectHeader* header) { - last_used_index_ = (last_used_index_ + 1) % kMaxCacheSize; - if (recently_retraced_cache_.size() <= last_used_index_) - recently_retraced_cache_.push_back(header); - else - recently_retraced_cache_[last_used_index_] = header; -} - -MarkingVisitor::MarkingVisitor(ThreadState* state, MarkingMode marking_mode) - : MarkingVisitorBase(state, marking_mode, WorklistTaskId::MutatorThread) { - DCHECK(state->InAtomicMarkingPause()); - DCHECK(state->CheckThread()); -} - -void MarkingVisitor::ConservativelyMarkAddress(BasePage* page, - ConstAddress address) { -#if DCHECK_IS_ON() - DCHECK(page->Contains(address)); -#endif - HeapObjectHeader* const header = - page->IsLargeObjectPage() - ? static_cast<LargeObjectPage*>(page)->ObjectHeader() - : static_cast<NormalPage*>(page)->ConservativelyFindHeaderFromAddress( - address); - if (!header) - return; - if (header->IsMarked()) { - // Weak containers found through conservative GC need to be strongified. In - // case the container was previously marked and weakly traced, it should be - // retraced strongly now. Previously marked/traced weak containers are - // marked using the |weak_containers_worklist_|. Other marked object can be - // skipped. - if (weak_containers_worklist_->Contains(header) && - !recently_retraced_weak_containers_.Contains(header)) { - DCHECK(!header->IsInConstruction()); - // Record the weak container backing store to avoid retracing it again. - recently_retraced_weak_containers_.Insert(header); - marking_worklist_.Push( - {header->Payload(), GCInfo::From(header->GcInfoIndex()).trace}); - } - return; - } - - // Simple case for fully constructed objects. This just adds the object to the - // regular marking worklist. - if (!header->IsInConstruction()) { - MarkHeader(header, - {header->Payload(), GCInfo::From(header->GcInfoIndex()).trace}); - return; - } - - // This case is reached for not-fully-constructed objects with vtables. - // We can differentiate multiple cases: - // 1. No vtable set up. Example: - // class A : public GarbageCollected<A> { virtual void f() = 0; }; - // class B : public A { B() : A(foo()) {}; }; - // The vtable for A is not set up if foo() allocates and triggers a GC. - // - // 2. Vtables properly set up (non-mixin case). - // 3. Vtables not properly set up (mixin) if GC is allowed during mixin - // construction. - // - // We use a simple conservative approach for these cases as they are not - // performance critical. - MarkHeaderNoTracing(header); - Address* payload = reinterpret_cast<Address*>(header->Payload()); - const size_t payload_size = header->PayloadSize(); - for (size_t i = 0; i < (payload_size / sizeof(Address)); ++i) { - Address maybe_ptr = payload[i]; -#if defined(MEMORY_SANITIZER) - // |payload| may be uninitialized by design or just contain padding bytes. - // Copy into a local variable that is unpoisoned for conservative marking. - // Copy into a temporary variable to maintain the original MSAN state. - __msan_unpoison(&maybe_ptr, sizeof(maybe_ptr)); -#endif - if (maybe_ptr) - Heap().CheckAndMarkPointer(this, maybe_ptr); - } - AccountMarkedBytes(header); -} - -void MarkingVisitor::FlushMarkingWorklists() { - marking_worklist_.FlushToGlobal(); - write_barrier_worklist_.FlushToGlobal(); -} - -ConcurrentMarkingVisitor::ConcurrentMarkingVisitor(ThreadState* state, - MarkingMode marking_mode, - int task_id) - : MarkingVisitorBase(state, marking_mode, task_id), - not_safe_to_concurrently_trace_worklist_( - Heap().GetNotSafeToConcurrentlyTraceWorklist(), - task_id), - previously_not_fully_constructed_worklist_( - Heap().GetPreviouslyNotFullyConstructedWorklist(), - task_id) { - DCHECK(!state->CheckThread()); - DCHECK_NE(WorklistTaskId::MutatorThread, task_id); -} - -ConcurrentMarkingVisitor::~ConcurrentMarkingVisitor() { - // ConcurrentMarkingVisitor should report all its marked_bytes before dying. - DCHECK_EQ(marked_bytes_, last_marked_bytes_); -} - -void ConcurrentMarkingVisitor::FlushWorklists() { - // Flush marking worklists for further marking on the mutator thread. - marking_worklist_.FlushToGlobal(); - write_barrier_worklist_.FlushToGlobal(); - not_fully_constructed_worklist_.FlushToGlobal(); - previously_not_fully_constructed_worklist_.FlushToGlobal(); - weak_callback_worklist_.FlushToGlobal(); - discovered_ephemeron_pairs_worklist_.FlushToGlobal(); - ephemeron_pairs_to_process_worklist_.FlushToGlobal(); - not_safe_to_concurrently_trace_worklist_.FlushToGlobal(); - // Flush compaction worklists. - if (marking_mode_ == kGlobalMarkingWithCompaction) { - movable_reference_worklist_.FlushToGlobal(); - } -} - -} // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/impl/marking_visitor.h b/third_party/blink/renderer/platform/heap/impl/marking_visitor.h deleted file mode 100644 index afa594b..0000000 --- a/third_party/blink/renderer/platform/heap/impl/marking_visitor.h +++ /dev/null
@@ -1,322 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_MARKING_VISITOR_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_MARKING_VISITOR_H_ - -#include "third_party/blink/renderer/platform/heap/heap.h" -#include "third_party/blink/renderer/platform/heap/heap_buildflags.h" -#include "third_party/blink/renderer/platform/heap/impl/heap_page.h" -#include "third_party/blink/renderer/platform/heap/thread_state_scopes.h" -#include "third_party/blink/renderer/platform/heap/visitor.h" - -namespace blink { - -namespace internal { - -ALWAYS_INLINE bool IsHashTableDeleteValue(const void* value) { - return value == reinterpret_cast<void*>(-1); -} - -} // namespace internal - -class BasePage; -enum class TracenessMemberConfiguration; -template <typename T, TracenessMemberConfiguration tracenessConfiguration> -class MemberBase; - -// Base visitor used to mark Oilpan objects on any thread. -class PLATFORM_EXPORT MarkingVisitorBase : public Visitor { - public: - enum MarkingMode { - // Default visitor mode used for regular marking. - kGlobalMarking, - // Visitor mode recording slots for compaction during marking. - kGlobalMarkingWithCompaction, - }; - - void VisitWeakContainer(const void*, - const void* const*, - TraceDescriptor, - TraceDescriptor, - WeakCallback, - const void*) final; - void VisitEphemeron(const void*, TraceDescriptor) final; - - // Marks an object dynamically using any address within its body and adds a - // tracing callback for processing of the object. The object is not allowed - // to be in construction. - void DynamicallyMarkAddress(ConstAddress); - - void RegisterMovableSlot(const void* const*) final; - - void RegisterWeakCallback(WeakCallback, const void*) final; - - // Flush private segments remaining in visitor's worklists to global pools. - void FlushCompactionWorklists(); - - size_t marked_bytes() const { return marked_bytes_; } - - int task_id() const { return task_id_; } - - // Account for object's live bytes. Should only be adjusted when - // actually tracing through an already marked object. Logically, this means - // accounting for the bytes when transitioning from grey to black. - ALWAYS_INLINE void AccountMarkedBytes(HeapObjectHeader*); - ALWAYS_INLINE void AccountMarkedBytes(size_t); - - protected: - MarkingVisitorBase(ThreadState*, MarkingMode, int task_id); - ~MarkingVisitorBase() override = default; - - void Visit(const void* object, TraceDescriptor desc) final; - void VisitWeak(const void*, const void*, TraceDescriptor, WeakCallback) final; - - // Marks an object and adds a tracing callback for processing of the object. - void MarkHeader(HeapObjectHeader*, const TraceDescriptor&); - // Try to mark an object without tracing. Returns true when the object was not - // marked upon calling. - bool MarkHeaderNoTracing(HeapObjectHeader*); - - MarkingWorklist::View marking_worklist_; - WriteBarrierWorklist::View write_barrier_worklist_; - NotFullyConstructedWorklist::View not_fully_constructed_worklist_; - WeakCallbackWorklist::View weak_callback_worklist_; - MovableReferenceWorklist::View movable_reference_worklist_; - EphemeronPairsWorklist::View discovered_ephemeron_pairs_worklist_; - EphemeronPairsWorklist::View ephemeron_pairs_to_process_worklist_; - WeakContainersWorklist* const weak_containers_worklist_; - size_t marked_bytes_ = 0; - const MarkingMode marking_mode_; - int task_id_; -}; - -ALWAYS_INLINE void MarkingVisitorBase::AccountMarkedBytes( - HeapObjectHeader* header) { - AccountMarkedBytes( - header->IsLargeObject<HeapObjectHeader::AccessMode::kAtomic>() - ? static_cast<LargeObjectPage*>(PageFromObject(header))->ObjectSize() - : header->size<HeapObjectHeader::AccessMode::kAtomic>()); -} - -ALWAYS_INLINE void MarkingVisitorBase::AccountMarkedBytes(size_t marked_bytes) { - marked_bytes_ += marked_bytes; -} - -ALWAYS_INLINE bool MarkingVisitorBase::MarkHeaderNoTracing( - HeapObjectHeader* header) { - DCHECK(header); - DCHECK(State()->IsIncrementalMarking() || State()->InAtomicMarkingPause()); - // A GC should only mark the objects that belong in its heap. - DCHECK_EQ(State(), - PageFromObject(header->Payload())->Arena()->GetThreadState()); - // Never mark free space objects. This would e.g. hint to marking a promptly - // freed backing store. - DCHECK(!header->IsFree()); - - return header->TryMark<HeapObjectHeader::AccessMode::kAtomic>(); -} - -inline void MarkingVisitorBase::Visit(const void* object, - TraceDescriptor desc) { - DCHECK(object); - MarkHeader(HeapObjectHeader::FromPayload(desc.base_object_payload), desc); -} - -// Marks an object and adds a tracing callback for processing of the object. -ALWAYS_INLINE void MarkingVisitorBase::MarkHeader(HeapObjectHeader* header, - const TraceDescriptor& desc) { - DCHECK(header); - DCHECK(desc.callback); - - if (header->IsInConstruction<HeapObjectHeader::AccessMode::kAtomic>()) { - not_fully_constructed_worklist_.Push(header->Payload()); - } else if (MarkHeaderNoTracing(header)) { - marking_worklist_.Push(desc); - } -} - -// Visitor used to mark Oilpan objects on the main thread. Also implements -// various sorts of write barriers that should only be called from the main -// thread. -class PLATFORM_EXPORT MarkingVisitor : public MarkingVisitorBase { - public: - // Write barrier that adds a value the |slot| refers to to the set of marked - // objects. The barrier bails out if marking is off or the object is not yet - // marked. Returns true if the value has been marked on this call. - ALWAYS_INLINE static bool WriteBarrier(void** slot); - - using ThreadStateCallback = ThreadState*(); - // Write barrier where for a range of |number_of_elements| elements of size - // |element_size| starting at |first_element|. The |callback| will be invoked - // for each element if necessary. - ALWAYS_INLINE static void WriteBarrier( - ThreadStateCallback thread_state_callback, - void* first_element, - size_t element_size, - size_t number_of_elements, - TraceCallback callback); - - // Eagerly traces an already marked |object| ensuring that all its children - // are discovered by the marker. The barrier bails out if marking is off and - // on individual objects reachable if they are already marked. The barrier - // uses the callback function through GcInfo. - // - // Note: |object| must point to the beginning of the heap object. - ALWAYS_INLINE static void RetraceObject(const void* object); - - MarkingVisitor(ThreadState*, MarkingMode); - ~MarkingVisitor() override = default; - - // Conservatively marks an object if pointed to by Address. The object may - // be in construction as the scan is conservative without relying on a - // Trace method. - void ConservativelyMarkAddress(BasePage*, ConstAddress); - - void FlushMarkingWorklists(); - - private: - ALWAYS_INLINE static void GenerationalBarrier(Address slot, - ThreadState* state); - - // Exact version of the marking and generational write barriers. - static bool WriteBarrierSlow(void*); - static void GenerationalBarrierSlow(Address, ThreadState*); - static bool MarkValue(void*, BasePage*, ThreadState*); - static void RetraceObjectSlow(const void*); - - // Weak containers are strongly retraced during conservative stack scanning. - // Stack scanning happens once per GC at the start of the atomic pause. - // Because the visitor is not retained between GCs, there is no need to clear - // the set at the end of GC. - class RecentlyRetracedWeakContainers { - static constexpr size_t kMaxCacheSize = 8; - - public: - bool Contains(const HeapObjectHeader*); - void Insert(const HeapObjectHeader*); - - private: - std::vector<const HeapObjectHeader*> recently_retraced_cache_; - size_t last_used_index_ = -1; - } recently_retraced_weak_containers_; - - template <typename T, TracenessMemberConfiguration tracenessConfiguration> - friend class MemberBase; -}; - -// static -bool MarkingVisitor::WriteBarrier(void** slot) { -#if BUILDFLAG(BLINK_HEAP_YOUNG_GENERATION) - void* value = *slot; - if (!value || internal::IsHashTableDeleteValue(value)) - return false; - - // Dijkstra barrier if concurrent marking is in progress. - BasePage* value_page = PageFromObject(value); - ThreadState* thread_state = value_page->thread_state(); - - if (UNLIKELY(thread_state->IsIncrementalMarking())) - return MarkValue(value, value_page, thread_state); - - GenerationalBarrier(reinterpret_cast<Address>(slot), thread_state); - return false; -#else - if (!ThreadState::IsAnyIncrementalMarking()) - return false; - - // Avoid any further checks and dispatch to a call at this point. Aggressive - // inlining otherwise pollutes the regular execution paths. - return WriteBarrierSlow(*slot); -#endif -} - -// static -void MarkingVisitor::WriteBarrier(ThreadStateCallback thread_state_callback, - void* first_element, - size_t element_size, - size_t number_of_elements, - TraceCallback callback) { -#if BUILDFLAG(BLINK_HEAP_YOUNG_GENERATION) - ThreadState* const thread_state = thread_state_callback(); - if (!thread_state->IsIncrementalMarking()) { - MarkingVisitor::GenerationalBarrier( - reinterpret_cast<Address>(first_element), thread_state); - return; - } -#else // !BLINK_HEAP_YOUNG_GENERATION - if (!ThreadState::IsAnyIncrementalMarking()) - return; - // The object may have been in-place constructed as part of a large object. - // It is not safe to retrieve the page from the object here. - ThreadState* const thread_state = thread_state_callback(); - if (!thread_state->IsIncrementalMarking()) { - return; - } -#endif // !BLINK_HEAP_YOUNG_GENERATION - ThreadState::NoAllocationScope no_allocation_scope(thread_state); - DCHECK(thread_state->CurrentVisitor()); - // No weak handling for write barriers. Modifying weakly reachable objects - // strongifies them for the current cycle. - char* array = static_cast<char*>(first_element); - while (number_of_elements-- > 0) { - callback(thread_state->CurrentVisitor(), array); - array += element_size; - } -} - -// static -void MarkingVisitor::GenerationalBarrier(Address slot, ThreadState* state) { - // First, check if the source object is in the last allocated region of heap. - if (LIKELY(state->Heap().IsInLastAllocatedRegion(slot))) - return; - if (UNLIKELY(state->IsOnStack(slot))) - return; - GenerationalBarrierSlow(slot, state); -} - -// static -void MarkingVisitor::RetraceObject(const void* object) { - if (!ThreadState::IsAnyIncrementalMarking()) - return; - - RetraceObjectSlow(object); -} - -// Visitor used to mark Oilpan objects on concurrent threads. -class PLATFORM_EXPORT ConcurrentMarkingVisitor : public MarkingVisitorBase { - public: - ConcurrentMarkingVisitor(ThreadState*, MarkingMode, int); - ~ConcurrentMarkingVisitor() override; - - virtual void FlushWorklists(); - - bool IsConcurrent() const override { return true; } - - bool DeferredTraceIfConcurrent(TraceDescriptor desc, - size_t bailout_size) override { - not_safe_to_concurrently_trace_worklist_.Push({desc, bailout_size}); - // The object is bailed out from concurrent marking, so updating - // marked_bytes_ to reflect how many bytes were actually traced. - // This deducted bytes will be added to the mutator thread marking - // visitor's marked_bytes_ count when the object is popped from - // the bailout worklist. - marked_bytes_ -= bailout_size; - return true; - } - - size_t RecentlyMarkedBytes() { - return marked_bytes_ - std::exchange(last_marked_bytes_, marked_bytes_); - } - - private: - NotSafeToConcurrentlyTraceWorklist::View - not_safe_to_concurrently_trace_worklist_; - NotFullyConstructedWorklist::View previously_not_fully_constructed_worklist_; - size_t last_marked_bytes_ = 0; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_MARKING_VISITOR_H_
diff --git a/third_party/blink/renderer/platform/heap/impl/member.h b/third_party/blink/renderer/platform/heap/impl/member.h deleted file mode 100644 index d5d373f8..0000000 --- a/third_party/blink/renderer/platform/heap/impl/member.h +++ /dev/null
@@ -1,543 +0,0 @@ -// Copyright 2016 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. - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_MEMBER_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_MEMBER_H_ - -#include "base/dcheck_is_on.h" -#include "third_party/blink/renderer/platform/heap/heap.h" -#include "third_party/blink/renderer/platform/heap/heap_buildflags.h" -#include "third_party/blink/renderer/platform/heap/impl/heap_page.h" -#include "third_party/blink/renderer/platform/heap/impl/marking_visitor.h" -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" -#include "third_party/blink/renderer/platform/wtf/construct_traits.h" -#include "third_party/blink/renderer/platform/wtf/hash_functions.h" -#include "third_party/blink/renderer/platform/wtf/hash_table_deleted_value_type.h" -#include "third_party/blink/renderer/platform/wtf/hash_traits.h" - -namespace WTF { -template <typename P, typename Traits, typename Allocator> -class MemberConstructTraits; -} // namespace WTF - -namespace blink { - -template <typename T> -class Persistent; - -enum class TracenessMemberConfiguration { - kTraced, - kUntraced, -}; - -template <typename T, - TracenessMemberConfiguration tracenessConfiguration = - TracenessMemberConfiguration::kTraced> -class MemberPointerVerifier { - public: - MemberPointerVerifier() = default; - - void SaveCreationThreadState(T* pointer) { - if (tracenessConfiguration == TracenessMemberConfiguration::kUntraced) { - creation_thread_state_ = nullptr; - } else { - creation_thread_state_ = ThreadState::Current(); - // Members should be created in an attached thread. But an empty - // value Member may be created on an unattached thread by a heap - // collection iterator. - DCHECK(creation_thread_state_ || !pointer); - } - } - - void CheckPointer(T* pointer) { - if (!pointer) - return; - - ThreadState* current = ThreadState::Current(); - DCHECK(current); - if (tracenessConfiguration != TracenessMemberConfiguration::kUntraced) { - // creation_thread_state_ may be null when this is used in a heap - // collection which initialized the Member with memset and the - // constructor wasn't called. - if (creation_thread_state_) { - // Member should point to objects that belong in the same ThreadHeap. - DCHECK(creation_thread_state_->IsOnThreadHeap(pointer)); - // Member should point to objects that belong in the same ThreadHeap. - DCHECK_EQ(¤t->Heap(), &creation_thread_state_->Heap()); - } else { - DCHECK(current->IsOnThreadHeap(pointer)); - } - } - - if (current->IsSweepingInProgress()) { - // During sweeping the object start bitmap is invalid. Check the header - // when the type is available and not pointing to a mixin. - if (IsFullyDefined<T>::value && !IsGarbageCollectedMixin<T>::value) - HeapObjectHeader::CheckFromPayload(pointer); - } else { - DCHECK(HeapObjectHeader::FromInnerAddress< - HeapObjectHeader::AccessMode::kAtomic>(pointer)); - } - } - - private: - const ThreadState* creation_thread_state_; -}; - -template <typename T, - TracenessMemberConfiguration tracenessConfiguration = - TracenessMemberConfiguration::kTraced> -class MemberBase { - DISALLOW_NEW(); - - public: - MemberBase() : raw_(nullptr) { SaveCreationThreadState(); } - - MemberBase(std::nullptr_t) : raw_(nullptr) { SaveCreationThreadState(); } - - explicit MemberBase(T* raw) : raw_(raw) { - SaveCreationThreadState(); - CheckPointer(); - // No write barrier for initializing stores. - } - - explicit MemberBase(T& raw) : raw_(&raw) { - SaveCreationThreadState(); - CheckPointer(); - // No write barrier for initializing stores. - } - - MemberBase(WTF::HashTableDeletedValueType) - : raw_(reinterpret_cast<T*>(kHashTableDeletedRawValue)) { - SaveCreationThreadState(); - } - - MemberBase(const MemberBase& other) : raw_(other) { - SaveCreationThreadState(); - CheckPointer(); - // No write barrier for initializing stores. - } - - template <typename U> - MemberBase(const Persistent<U>& other) : raw_(other) { - SaveCreationThreadState(); - CheckPointer(); - // No write barrier for initializing stores. - } - - template <typename U> - MemberBase(const MemberBase<U>& other) : raw_(other) { - SaveCreationThreadState(); - CheckPointer(); - // No write barrier for initializing stores. - } - - template <typename U> - MemberBase& operator=(const Persistent<U>& other) { - SetRaw(other); - CheckPointer(); - WriteBarrier(); - return *this; - } - - MemberBase& operator=(const MemberBase& other) { - SetRaw(other); - CheckPointer(); - WriteBarrier(); - return *this; - } - - template <typename U> - MemberBase& operator=(const MemberBase<U>& other) { - SetRaw(other); - CheckPointer(); - WriteBarrier(); - return *this; - } - - template <typename U> - MemberBase& operator=(U* other) { - SetRaw(other); - CheckPointer(); - WriteBarrier(); - return *this; - } - - MemberBase& operator=(WTF::HashTableDeletedValueType) { - SetRaw(reinterpret_cast<T*>(-1)); - return *this; - } - - MemberBase& operator=(std::nullptr_t) { - SetRaw(nullptr); - return *this; - } - - void Swap(MemberBase<T>& other) { - T* tmp = GetRaw(); - SetRaw(other.GetRaw()); - other.SetRaw(tmp); - CheckPointer(); - WriteBarrier(); - other.WriteBarrier(); - } - - explicit operator bool() const { return GetRaw(); } - operator T*() const { return GetRaw(); } - T* operator->() const { return GetRaw(); } - T& operator*() const { return *GetRaw(); } - - T* Get() const { return GetRaw(); } - - void Clear() { SetRaw(nullptr); } - - T* Release() { - T* result = GetRaw(); - SetRaw(nullptr); - return result; - } - - static bool IsMemberHashTableDeletedValue(const T* t) { - return t == reinterpret_cast<T*>(kHashTableDeletedRawValue); - } - - bool IsHashTableDeletedValue() const { - return IsMemberHashTableDeletedValue(GetRaw()); - } - - protected: - static constexpr intptr_t kHashTableDeletedRawValue = -1; - - enum class AtomicCtorTag { Atomic }; - - // MemberBase ctors that use atomic write to set raw_. - - MemberBase(AtomicCtorTag, T* raw) { - SetRaw(raw); - SaveCreationThreadState(); - CheckPointer(); - // No write barrier for initializing stores. - } - - MemberBase(AtomicCtorTag, T& raw) { - SetRaw(&raw); - SaveCreationThreadState(); - CheckPointer(); - // No write barrier for initializing stores. - } - - void WriteBarrier() const { - MarkingVisitor::WriteBarrier( - reinterpret_cast<void**>(const_cast<std::remove_const_t<T>**>(&raw_))); - } - - void CheckPointer() { -#if DCHECK_IS_ON() - // Should not be called for deleted hash table values. A value can be - // propagated here if a MemberBase containing the deleted value is copied. - if (IsHashTableDeletedValue()) - return; - pointer_verifier_.CheckPointer(GetRaw()); -#endif // DCHECK_IS_ON() - } - - void SaveCreationThreadState() { -#if DCHECK_IS_ON() - pointer_verifier_.SaveCreationThreadState(GetRaw()); -#endif // DCHECK_IS_ON() - } - - ALWAYS_INLINE void SetRaw(T* raw) { - if (tracenessConfiguration == TracenessMemberConfiguration::kUntraced) - raw_ = raw; - else - WTF::AsAtomicPtr(&raw_)->store(raw, std::memory_order_relaxed); - } - ALWAYS_INLINE T* GetRaw() const { return raw_; } - - private: - // Thread safe version of Get() for marking visitors. - // This is used to prevent data races between concurrent marking visitors - // and writes on the main thread. - const T* GetSafe() const { - // TOOD(omerkatz): replace this cast with std::atomic_ref (C++20) once it - // becomes available - return WTF::AsAtomicPtr(&raw_)->load(std::memory_order_relaxed); - } - - T* raw_; -#if DCHECK_IS_ON() - MemberPointerVerifier<T, tracenessConfiguration> pointer_verifier_; -#endif // DCHECK_IS_ON() - - friend class Visitor; -}; - -// Members are used in classes to contain strong pointers to other oilpan heap -// allocated objects. -// All Member fields of a class must be traced in the class' trace method. -// During the mark phase of the GC all live objects are marked as live and -// all Member fields of a live object will be traced marked as live as well. -template <typename T> -class Member : public MemberBase<T, TracenessMemberConfiguration::kTraced> { - DISALLOW_NEW(); - typedef MemberBase<T, TracenessMemberConfiguration::kTraced> Parent; - - public: - Member() : Parent() {} - Member(std::nullptr_t) : Parent(nullptr) {} - Member(T* raw) : Parent(raw) {} - Member(T& raw) : Parent(raw) {} - Member(WTF::HashTableDeletedValueType x) : Parent(x) {} - - Member(const Member& other) : Parent(other) {} - - template <typename U> - Member(const Member<U>& other) : Parent(other) {} - - template <typename U> - Member(const Persistent<U>& other) : Parent(other) {} - - template <typename U> - Member& operator=(const Persistent<U>& other) { - Parent::operator=(other); - return *this; - } - - Member& operator=(const Member& other) { - Parent::operator=(other); - return *this; - } - - template <typename U> - Member& operator=(const Member<U>& other) { - Parent::operator=(other); - return *this; - } - - template <typename U> - Member& operator=(const WeakMember<U>& other) { - Parent::operator=(other); - return *this; - } - - template <typename U> - Member& operator=(U* other) { - Parent::operator=(other); - return *this; - } - - Member& operator=(WTF::HashTableDeletedValueType x) { - Parent::operator=(x); - return *this; - } - - Member& operator=(std::nullptr_t) { - Parent::operator=(nullptr); - return *this; - } - - private: - using typename Parent::AtomicCtorTag; - Member(AtomicCtorTag atomic, T* raw) : Parent(atomic, raw) {} - Member(AtomicCtorTag atomic, T& raw) : Parent(atomic, raw) {} - - template <typename P, typename Traits, typename Allocator> - friend class WTF::MemberConstructTraits; -}; - -// WeakMember is similar to Member in that it is used to point to other oilpan -// heap allocated objects. -// However instead of creating a strong pointer to the object, the WeakMember -// creates a weak pointer, which does not keep the pointee alive. Hence if all -// pointers to a heap allocated object are weak the object will be garbage -// collected. At the time of GC the weak pointers will automatically be set to -// null. -template <typename T> -class WeakMember : public MemberBase<T, TracenessMemberConfiguration::kTraced> { - typedef MemberBase<T, TracenessMemberConfiguration::kTraced> Parent; - - public: - WeakMember() : Parent() {} - - WeakMember(std::nullptr_t) : Parent(nullptr) {} - - WeakMember(T* raw) : Parent(raw) {} - - WeakMember(WTF::HashTableDeletedValueType x) : Parent(x) {} - - template <typename U> - WeakMember(const Persistent<U>& other) : Parent(other) {} - - template <typename U> - WeakMember(const Member<U>& other) : Parent(other) {} - - template <typename U> - WeakMember& operator=(const Persistent<U>& other) { - Parent::operator=(other); - return *this; - } - - template <typename U> - WeakMember& operator=(const Member<U>& other) { - Parent::operator=(other); - return *this; - } - - template <typename U> - WeakMember& operator=(U* other) { - Parent::operator=(other); - return *this; - } - - WeakMember& operator=(std::nullptr_t) { - this->SetRaw(nullptr); - return *this; - } - - private: - using typename Parent::AtomicCtorTag; - WeakMember(AtomicCtorTag atomic, T* raw) : Parent(atomic, raw) {} - WeakMember(AtomicCtorTag atomic, T& raw) : Parent(atomic, raw) {} - - template <typename P, typename Traits, typename Allocator> - friend class WTF::MemberConstructTraits; -}; - -// UntracedMember is a pointer to an on-heap object that is not traced for some -// reason. Please don't use this unless you understand what you're doing. -// Basically, all pointers to on-heap objects must be stored in either of -// Persistent, Member or WeakMember. It is not allowed to leave raw pointers to -// on-heap objects. However, there can be scenarios where you have to use raw -// pointers for some reason, and in that case you can use UntracedMember. Of -// course, it must be guaranteed that the pointing on-heap object is kept alive -// while the raw pointer is pointing to the object. -template <typename T> -class UntracedMember final - : public MemberBase<T, TracenessMemberConfiguration::kUntraced> { - typedef MemberBase<T, TracenessMemberConfiguration::kUntraced> Parent; - - public: - UntracedMember() : Parent() {} - - UntracedMember(std::nullptr_t) : Parent(nullptr) {} - - UntracedMember(T* raw) : Parent(raw) {} - - UntracedMember(const UntracedMember& other) : Parent(other) {} - - template <typename U> - UntracedMember(const Persistent<U>& other) : Parent(other) {} - - template <typename U> - UntracedMember(const Member<U>& other) : Parent(other) {} - - UntracedMember(WTF::HashTableDeletedValueType x) : Parent(x) {} - - UntracedMember& operator=(const UntracedMember& other) { - this->SetRaw(other); - this->CheckPointer(); - return *this; - } - - template <typename U> - UntracedMember& operator=(const Persistent<U>& other) { - this->SetRaw(other); - this->CheckPointer(); - return *this; - } - - template <typename U> - UntracedMember& operator=(const Member<U>& other) { - this->SetRaw(other); - this->CheckPointer(); - return *this; - } - - template <typename U> - UntracedMember& operator=(U* other) { - this->SetRaw(other); - this->CheckPointer(); - return *this; - } - - UntracedMember& operator=(std::nullptr_t) { - this->SetRaw(nullptr); - return *this; - } -}; - -template <typename T> -struct MemberTraceTraits { - STATIC_ONLY(MemberTraceTraits); - - public: - static TraceDescriptor GetTraceDescriptor(const T* ref) { - return {ref, TraceTrait<T>::Trace}; - } - - static void Trace(Visitor* visitor, const void* ref) { - visitor->Trace(*static_cast<const T*>(ref)); - } -}; - -template <typename T> -struct TraceTrait<Member<T>> : public MemberTraceTraits<Member<T>> {}; - -template <typename T> -struct TraceTrait<WeakMember<T>> : public MemberTraceTraits<WeakMember<T>> {}; - -template <typename T> -inline bool IsHashTableDeletedValue(const Member<T>& m) { - return m.IsHashTableDeletedValue(); -} - -constexpr auto kMemberDeletedValue = WTF::kHashTableDeletedValue; - -} // namespace blink - -namespace WTF { - -template <typename T, typename Traits, typename Allocator> -class MemberConstructTraits { - STATIC_ONLY(MemberConstructTraits); - - public: - template <typename... Args> - static T* Construct(void* location, Args&&... args) { - return new (NotNullTag::kNotNull, location) T(std::forward<Args>(args)...); - } - - static void NotifyNewElement(T* element) { element->WriteBarrier(); } - - template <typename... Args> - static T* ConstructAndNotifyElement(void* location, Args&&... args) { - // ConstructAndNotifyElement updates an existing Member which might - // also be comncurrently traced while we update it. The regular ctors - // for Member don't use an atomic write which can lead to data races. - T* object = Construct(location, T::AtomicCtorTag::Atomic, - std::forward<Args>(args)...); - NotifyNewElement(object); - return object; - } - - static void NotifyNewElements(T* array, size_t len) { - while (len-- > 0) { - array->WriteBarrier(); - array++; - } - } -}; - -template <typename T, typename Traits, typename Allocator> -class ConstructTraits<blink::Member<T>, Traits, Allocator> - : public MemberConstructTraits<blink::Member<T>, Traits, Allocator> {}; - -template <typename T, typename Traits, typename Allocator> -class ConstructTraits<blink::WeakMember<T>, Traits, Allocator> - : public MemberConstructTraits<blink::WeakMember<T>, Traits, Allocator> {}; - -} // namespace WTF - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_MEMBER_H_
diff --git a/third_party/blink/renderer/platform/heap/impl/name_traits.h b/third_party/blink/renderer/platform/heap/impl/name_traits.h deleted file mode 100644 index c44305f..0000000 --- a/third_party/blink/renderer/platform/heap/impl/name_traits.h +++ /dev/null
@@ -1,62 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_NAME_TRAITS_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_NAME_TRAITS_H_ - -#include <cstring> - -#include "build/build_config.h" -#include "third_party/blink/renderer/platform/bindings/name_client.h" -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" -#include "third_party/blink/renderer/platform/wtf/type_traits.h" - -namespace blink { - -struct HeapObjectName { - const char* value; - bool name_is_hidden; -}; - -using NameCallback = HeapObjectName (*)(const void*); - -template <typename T> -class NameTrait { - STATIC_ONLY(NameTrait); - - public: - static HeapObjectName GetName(const void* obj) { - return GetNameFor(static_cast<const T*>(obj)); - } - - private: - static HeapObjectName GetNameFor(const NameClient* wrapper_tracable) { - return {wrapper_tracable->NameInHeapSnapshot(), false}; - } - - static HeapObjectName GetNameFor(...) { - if (NameClient::HideInternalName()) - return {"InternalNode", true}; - - DCHECK(!NameClient::HideInternalName()); - static const char* leaky_class_name = nullptr; - if (leaky_class_name) - return {leaky_class_name, false}; - - // Parsing string of structure: - // const char *WTF::GetStringWithTypeName<TYPE>() [T = TYPE] - // Note that this only works on clang or GCC builds. - const std::string raw(WTF::GetStringWithTypeName<T>()); - const auto start_pos = raw.rfind("T = ") + 4; - DCHECK(std::string::npos != start_pos); - const auto len = raw.length() - start_pos - 1; - const std::string name = raw.substr(start_pos, len).c_str(); - leaky_class_name = strcpy(new char[name.length() + 1], name.c_str()); - return {leaky_class_name, false}; - } -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_NAME_TRAITS_H_
diff --git a/third_party/blink/renderer/platform/heap/impl/page_bloom_filter.h b/third_party/blink/renderer/platform/heap/impl/page_bloom_filter.h deleted file mode 100644 index 19263ae..0000000 --- a/third_party/blink/renderer/platform/heap/impl/page_bloom_filter.h +++ /dev/null
@@ -1,48 +0,0 @@ -// Copyright 2019 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. - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_PAGE_BLOOM_FILTER_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_PAGE_BLOOM_FILTER_H_ - -#include "third_party/blink/renderer/platform/heap/impl/heap_page.h" -#include "third_party/blink/renderer/platform/wtf/bloom_filter.h" - -namespace blink { - -// Bloom filter for Oilpan pages. Use counting to support correct deletion. This -// is needed for stack scanning to quickly check if an arbitrary address doesn't -// point inside Oilpan pages. May return false positives but never false -// negatives. -class PageBloomFilter { - public: - void Add(Address address) { - filter_.Add(Hash(RoundToBlinkPageStart(address))); - } - - void Remove(Address address) { - filter_.Remove(Hash(RoundToBlinkPageStart(address))); - } - - bool MayContain(Address address) const { - return filter_.MayContain(Hash(RoundToBlinkPageStart(address))); - } - - private: - static constexpr size_t kNumberOfEntriesLog2 = 12; - static constexpr size_t kNumberOfEntries = 1 << kNumberOfEntriesLog2; - - static unsigned Hash(Address address) { - size_t value = reinterpret_cast<size_t>(address) >> kBlinkPageSizeLog2; - value ^= value >> kNumberOfEntriesLog2; - value ^= value >> (kNumberOfEntriesLog2 * 2); - value &= kNumberOfEntries - 1; - return static_cast<unsigned>(value); - } - - WTF::BloomFilter<kNumberOfEntriesLog2> filter_; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_PAGE_BLOOM_FILTER_H_
diff --git a/third_party/blink/renderer/platform/heap/impl/page_memory.cc b/third_party/blink/renderer/platform/heap/impl/page_memory.cc deleted file mode 100644 index c463e17..0000000 --- a/third_party/blink/renderer/platform/heap/impl/page_memory.cc +++ /dev/null
@@ -1,135 +0,0 @@ -// Copyright 2016 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/heap/impl/page_memory.h" - -#include "base/allocator/partition_allocator/oom.h" -#include "base/allocator/partition_allocator/page_allocator.h" -#include "third_party/blink/renderer/platform/heap/heap.h" -#include "third_party/blink/renderer/platform/wtf/sanitizers.h" - -namespace blink { - -void MemoryRegion::Release() { - base::FreePages(base_, size_); -} - -void MemoryRegion::Commit() { - base::RecommitSystemPages(base_, size_, base::PageReadWrite, - base::PageUpdatePermissions); -} - -void MemoryRegion::Decommit() { - ASAN_UNPOISON_MEMORY_REGION(base_, size_); - base::DecommitSystemPages(base_, size_, base::PageUpdatePermissions); -} - -PageMemoryRegion::PageMemoryRegion(Address base, - size_t size, - unsigned num_pages, - RegionTree* region_tree) - : MemoryRegion(base, size), - is_large_page_(num_pages == 1), - num_pages_(num_pages), - region_tree_(region_tree) { - DCHECK(region_tree); - region_tree_->Add(this); - for (size_t i = 0; i < kBlinkPagesPerRegion; ++i) - in_use_[i] = false; -} - -PageMemoryRegion::~PageMemoryRegion() { - region_tree_->Remove(this); - Release(); -} - -void PageMemoryRegion::PageDeleted(Address page) { - MarkPageUnused(page); - if (!num_pages_.Decrement()) - delete this; -} - -// TODO(haraken): Like partitionOutOfMemoryWithLotsOfUncommitedPages(), -// we should probably have a way to distinguish physical memory OOM from -// virtual address space OOM. -static NOINLINE void BlinkGCOutOfMemory() { - // TODO(lizeb): Add the real allocation size here as well. - OOM_CRASH(0); -} - -PageMemoryRegion* PageMemoryRegion::Allocate(size_t size, - unsigned num_pages, - RegionTree* region_tree) { - // Round size up to the allocation granularity. - size = base::RoundUpToPageAllocationGranularity(size); - Address base = static_cast<Address>( - base::AllocPages(nullptr, size, kBlinkPageSize, base::PageInaccessible, - base::PageTag::kBlinkGC)); - if (!base) - BlinkGCOutOfMemory(); - return new PageMemoryRegion(base, size, num_pages, region_tree); -} - -PageMemoryRegion* RegionTree::Lookup(ConstAddress address) { - auto it = set_.upper_bound(address); - // This check also covers set_.size() > 0, since for empty vectors it is - // guaranteed that begin() == end(). - if (it == set_.begin()) - return nullptr; - auto* result = std::next(it, -1)->second; - if (address < result->Base() + result->size()) - return result; - return nullptr; -} - -void RegionTree::Add(PageMemoryRegion* region) { - DCHECK(region); - auto result = set_.emplace(region->Base(), region); - DCHECK(result.second); -} - -void RegionTree::Remove(PageMemoryRegion* region) { - DCHECK(region); - auto size = set_.erase(region->Base()); - DCHECK_EQ(1u, size); -} - -PageMemory::PageMemory(PageMemoryRegion* reserved, const MemoryRegion& writable) - : reserved_(reserved), writable_(writable) { - DCHECK(reserved->Contains(writable)); - - // Register the writable area of the memory as part of the LSan root set. - // Only the writable area is mapped and can contain C++ objects. Those - // C++ objects can contain pointers to objects outside of the heap and - // should therefore be part of the LSan root set. - __lsan_register_root_region(writable_.Base(), writable_.size()); -} - -PageMemory* PageMemory::SetupPageMemoryInRegion(PageMemoryRegion* region, - size_t page_offset, - size_t payload_size) { - // Setup the payload one guard page into the page memory. - Address payload_address = region->Base() + page_offset + BlinkGuardPageSize(); - return new PageMemory(region, MemoryRegion(payload_address, payload_size)); -} - -PageMemory* PageMemory::Allocate(size_t payload_size, RegionTree* region_tree) { - DCHECK_GT(payload_size, 0u); - - // Virtual memory allocation routines operate in OS page sizes. - // Round up the requested size to nearest os page size. - payload_size = base::RoundUpToSystemPage(payload_size); - - // Overallocate by 2 times OS page size to have space for a - // guard page at the beginning and end of blink heap page. - size_t allocation_size = payload_size + 2 * BlinkGuardPageSize(); - PageMemoryRegion* page_memory_region = - PageMemoryRegion::AllocateLargePage(allocation_size, region_tree); - PageMemory* storage = - SetupPageMemoryInRegion(page_memory_region, 0, payload_size); - storage->Commit(); - return storage; -} - -} // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/impl/page_memory.h b/third_party/blink/renderer/platform/heap/impl/page_memory.h deleted file mode 100644 index 2d25530..0000000 --- a/third_party/blink/renderer/platform/heap/impl/page_memory.h +++ /dev/null
@@ -1,185 +0,0 @@ -// Copyright 2015 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. - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_PAGE_MEMORY_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_PAGE_MEMORY_H_ - -#include "base/atomic_ref_count.h" -#include "base/containers/flat_map.h" -#include "third_party/blink/renderer/platform/heap/heap.h" -#include "third_party/blink/renderer/platform/heap/impl/heap_page.h" -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" - -namespace blink { - -class RegionTree; - -class MemoryRegion { - USING_FAST_MALLOC(MemoryRegion); - - public: - MemoryRegion(Address base, size_t size) : base_(base), size_(size) { - DCHECK_GT(size, 0u); - } - - bool Contains(ConstAddress addr) const { - return base_ <= addr && addr < (base_ + size_); - } - - bool Contains(const MemoryRegion& other) const { - return Contains(other.base_) && Contains(other.base_ + other.size_ - 1); - } - - void Release(); - void Commit(); - void Decommit(); - - Address Base() const { return base_; } - size_t size() const { return size_; } - - private: - Address base_; - size_t size_; -}; - -// A PageMemoryRegion represents a chunk of reserved virtual address -// space containing a number of blink heap pages. On Windows, reserved -// virtual address space can only be given back to the system as a -// whole. The PageMemoryRegion allows us to do that by keeping track -// of the number of pages using it in order to be able to release all -// of the virtual address space when there are no more pages using it. -class PageMemoryRegion : public MemoryRegion { - public: - ~PageMemoryRegion(); - - void PageDeleted(Address); - - void MarkPageUsed(Address page) { - DCHECK(!in_use_[Index(page)]); - in_use_[Index(page)] = true; - } - - void MarkPageUnused(Address page) { in_use_[Index(page)] = false; } - - static PageMemoryRegion* AllocateLargePage(size_t size, - RegionTree* region_tree) { - return Allocate(size, 1, region_tree); - } - - static PageMemoryRegion* AllocateNormalPages(RegionTree* region_tree) { - return Allocate(kBlinkPageSize * kBlinkPagesPerRegion, kBlinkPagesPerRegion, - region_tree); - } - - BasePage* PageFromAddress(ConstAddress address) { - DCHECK(Contains(address)); - if (!in_use_[Index(address)]) - return nullptr; - if (is_large_page_) - return PageFromObject(Base()); - return PageFromObject(address); - } - - private: - PageMemoryRegion(Address base, size_t, unsigned num_pages, RegionTree*); - - unsigned Index(ConstAddress address) const { - DCHECK(Contains(address)); - if (is_large_page_) - return 0; - size_t offset = BlinkPageAddress(const_cast<Address>(address)) - Base(); - DCHECK_EQ(offset % kBlinkPageSize, 0u); - return static_cast<unsigned>(offset / kBlinkPageSize); - } - - static PageMemoryRegion* Allocate(size_t, unsigned num_pages, RegionTree*); - - const bool is_large_page_; - // A thread owns a page, but not a region. Represent the in-use - // bitmap such that thread non-interference comes for free. - bool in_use_[kBlinkPagesPerRegion]; - base::AtomicRefCount num_pages_; - RegionTree* const region_tree_; -}; - -// A RegionTree is a simple binary search tree of PageMemoryRegions sorted -// by base addresses. -class RegionTree { - USING_FAST_MALLOC(RegionTree); - - public: - void Add(PageMemoryRegion*); - void Remove(PageMemoryRegion*); - PageMemoryRegion* Lookup(ConstAddress); - - private: - // Using flat_map allows to improve locality to minimize cache misses and - // balance binary lookup. - base::flat_map<ConstAddress, PageMemoryRegion*> set_; -}; - -// Representation of the memory used for a Blink heap page. -// -// The representation keeps track of two memory regions: -// -// 1. The virtual memory reserved from the system in order to be able -// to free all the virtual memory reserved. Multiple PageMemory -// instances can share the same reserved memory region and -// therefore notify the reserved memory region on destruction so -// that the system memory can be given back when all PageMemory -// instances for that memory are gone. -// -// 2. The writable memory (a sub-region of the reserved virtual -// memory region) that is used for the actual heap page payload. -// -// Guard pages are created before and after the writable memory. -class PageMemory { - USING_FAST_MALLOC(PageMemory); - - public: - ~PageMemory() { - __lsan_unregister_root_region(writable_.Base(), writable_.size()); - reserved_->PageDeleted(WritableStart()); - } - - void Commit() { - reserved_->MarkPageUsed(WritableStart()); - writable_.Commit(); - } - - void Decommit() { - reserved_->MarkPageUnused(WritableStart()); - writable_.Decommit(); - } - - void MarkUnused() { reserved_->MarkPageUnused(WritableStart()); } - - PageMemoryRegion* Region() { return reserved_; } - - Address WritableStart() { return writable_.Base(); } - - static PageMemory* SetupPageMemoryInRegion(PageMemoryRegion*, - size_t page_offset, - size_t payload_size); - - // Allocate a virtual address space for one blink page with the - // following layout: - // - // [ guard os page | ... payload ... | guard os page ] - // ^---{ aligned to blink page size } - // - // The returned page memory region will be zeroed. - // - static PageMemory* Allocate(size_t payload_size, RegionTree*); - - private: - PageMemory(PageMemoryRegion* reserved, const MemoryRegion& writable); - - PageMemoryRegion* reserved_; - MemoryRegion writable_; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_PAGE_MEMORY_H_
diff --git a/third_party/blink/renderer/platform/heap/impl/page_pool.cc b/third_party/blink/renderer/platform/heap/impl/page_pool.cc deleted file mode 100644 index 94360c2..0000000 --- a/third_party/blink/renderer/platform/heap/impl/page_pool.cc +++ /dev/null
@@ -1,51 +0,0 @@ -// Copyright 2015 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/heap/impl/page_pool.h" - -#include "third_party/blink/renderer/platform/heap/heap.h" -#include "third_party/blink/renderer/platform/heap/impl/page_memory.h" - -namespace blink { - -PagePool::PagePool() { - for (int i = 0; i < BlinkGC::kNumberOfArenas; ++i) { - pool_[i] = nullptr; - } -} - -PagePool::~PagePool() { - for (int index = 0; index < BlinkGC::kNumberOfArenas; ++index) { - while (PoolEntry* entry = pool_[index]) { - pool_[index] = entry->next; - PageMemory* memory = entry->data; - DCHECK(memory); - delete memory; - delete entry; - } - } -} - -void PagePool::Add(int index, PageMemory* memory) { - // When adding a page to the pool we decommit it to ensure it is unused - // while in the pool. This also allows the physical memory, backing the - // page, to be given back to the OS. - memory->Decommit(); - PoolEntry* entry = new PoolEntry(memory, pool_[index]); - pool_[index] = entry; -} - -PageMemory* PagePool::Take(int index) { - if (PoolEntry* entry = pool_[index]) { - pool_[index] = entry->next; - PageMemory* memory = entry->data; - DCHECK(memory); - delete entry; - memory->Commit(); - return memory; - } - return nullptr; -} - -} // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/impl/page_pool.h b/third_party/blink/renderer/platform/heap/impl/page_pool.h deleted file mode 100644 index fdf448f..0000000 --- a/third_party/blink/renderer/platform/heap/impl/page_pool.h +++ /dev/null
@@ -1,48 +0,0 @@ -// Copyright 2015 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. - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_PAGE_POOL_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_PAGE_POOL_H_ - -#include "third_party/blink/renderer/platform/heap/thread_state.h" -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" - -namespace blink { - -class PageMemory; - -// Once pages have been used for one type of thread heap they will never be -// reused for another type of thread heap. Instead of unmapping, we add the -// pages to a pool of pages to be reused later by a thread heap of the same -// type. This is done as a security feature to avoid type confusion. The -// heaps are type segregated by having separate thread arenas for different -// types of objects. Holding on to pages ensures that the same virtual address -// space cannot be used for objects of another type than the type contained -// in this page to begin with. -class PagePool { - USING_FAST_MALLOC(PagePool); - - public: - PagePool(); - ~PagePool(); - void Add(int, PageMemory*); - PageMemory* Take(int); - - private: - class PoolEntry { - USING_FAST_MALLOC(PoolEntry); - - public: - PoolEntry(PageMemory* data, PoolEntry* next) : data(data), next(next) {} - - PageMemory* data; - PoolEntry* next; - }; - - PoolEntry* pool_[BlinkGC::kNumberOfArenas]; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_PAGE_POOL_H_
diff --git a/third_party/blink/renderer/platform/heap/impl/persistent.h b/third_party/blink/renderer/platform/heap/impl/persistent.h deleted file mode 100644 index 4a7328b..0000000 --- a/third_party/blink/renderer/platform/heap/impl/persistent.h +++ /dev/null
@@ -1,865 +0,0 @@ -// Copyright 2016 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. - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_PERSISTENT_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_PERSISTENT_H_ - -#include "base/bind.h" -#include "base/dcheck_is_on.h" -#include "base/location.h" -#include "third_party/blink/renderer/platform/bindings/buildflags.h" -#include "third_party/blink/renderer/platform/heap/heap.h" -#include "third_party/blink/renderer/platform/heap/heap_allocator.h" -#include "third_party/blink/renderer/platform/heap/impl/heap_compact.h" -#include "third_party/blink/renderer/platform/heap/impl/persistent_node.h" -#include "third_party/blink/renderer/platform/heap/member.h" -#include "third_party/blink/renderer/platform/heap/visitor.h" -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" -#include "third_party/blink/renderer/platform/wtf/cross_thread_copier.h" - -namespace blink { - -template <typename T> -class CrossThreadWeakPersistent; - -// Wrapping type to force callers to go through macros that expand or drop -// base::Location. This is needed to avoid adding the strings when not needed. -// The type can be dropped once http://crbug.com/760702 is resolved and -// ENABLE_LOCATION_SOURCE is disabled for release builds. -class PersistentLocation final { - public: - PersistentLocation() = default; - explicit PersistentLocation(const base::Location& location) - : location_(location) {} - PersistentLocation(const PersistentLocation& other) = default; - - const base::Location& get() const { return location_; } - - private: - base::Location location_; -}; - -#if BUILDFLAG(RAW_HEAP_SNAPSHOTS) -#define PERSISTENT_FROM_HERE PersistentLocation(base::Location::Current()) -#else // !RAW_HEAP_SNAPSHOTS -#define PERSISTENT_FROM_HERE PersistentLocation() -#endif // !RAW_HEAP_SNAPSHOTS - -template <typename T, - WeaknessPersistentConfiguration weaknessConfiguration, - CrossThreadnessPersistentConfiguration crossThreadnessConfiguration> -class PersistentBase { - USING_FAST_MALLOC(PersistentBase); - - public: - bool IsHashTableDeletedValue() const { - return raw_ == reinterpret_cast<T*>(-1); - } - - T* Release() { - T* result = raw_; - AssignSafe(nullptr); - return result; - } - - void Clear() { - // Note that this also frees up related data in the backend. - AssignSafe(nullptr); - } - - T* Get() const { - CheckPointer(); - return raw_; - } - - explicit operator bool() const { return Get(); } - T& operator*() const { return *Get(); } - operator T*() const { return Get(); } - T* operator->() const { return Get(); } - - NO_SANITIZE_ADDRESS - void ClearWithLockHeld() { - static_assert( - crossThreadnessConfiguration == kCrossThreadPersistentConfiguration, - "This Persistent does not require the cross-thread lock."); - PersistentMutexTraits<crossThreadnessConfiguration>::AssertAcquired(); - raw_ = nullptr; - persistent_node_.ClearWithLockHeld(); - } - - void UpdateLocation(const PersistentLocation& other) { -#if BUILDFLAG(RAW_HEAP_SNAPSHOTS) - location_ = other; -#endif // BUILDFLAG(RAW_HEAP_SNAPSHOTS) - } - - protected: - ~PersistentBase() { - UninitializeSafe(); - // Not resetting raw_ as it is not observable. - } - - PersistentBase() : raw_(nullptr) { - SaveCreationThreadHeap(); - // No initialization needed for empty handle. - } - PersistentBase(const PersistentLocation& location) : PersistentBase() { - UpdateLocation(location); - } - - PersistentBase(std::nullptr_t) : raw_(nullptr) { - SaveCreationThreadHeap(); - // No initialization needed for empty handle. - } - PersistentBase(const PersistentLocation& location, std::nullptr_t) - : PersistentBase(nullptr) { - UpdateLocation(location); - } - - PersistentBase(T* raw) : raw_(raw) { - SaveCreationThreadHeap(); - InitializeSafe(); - CheckPointer(); - } - PersistentBase(const PersistentLocation& location, T* raw) - : PersistentBase(raw) { - UpdateLocation(location); - } - - PersistentBase(T& raw) : raw_(&raw) { - SaveCreationThreadHeap(); - InitializeSafe(); - CheckPointer(); - } - PersistentBase(const PersistentLocation& location, T& raw) - : PersistentBase(raw) { - UpdateLocation(location); - } - - PersistentBase(const PersistentBase& other) : raw_(other) { - SaveCreationThreadHeap(); - InitializeSafe(); - CheckPointer(); - } - PersistentBase(const PersistentLocation& location, PersistentBase& other) - : PersistentBase(other) { - UpdateLocation(location); - } - - template <typename U> - PersistentBase(const PersistentBase<U, - weaknessConfiguration, - crossThreadnessConfiguration>& other) - : raw_(other) { - SaveCreationThreadHeap(); - InitializeSafe(); - CheckPointer(); - } - template <typename U> - PersistentBase(const PersistentLocation& location, - const PersistentBase<U, - weaknessConfiguration, - crossThreadnessConfiguration>& other) - : PersistentBase(other) { - UpdateLocation(location); - } - - template <typename U> - PersistentBase(const Member<U>& other) : raw_(other) { - SaveCreationThreadHeap(); - InitializeSafe(); - CheckPointer(); - } - template <typename U> - PersistentBase(const PersistentLocation& location, const Member<U>& other) - : PersistentBase(other) { - UpdateLocation(location); - } - - PersistentBase(WTF::HashTableDeletedValueType) - : raw_(reinterpret_cast<T*>(-1)) { - SaveCreationThreadHeap(); - // No initialization needed for empty handle. - } - PersistentBase(const PersistentLocation& location, - WTF::HashTableDeletedValueType) - : PersistentBase(WTF::kHashTableDeletedValue) { - UpdateLocation(location); - } - - template <typename U> - PersistentBase& operator=(U* other) { - AssignSafe(other); - return *this; - } - - PersistentBase& operator=(std::nullptr_t) { - AssignSafe(nullptr); - return *this; - } - - template <typename U> - PersistentBase& operator=(const Member<U>& other) { - AssignSafe(other); - return *this; - } - - // Using unsafe operations and assuming that caller acquires the lock for - // kCrossThreadPersistentConfiguration configuration. - PersistentBase& operator=(const PersistentBase& other) { - PersistentMutexTraits<crossThreadnessConfiguration>::AssertAcquired(); - AssignUnsafe(other); - return *this; - } - - // Using unsafe operations and assuming that caller acquires the lock for - // kCrossThreadPersistentConfiguration configuration. - template <typename U> - PersistentBase& operator=( - const PersistentBase<U, - weaknessConfiguration, - crossThreadnessConfiguration>& other) { - PersistentMutexTraits<crossThreadnessConfiguration>::AssertAcquired(); - AssignUnsafe(static_cast<T*>(other.Get())); - return *this; - } - - // Using unsafe operations and assuming that caller acquires the lock for - // kCrossThreadPersistentConfiguration configuration. - template <typename U> - PersistentBase& operator=( - PersistentBase<U, weaknessConfiguration, crossThreadnessConfiguration>&& - other) { - PersistentMutexTraits<crossThreadnessConfiguration>::AssertAcquired(); - if (persistent_node_.IsInitialized()) { - // Drop persistent node if present as it's always possible to reuse the - // node (if present) from |other|. - persistent_node_.Uninitialize(); - } - // Explicit cast enabling downcasting. - raw_ = static_cast<T*>(other.raw_); - other.raw_ = nullptr; - // Efficiently move by just rewiring the node pointer. - persistent_node_ = std::move(other.persistent_node_); - DCHECK(!other.persistent_node_.Get()); - if (persistent_node_.IsInitialized()) { - // If |raw_| points to a non-null or deleted value, just reuse the node. - TraceCallback trace_callback = - TraceMethodDelegate<PersistentBase, - &PersistentBase::TracePersistent>::Trampoline; - persistent_node_.Get()->Reinitialize(this, trace_callback); - } - CheckPointer(); - return *this; - } - - NO_SANITIZE_ADDRESS - bool IsNotNull() const { return raw_; } - - NO_SANITIZE_ADDRESS - void AssignSafe(T* ptr) { - typename PersistentMutexTraits<crossThreadnessConfiguration>::Locker lock; - AssignUnsafe(ptr); - } - - NO_SANITIZE_ADDRESS - void AssignUnsafe(T* ptr) { - raw_ = ptr; - CheckPointer(); - if (raw_ && !IsHashTableDeletedValue()) { - if (!persistent_node_.IsInitialized()) - InitializeUnsafe(); - return; - } - UninitializeUnsafe(); - } - - void TracePersistent(Visitor* visitor) const { - static_assert(sizeof(T), "T must be fully defined"); - static_assert(IsGarbageCollectedType<T>::value, - "T needs to be a garbage collected object"); - DCHECK(!IsHashTableDeletedValue()); - if (weaknessConfiguration == kWeakPersistentConfiguration) { - visitor->RegisterWeakCallback(HandleWeakPersistent, this); - } else { -#if BUILDFLAG(RAW_HEAP_SNAPSHOTS) - visitor->TraceRoot(raw_, location_.get()); -#else - visitor->TraceRoot(raw_, base::Location()); -#endif // BUILDFLAG(RAW_HEAP_SNAPSHOTS) - } - } - - NO_SANITIZE_ADDRESS - void InitializeSafe() { - DCHECK(!persistent_node_.IsInitialized()); - if (!raw_ || IsHashTableDeletedValue()) - return; - - TraceCallback trace_callback = - TraceMethodDelegate<PersistentBase, - &PersistentBase::TracePersistent>::Trampoline; - typename PersistentMutexTraits<crossThreadnessConfiguration>::Locker lock; - persistent_node_.Initialize(this, trace_callback); - } - - NO_SANITIZE_ADDRESS - void InitializeUnsafe() { - DCHECK(!persistent_node_.IsInitialized()); - if (!raw_ || IsHashTableDeletedValue()) - return; - - TraceCallback trace_callback = - TraceMethodDelegate<PersistentBase, - &PersistentBase::TracePersistent>::Trampoline; - persistent_node_.Initialize(this, trace_callback); - } - - void UninitializeSafe() { - if (persistent_node_.IsInitialized()) { - typename PersistentMutexTraits<crossThreadnessConfiguration>::Locker lock; - persistent_node_.Uninitialize(); - } - } - - void UninitializeUnsafe() { - if (persistent_node_.IsInitialized()) - persistent_node_.Uninitialize(); - } - - void CheckPointer() const { -#if DCHECK_IS_ON() - if (!raw_ || IsHashTableDeletedValue()) - return; - - if (crossThreadnessConfiguration != kCrossThreadPersistentConfiguration) { - ThreadState* current = ThreadState::Current(); - DCHECK(current); - // m_creationThreadState may be null when this is used in a heap - // collection which initialized the Persistent with memset and the - // constructor wasn't called. - if (creation_thread_state_) { - // Member should point to objects that belong in the same ThreadHeap. - DCHECK_EQ(&ThreadState::FromObject(raw_)->Heap(), - &creation_thread_state_->Heap()); - // Member should point to objects that belong in the same ThreadHeap. - DCHECK_EQ(¤t->Heap(), &creation_thread_state_->Heap()); - } - } -#endif - } - - void SaveCreationThreadHeap() { -#if DCHECK_IS_ON() - if (crossThreadnessConfiguration == kCrossThreadPersistentConfiguration) { - creation_thread_state_ = nullptr; - } else { - creation_thread_state_ = ThreadState::Current(); - DCHECK(creation_thread_state_); - } -#endif - } - - static void HandleWeakPersistent(const LivenessBroker& broker, - const void* persistent_pointer) { - using Base = - PersistentBase<typename std::remove_const<T>::type, - weaknessConfiguration, crossThreadnessConfiguration>; - Base* persistent = - reinterpret_cast<Base*>(const_cast<void*>(persistent_pointer)); - T* object = persistent->Get(); - if (object && !broker.IsHeapObjectAlive(object)) - ClearWeakPersistent(persistent); - } - - static void ClearWeakPersistent( - PersistentBase<std::remove_const_t<T>, - kWeakPersistentConfiguration, - kCrossThreadPersistentConfiguration>* persistent) { - PersistentMutexTraits<crossThreadnessConfiguration>::AssertAcquired(); - persistent->ClearWithLockHeld(); - } - - static void ClearWeakPersistent( - PersistentBase<std::remove_const_t<T>, - kWeakPersistentConfiguration, - kSingleThreadPersistentConfiguration>* persistent) { - persistent->Clear(); - } - - template <typename BadPersistent> - static void ClearWeakPersistent(BadPersistent* non_weak_persistent) { - NOTREACHED(); - } - - // raw_ is accessed most, so put it at the first field. - T* raw_; - - // The pointer to the underlying persistent node. - // - // Since accesses are atomics in the cross-thread case, a different type is - // needed to prevent the compiler producing an error when it encounters - // operations that are legal on raw pointers but not on atomics, or - // vice-versa. - std::conditional_t< - crossThreadnessConfiguration == kCrossThreadPersistentConfiguration, - CrossThreadPersistentNodePtr<weaknessConfiguration>, - PersistentNodePtr<ThreadingTrait<T>::kAffinity, weaknessConfiguration>> - persistent_node_; - -#if BUILDFLAG(RAW_HEAP_SNAPSHOTS) - PersistentLocation location_; -#endif // BUILDFLAG(RAW_HEAP_SNAPSHOTS) - -#if DCHECK_IS_ON() - const ThreadState* creation_thread_state_; -#endif - - template <typename F, - WeaknessPersistentConfiguration, - CrossThreadnessPersistentConfiguration> - friend class PersistentBase; -}; - -// Persistent is a way to create a strong pointer from an off-heap object -// to another on-heap object. As long as the Persistent handle is alive -// the GC will keep the object pointed to alive. The Persistent handle is -// always a GC root from the point of view of the GC. -// -// We have to construct and destruct Persistent in the same thread. -template <typename T> -class Persistent : public PersistentBase<T, - kNonWeakPersistentConfiguration, - kSingleThreadPersistentConfiguration> { - using Parent = PersistentBase<T, - kNonWeakPersistentConfiguration, - kSingleThreadPersistentConfiguration>; - - public: - Persistent() : Parent() {} - Persistent(const PersistentLocation& location) : Parent(location) {} - Persistent(std::nullptr_t) : Parent(nullptr) {} - Persistent(const PersistentLocation& location, std::nullptr_t) - : Parent(location, nullptr) {} - Persistent(T* raw) : Parent(raw) {} - Persistent(const PersistentLocation& location, T* raw) - : Parent(location, raw) {} - Persistent(T& raw) : Parent(raw) {} - Persistent(const PersistentLocation& location, T& raw) - : Parent(location, raw) {} - Persistent(const Persistent& other) : Parent(other) {} - Persistent(const PersistentLocation& location, const Persistent& other) - : Parent(location, other) {} - template <typename U> - Persistent(const Persistent<U>& other) : Parent(other) {} - template <typename U> - Persistent(const PersistentLocation& location, const Persistent<U>& other) - : Parent(location, other) {} - template <typename U> - Persistent(const Member<U>& other) : Parent(other) {} - template <typename U> - Persistent(const PersistentLocation& location, const Member<U>& other) - : Parent(location, other) {} - Persistent(WTF::HashTableDeletedValueType x) : Parent(x) {} - Persistent(const PersistentLocation& location, - WTF::HashTableDeletedValueType x) - : Parent(location, x) {} - - template <typename U> - Persistent& operator=(U* other) { - Parent::operator=(other); - return *this; - } - - Persistent& operator=(std::nullptr_t) { - Parent::operator=(nullptr); - return *this; - } - - Persistent& operator=(const Persistent& other) { - Parent::operator=(other); - return *this; - } - - template <typename U> - Persistent& operator=(const Persistent<U>& other) { - Parent::operator=(other); - return *this; - } - - template <typename U> - Persistent& operator=(const Member<U>& other) { - Parent::operator=(other); - return *this; - } -}; - -// WeakPersistent is a way to create a weak pointer from an off-heap object -// to an on-heap object. The m_raw is automatically cleared when the pointee -// gets collected. -// -// We have to construct and destruct WeakPersistent in the same thread. -// -// Note that collections of WeakPersistents are not supported. Use a collection -// of WeakMembers instead. -// -// HashSet<WeakPersistent<T>> m_set; // wrong -// Persistent<HeapHashSet<WeakMember<T>>> m_set; // correct -template <typename T> -class WeakPersistent - : public PersistentBase<T, - kWeakPersistentConfiguration, - kSingleThreadPersistentConfiguration> { - using Parent = PersistentBase<T, - kWeakPersistentConfiguration, - kSingleThreadPersistentConfiguration>; - - public: - WeakPersistent() : Parent() {} - WeakPersistent(std::nullptr_t) : Parent(nullptr) {} - WeakPersistent(T* raw) : Parent(raw) {} - WeakPersistent(T& raw) : Parent(raw) {} - WeakPersistent(const WeakPersistent& other) : Parent(other) {} - template <typename U> - WeakPersistent(const WeakPersistent<U>& other) : Parent(other) {} - template <typename U> - WeakPersistent(const Member<U>& other) : Parent(other) {} - - template <typename U> - WeakPersistent& operator=(U* other) { - Parent::operator=(other); - return *this; - } - - WeakPersistent& operator=(std::nullptr_t) { - Parent::operator=(nullptr); - return *this; - } - - WeakPersistent& operator=(const WeakPersistent& other) { - Parent::operator=(other); - return *this; - } - - template <typename U> - WeakPersistent& operator=(const WeakPersistent<U>& other) { - Parent::operator=(other); - return *this; - } - - template <typename U> - WeakPersistent& operator=(const Member<U>& other) { - Parent::operator=(other); - return *this; - } -}; - -// CrossThreadPersistent allows for holding onto an object strongly on a -// different thread. -// -// Thread-safe operations: -// - Construction -// - Destruction -// - Copy and move construction and assignment -// - Clearing -// - Deref if treated as immutable reference or if externally synchronized (e.g. -// mutex, task). The current implementation of Get() uses a raw load (on -// purpose) which prohibits mutation while accessing the reference on a -// different thread. -template <typename T> -class CrossThreadPersistent - : public PersistentBase<T, - kNonWeakPersistentConfiguration, - kCrossThreadPersistentConfiguration> { - using Parent = PersistentBase<T, - kNonWeakPersistentConfiguration, - kCrossThreadPersistentConfiguration>; - - public: - CrossThreadPersistent() : Parent() {} - CrossThreadPersistent(const PersistentLocation& location) - : Parent(location) {} - CrossThreadPersistent(std::nullptr_t) : Parent(nullptr) {} - CrossThreadPersistent(const PersistentLocation& location, std::nullptr_t) - : Parent(location, nullptr) {} - explicit CrossThreadPersistent(T* raw) : Parent(raw) {} - CrossThreadPersistent(const PersistentLocation& location, T* raw) - : Parent(location, raw) {} - explicit CrossThreadPersistent(T& raw) : Parent(raw) {} - CrossThreadPersistent(const PersistentLocation& location, T& raw) - : Parent(location, raw) {} - CrossThreadPersistent(const CrossThreadPersistent& other) { *this = other; } - CrossThreadPersistent(const PersistentLocation& location, - const CrossThreadPersistent& other) { - *this = other; - } - template <typename U> - CrossThreadPersistent(const CrossThreadPersistent<U>& other) { - *this = other; - } - template <typename U> - CrossThreadPersistent(const PersistentLocation& location, - const CrossThreadPersistent<U>& other) { - *this = other; - } - template <typename U> - CrossThreadPersistent(const Member<U>& other) : Parent(other) {} - template <typename U> - CrossThreadPersistent(const PersistentLocation& location, - const Member<U>& other) - : Parent(location, other) {} - CrossThreadPersistent(WTF::HashTableDeletedValueType x) : Parent(x) {} - CrossThreadPersistent(const PersistentLocation& location, - WTF::HashTableDeletedValueType x) - : Parent(location, x) {} - template <typename U> - CrossThreadPersistent(const CrossThreadWeakPersistent<U>& other) { - *this = other; - } - - // Instead of using release(), assign then clear() instead. - // Using release() with per thread heap enabled can cause the object to be - // destroyed before assigning it to a new handle. - T* Release() = delete; - - template <typename U> - CrossThreadPersistent& operator=(U* other) { - Parent::operator=(other); - return *this; - } - - CrossThreadPersistent& operator=(std::nullptr_t) { - Parent::operator=(nullptr); - return *this; - } - - CrossThreadPersistent& operator=(const CrossThreadPersistent& other) { - MutexLocker locker(ProcessHeap::CrossThreadPersistentMutex()); - Parent::operator=(other); - return *this; - } - - template <typename U> - CrossThreadPersistent& operator=(const CrossThreadPersistent<U>& other) { - MutexLocker locker(ProcessHeap::CrossThreadPersistentMutex()); - Parent::operator=(other); - return *this; - } - - template <typename U> - CrossThreadPersistent& operator=(const CrossThreadWeakPersistent<U>&); -}; - -// CrossThreadWeakPersistent combines behavior of CrossThreadPersistent and -// WeakPersistent, i.e., it allows holding onto an object weakly on a different -// thread. -// -// Thread-safe operations: -// - Construction -// - Destruction -// - Copy and move construction and assignment -// - Clearing -// -// Note that this does not include dereferencing and using the raw pointer as -// there is no guarantee that the object will be alive at the time it is used. -template <typename T> -class CrossThreadWeakPersistent - : public PersistentBase<T, - kWeakPersistentConfiguration, - kCrossThreadPersistentConfiguration> { - using Parent = PersistentBase<T, - kWeakPersistentConfiguration, - kCrossThreadPersistentConfiguration>; - - public: - CrossThreadWeakPersistent() : Parent() {} - explicit CrossThreadWeakPersistent(T* raw) : Parent(raw) {} - explicit CrossThreadWeakPersistent(T& raw) : Parent(raw) {} - CrossThreadWeakPersistent(const CrossThreadWeakPersistent& other) { - *this = other; - } - template <typename U> - CrossThreadWeakPersistent(const CrossThreadWeakPersistent<U>& other) { - *this = other; - } - CrossThreadWeakPersistent(CrossThreadWeakPersistent&& other) { - *this = std::move(other); - } - template <typename U> - CrossThreadWeakPersistent(CrossThreadWeakPersistent<U>&& other) { - *this = std::move(other); - } - - CrossThreadWeakPersistent& operator=(const CrossThreadWeakPersistent& other) { - MutexLocker locker(ProcessHeap::CrossThreadPersistentMutex()); - Parent::operator=(other); - return *this; - } - - template <typename U> - CrossThreadWeakPersistent& operator=( - const CrossThreadWeakPersistent<U>& other) { - MutexLocker locker(ProcessHeap::CrossThreadPersistentMutex()); - Parent::operator=(other); - return *this; - } - - CrossThreadWeakPersistent& operator=(CrossThreadWeakPersistent&& other) { - MutexLocker locker(ProcessHeap::CrossThreadPersistentMutex()); - Parent::operator=(std::move(other)); - return *this; - } - - template <typename U> - CrossThreadWeakPersistent& operator=(CrossThreadWeakPersistent<U>&& other) { - MutexLocker locker(ProcessHeap::CrossThreadPersistentMutex()); - Parent::operator=(std::move(other)); - return *this; - } - - template <typename U> - CrossThreadWeakPersistent& operator=(U* other) { - Parent::operator=(other); - return *this; - } - - // Create a CrossThreadPersistent that keeps the underlying object alive if - // there is still on set. Can be used to work with an object on a different - // thread than it was allocated. Note that CTP does not block threads from - // terminating, in which case the reference would still be invalid. - const CrossThreadPersistent<T> Lock() const { - return CrossThreadPersistent<T>(*this); - } - - // Disallow directly using CrossThreadWeakPersistent. Users must go through - // CrossThreadPersistent to access the pointee. Note that this does not - // guarantee that the object is still alive at that point. Users must check - // the state of CTP manually before invoking any calls. - T* operator->() const = delete; - T& operator*() const = delete; - operator T*() const = delete; - T* Get() const = delete; - - private: - template <typename U> - friend class CrossThreadPersistent; -}; - -template <typename T> -template <typename U> -CrossThreadPersistent<T>& CrossThreadPersistent<T>::operator=( - const CrossThreadWeakPersistent<U>& other) { - MutexLocker locker(ProcessHeap::CrossThreadPersistentMutex()); - using ParentU = PersistentBase<U, kWeakPersistentConfiguration, - kCrossThreadPersistentConfiguration>; - this->AssignUnsafe(static_cast<const ParentU&>(other).Get()); - return *this; -} - -template <typename T> -Persistent<T> WrapPersistentInternal(const PersistentLocation& location, - T* value) { - return Persistent<T>(location, value); -} - -template <typename T> -Persistent<T> WrapPersistentInternal(T* value) { - return Persistent<T>(value); -} - -#if BUILDFLAG(RAW_HEAP_SNAPSHOTS) -#define WrapPersistent(value) \ - WrapPersistentInternal(PERSISTENT_FROM_HERE, value) -#else -#define WrapPersistent(value) WrapPersistentInternal(value) -#endif // BUILDFLAG(RAW_HEAP_SNAPSHOTS) - -template <typename T> -WeakPersistent<T> WrapWeakPersistent(T* value) { - return WeakPersistent<T>(value); -} - -template <typename T> -CrossThreadPersistent<T> WrapCrossThreadPersistentInternal( - const PersistentLocation& location, - T* value) { - return CrossThreadPersistent<T>(location, value); -} - -template <typename T> -CrossThreadPersistent<T> WrapCrossThreadPersistentInternal(T* value) { - return CrossThreadPersistent<T>(value); -} - -#if BUILDFLAG(RAW_HEAP_SNAPSHOTS) -#define WrapCrossThreadPersistent(value) \ - WrapCrossThreadPersistentInternal(PERSISTENT_FROM_HERE, value) -#else -#define WrapCrossThreadPersistent(value) \ - WrapCrossThreadPersistentInternal(value) -#endif // BUILDFLAG(RAW_HEAP_SNAPSHOTS) - -template <typename T> -CrossThreadWeakPersistent<T> WrapCrossThreadWeakPersistent(T* value) { - return CrossThreadWeakPersistent<T>(value); -} - -// Comparison operators between (Weak)Members, Persistents, and UntracedMembers. -template <typename T, typename U> -inline bool operator==(const Member<T>& a, const Member<U>& b) { - return a.Get() == b.Get(); -} -template <typename T, typename U> -inline bool operator!=(const Member<T>& a, const Member<U>& b) { - return a.Get() != b.Get(); -} -template <typename T, typename U> -inline bool operator==(const Persistent<T>& a, const Persistent<U>& b) { - return a.Get() == b.Get(); -} -template <typename T, typename U> -inline bool operator!=(const Persistent<T>& a, const Persistent<U>& b) { - return a.Get() != b.Get(); -} - -template <typename T, typename U> -inline bool operator==(const Member<T>& a, const Persistent<U>& b) { - return a.Get() == b.Get(); -} -template <typename T, typename U> -inline bool operator!=(const Member<T>& a, const Persistent<U>& b) { - return a.Get() != b.Get(); -} -template <typename T, typename U> -inline bool operator==(const Persistent<T>& a, const Member<U>& b) { - return a.Get() == b.Get(); -} -template <typename T, typename U> -inline bool operator!=(const Persistent<T>& a, const Member<U>& b) { - return a.Get() != b.Get(); -} - -template <typename U, typename T> -Persistent<U> DownCast(const Persistent<T>& p) { - return Persistent<U>(p); -} - -template <typename U, typename T> -WeakPersistent<U> DownCast(const WeakPersistent<T>& p) { - return WeakPersistent<U>(p); -} - -template <typename U, typename T> -CrossThreadPersistent<U> DownCast(const CrossThreadPersistent<T>& p) { - return CrossThreadPersistent<U>(p); -} - -template <typename U, typename T> -CrossThreadWeakPersistent<U> DownCast(const CrossThreadWeakPersistent<T>& p) { - return CrossThreadWeakPersistent<U>(p); -} - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_PERSISTENT_H_
diff --git a/third_party/blink/renderer/platform/heap/impl/persistent_node.cc b/third_party/blink/renderer/platform/heap/impl/persistent_node.cc deleted file mode 100644 index f61c39b..0000000 --- a/third_party/blink/renderer/platform/heap/impl/persistent_node.cc +++ /dev/null
@@ -1,206 +0,0 @@ -// Copyright 2015 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/heap/impl/persistent_node.h" - -#include "base/debug/alias.h" -#include "third_party/blink/renderer/platform/heap/handle.h" -#include "third_party/blink/renderer/platform/heap/persistent.h" -#include "third_party/blink/renderer/platform/heap/process_heap.h" - -namespace blink { - -namespace { - -class DummyGCBase final : public GarbageCollected<DummyGCBase> { - public: - void Trace(Visitor* visitor) const {} -}; -} // namespace - -PersistentRegionBase::~PersistentRegionBase() { - PersistentNodeSlots* slots = slots_; - while (slots) { - PersistentNodeSlots* dead_slots = slots; - slots = slots->next; - delete dead_slots; - } -} - -int PersistentRegionBase::NodesInUse() const { - int persistent_count = 0; - for (PersistentNodeSlots* slots = slots_; slots; slots = slots->next) { - for (int i = 0; i < PersistentNodeSlots::kSlotCount; ++i) { - if (!slots->slot[i].IsUnused()) - ++persistent_count; - } - } -#if DCHECK_IS_ON() - DCHECK_EQ(persistent_count, used_node_count_); -#endif - return persistent_count; -} - -void PersistentRegionBase::EnsureNodeSlots() { - DCHECK(!free_list_head_); - PersistentNodeSlots* slots = new PersistentNodeSlots; - for (int i = 0; i < PersistentNodeSlots::kSlotCount; ++i) { - PersistentNode* node = &slots->slot[i]; - node->SetFreeListNext(free_list_head_); - free_list_head_ = node; - DCHECK(node->IsUnused()); - } - slots->next = slots_; - slots_ = slots; -} - -void PersistentRegionBase::TraceNodesImpl(Visitor* visitor, - ShouldTraceCallback should_trace) { - free_list_head_ = nullptr; - int persistent_count = 0; - PersistentNodeSlots** prev_next = &slots_; - PersistentNodeSlots* slots = slots_; - while (slots) { - PersistentNode* free_list_next = nullptr; - PersistentNode* free_list_last = nullptr; - int free_count = 0; - for (int i = 0; i < PersistentNodeSlots::kSlotCount; ++i) { - PersistentNode* node = &slots->slot[i]; - if (node->IsUnused()) { - if (!free_list_next) - free_list_last = node; - node->SetFreeListNext(free_list_next); - free_list_next = node; - ++free_count; - } else { - ++persistent_count; - if (!should_trace(visitor, node)) - continue; - node->TracePersistentNode(visitor); - } - } - if (free_count == PersistentNodeSlots::kSlotCount) { - PersistentNodeSlots* dead_slots = slots; - *prev_next = slots->next; - slots = slots->next; - delete dead_slots; - } else { - if (free_list_last) { - DCHECK(free_list_next); - DCHECK(!free_list_last->FreeListNext()); - free_list_last->SetFreeListNext(free_list_head_); - free_list_head_ = free_list_next; - } - prev_next = &slots->next; - slots = slots->next; - } - } -#if DCHECK_IS_ON() - DCHECK_EQ(persistent_count, used_node_count_); -#endif -} - -void PersistentRegion::ReleaseNode(PersistentNode* persistent_node) { - DCHECK(!persistent_node->IsUnused()); - // 'self' is in use, containing the persistent wrapper object. - void* self = persistent_node->Self(); - Persistent<DummyGCBase>* persistent = - reinterpret_cast<Persistent<DummyGCBase>*>(self); - persistent->Clear(); - DCHECK(persistent_node->IsUnused()); -} - -void PersistentRegion::PrepareForThreadStateTermination(ThreadState* state) { - DCHECK_EQ(state, ThreadState::Current()); - DCHECK(!IsMainThread()); - PersistentNodeSlots* slots = slots_; - while (slots) { - for (int i = 0; i < PersistentNodeSlots::kSlotCount; ++i) { - PersistentNode* node = &slots->slot[i]; - if (node->IsUnused()) - continue; - // It is safe to cast to Persistent<DummyGCBase> because persistent heap - // collections are banned in non-main threads. - Persistent<DummyGCBase>* persistent = - reinterpret_cast<Persistent<DummyGCBase>*>(node->Self()); - DCHECK(persistent); - persistent->Clear(); - DCHECK(node->IsUnused()); - } - slots = slots->next; - } -#if DCHECK_IS_ON() - DCHECK_EQ(used_node_count_, 0); -#endif -} - -bool CrossThreadPersistentRegion::ShouldTracePersistentNode( - Visitor* visitor, - PersistentNode* node) { - CrossThreadPersistent<DummyGCBase>* persistent = - reinterpret_cast<CrossThreadPersistent<DummyGCBase>*>(node->Self()); - DCHECK(persistent); - DCHECK(!persistent->IsHashTableDeletedValue()); - Address raw_object = reinterpret_cast<Address>(persistent->Get()); - if (!raw_object) - return false; - return &visitor->Heap() == &ThreadState::FromObject(raw_object)->Heap(); -} - -void CrossThreadPersistentRegion::PrepareForThreadStateTermination( - ThreadState* thread_state) { - // For heaps belonging to a thread that's detaching, any cross-thread - // persistents pointing into them needs to be disabled. Do that by clearing - // out the underlying heap reference. - MutexLocker lock(ProcessHeap::CrossThreadPersistentMutex()); - - PersistentNodeSlots* slots = slots_; - while (slots) { - for (int i = 0; i < PersistentNodeSlots::kSlotCount; ++i) { - if (slots->slot[i].IsUnused()) - continue; - - // 'self' is in use, containing the cross-thread persistent wrapper - // object. - CrossThreadPersistent<DummyGCBase>* persistent = - reinterpret_cast<CrossThreadPersistent<DummyGCBase>*>( - slots->slot[i].Self()); - DCHECK(persistent); - void* raw_object = persistent->Get(); - if (!raw_object) - continue; - BasePage* page = PageFromObject(raw_object); - DCHECK(page); - if (page->Arena()->GetThreadState() == thread_state) { - persistent->ClearWithLockHeld(); - DCHECK(slots->slot[i].IsUnused()); - } - } - slots = slots->next; - } -} - -#if defined(ADDRESS_SANITIZER) -void CrossThreadPersistentRegion::UnpoisonCrossThreadPersistents() { -#if DCHECK_IS_ON() - ProcessHeap::CrossThreadPersistentMutex().AssertAcquired(); -#endif - int persistent_count = 0; - for (PersistentNodeSlots* slots = slots_; slots; slots = slots->next) { - for (int i = 0; i < PersistentNodeSlots::kSlotCount; ++i) { - const PersistentNode& node = slots->slot[i]; - if (!node.IsUnused()) { - ASAN_UNPOISON_MEMORY_REGION(node.Self(), - sizeof(CrossThreadPersistent<void*>)); - ++persistent_count; - } - } - } -#if DCHECK_IS_ON() - DCHECK_EQ(persistent_count, used_node_count_); -#endif -} -#endif - -} // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/impl/persistent_node.h b/third_party/blink/renderer/platform/heap/impl/persistent_node.h deleted file mode 100644 index ab99685..0000000 --- a/third_party/blink/renderer/platform/heap/impl/persistent_node.h +++ /dev/null
@@ -1,386 +0,0 @@ -// Copyright 2015 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. - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_PERSISTENT_NODE_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_PERSISTENT_NODE_H_ - -#include <atomic> -#include <memory> - -#include "base/dcheck_is_on.h" -#include "third_party/blink/renderer/platform/heap/process_heap.h" -#include "third_party/blink/renderer/platform/heap/thread_state.h" -#include "third_party/blink/renderer/platform/platform_export.h" -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" -#include "third_party/blink/renderer/platform/wtf/threading_primitives.h" - -namespace blink { - -class CrossThreadPersistentRegion; -class PersistentRegion; - -enum WeaknessPersistentConfiguration { - kNonWeakPersistentConfiguration, - kWeakPersistentConfiguration -}; - -enum CrossThreadnessPersistentConfiguration { - kSingleThreadPersistentConfiguration, - kCrossThreadPersistentConfiguration -}; - -template <CrossThreadnessPersistentConfiguration> -struct PersistentMutexTraits { - struct [[maybe_unused]] Locker{}; - static void AssertAcquired() {} -}; - -template <> -struct PersistentMutexTraits<kCrossThreadPersistentConfiguration> { - struct Locker { - MutexLocker locker{ProcessHeap::CrossThreadPersistentMutex()}; - }; - static void AssertAcquired() { -#if DCHECK_IS_ON() - ProcessHeap::CrossThreadPersistentMutex().AssertAcquired(); -#endif - } -}; - -class PersistentNode final { - DISALLOW_NEW(); - - public: - PersistentNode() { DCHECK(IsUnused()); } - -#if DCHECK_IS_ON() - ~PersistentNode() { - // If you hit this assert, it means that the thread finished - // without clearing persistent handles that the thread created. - // We don't enable the assert for the main thread because the - // main thread finishes without clearing all persistent handles. - DCHECK(IsMainThread() || IsUnused()); - } -#endif - - // It is dangerous to copy the PersistentNode because it breaks the - // free list. - PersistentNode& operator=(const PersistentNode& otherref) = delete; - - // Ideally the trace method should be virtual and automatically dispatch - // to the most specific implementation. However having a virtual method - // on PersistentNode leads to too eager template instantiation with MSVC - // which leads to include cycles. - // Instead we call the constructor with a TraceCallback which knows the - // type of the most specific child and calls trace directly. See - // TraceMethodDelegate in Visitor.h for how this is done. - void TracePersistentNode(Visitor* visitor) const { - DCHECK(!IsUnused()); - DCHECK(trace_); - trace_(visitor, self_); - } - - void Initialize(void* self, TraceCallback trace) { - DCHECK(IsUnused()); - self_ = self; - trace_ = trace; - } - - void Reinitialize(void* self, TraceCallback trace) { - self_ = self; - trace_ = trace; - } - - void SetFreeListNext(PersistentNode* node) { - DCHECK(!node || node->IsUnused()); - self_ = node; - trace_ = nullptr; - DCHECK(IsUnused()); - } - - PersistentNode* FreeListNext() { - DCHECK(IsUnused()); - PersistentNode* node = reinterpret_cast<PersistentNode*>(self_); - DCHECK(!node || node->IsUnused()); - return node; - } - - bool IsUnused() const { return !trace_; } - - void* Self() const { return self_; } - - private: - // If this PersistentNode is in use: - // - m_self points to the corresponding Persistent handle. - // - m_trace points to the trace method. - // If this PersistentNode is freed: - // - m_self points to the next freed PersistentNode. - // - m_trace is nullptr. - void* self_ = nullptr; - TraceCallback trace_ = nullptr; -}; - -struct PersistentNodeSlots final { - USING_FAST_MALLOC(PersistentNodeSlots); - - public: - static constexpr int kSlotCount = 256; - - PersistentNodeSlots* next; - PersistentNode slot[kSlotCount]; -}; - -// Used by PersistentBase to manage a pointer to a thread heap persistent node. -// This class mostly passes accesses through, but provides an interface -// compatible with CrossThreadPersistentNodePtr. -template <ThreadAffinity affinity, - WeaknessPersistentConfiguration weakness_configuration> -class PersistentNodePtr { - STACK_ALLOCATED(); - - public: - PersistentNode* Get() const { return ptr_; } - bool IsInitialized() const { return ptr_; } - - void Initialize(void* owner, TraceCallback); - void Uninitialize(); - - PersistentNodePtr& operator=(PersistentNodePtr&& other) { - ptr_ = other.ptr_; - other.ptr_ = nullptr; - return *this; - } - - private: - PersistentNode* ptr_ = nullptr; -#if DCHECK_IS_ON() - ThreadState* state_ = nullptr; -#endif -}; - -// Used by PersistentBase to manage a pointer to a cross-thread persistent node. -// It uses ProcessHeap::CrossThreadPersistentMutex() to protect most accesses, -// but can be polled to see whether it is initialized without the mutex. -template <WeaknessPersistentConfiguration weakness_configuration> -class CrossThreadPersistentNodePtr { - STACK_ALLOCATED(); - - public: - PersistentNode* Get() const { - PersistentMutexTraits< - kCrossThreadPersistentConfiguration>::AssertAcquired(); - return ptr_.load(std::memory_order_relaxed); - } - bool IsInitialized() const { return ptr_.load(std::memory_order_acquire); } - - void Initialize(void* owner, TraceCallback); - void Uninitialize(); - - void ClearWithLockHeld(); - - CrossThreadPersistentNodePtr& operator=( - CrossThreadPersistentNodePtr&& other) { - PersistentMutexTraits< - kCrossThreadPersistentConfiguration>::AssertAcquired(); - PersistentNode* node = other.ptr_.load(std::memory_order_relaxed); - ptr_.store(node, std::memory_order_relaxed); - other.ptr_.store(nullptr, std::memory_order_relaxed); - return *this; - } - - private: - // Access must either be protected by the cross-thread persistent mutex or - // handle the fact that this may be changed concurrently (with a - // release-store). - std::atomic<PersistentNode*> ptr_{nullptr}; -}; - -class PLATFORM_EXPORT PersistentRegionBase { - public: - ~PersistentRegionBase(); - - inline PersistentNode* AllocateNode(void* self, TraceCallback trace); - inline void FreeNode(PersistentNode* persistent_node); - int NodesInUse() const; - - protected: - using ShouldTraceCallback = bool (*)(Visitor*, PersistentNode*); - - void TraceNodesImpl(Visitor*, ShouldTraceCallback); - - void EnsureNodeSlots(); - - PersistentNode* free_list_head_ = nullptr; - PersistentNodeSlots* slots_ = nullptr; -#if DCHECK_IS_ON() - int used_node_count_ = 0; -#endif -}; - -inline PersistentNode* PersistentRegionBase::AllocateNode(void* self, - TraceCallback trace) { -#if DCHECK_IS_ON() - ++used_node_count_; -#endif - if (UNLIKELY(!free_list_head_)) - EnsureNodeSlots(); - DCHECK(free_list_head_); - PersistentNode* node = free_list_head_; - free_list_head_ = free_list_head_->FreeListNext(); - node->Initialize(self, trace); - DCHECK(!node->IsUnused()); - return node; -} - -void PersistentRegionBase::FreeNode(PersistentNode* persistent_node) { -#if DCHECK_IS_ON() - DCHECK_GT(used_node_count_, 0); -#endif - persistent_node->SetFreeListNext(free_list_head_); - free_list_head_ = persistent_node; -#if DCHECK_IS_ON() - --used_node_count_; -#endif -} - -class PLATFORM_EXPORT PersistentRegion final : public PersistentRegionBase { - USING_FAST_MALLOC(PersistentRegion); - - public: - inline void TraceNodes(Visitor*); - - // Clears the Persistent and then frees the node. - void ReleaseNode(PersistentNode*); - - void PrepareForThreadStateTermination(ThreadState*); - - private: - static constexpr bool ShouldTracePersistentNode(Visitor*, PersistentNode*) { - return true; - } -}; - -inline void PersistentRegion::TraceNodes(Visitor* visitor) { - PersistentRegionBase::TraceNodesImpl(visitor, ShouldTracePersistentNode); -} - -class PLATFORM_EXPORT CrossThreadPersistentRegion final - : public PersistentRegionBase { - USING_FAST_MALLOC(CrossThreadPersistentRegion); - - public: - inline PersistentNode* AllocateNode(void* self, TraceCallback trace); - inline void FreeNode(PersistentNode*); - inline void TraceNodes(Visitor*); - - void PrepareForThreadStateTermination(ThreadState*); - -#if defined(ADDRESS_SANITIZER) - void UnpoisonCrossThreadPersistents(); -#endif - - private: - NO_SANITIZE_ADDRESS - static bool ShouldTracePersistentNode(Visitor*, PersistentNode*); -}; - -inline PersistentNode* CrossThreadPersistentRegion::AllocateNode( - void* self, - TraceCallback trace) { - PersistentMutexTraits<kCrossThreadPersistentConfiguration>::AssertAcquired(); - return PersistentRegionBase::AllocateNode(self, trace); -} - -inline void CrossThreadPersistentRegion::FreeNode(PersistentNode* node) { - PersistentMutexTraits<kCrossThreadPersistentConfiguration>::AssertAcquired(); - // PersistentBase::UninitializeSafe opportunistically checks for uninitialized - // nodes to allow a fast path destruction of unused nodes. This check is - // performed without taking the lock that is required for processing a - // cross-thread node. After taking the lock the condition needs to checked - // again to avoid double-freeing a node because the node may have been - // concurrently freed by the garbage collector on another thread. - if (!node) - return; - PersistentRegionBase::FreeNode(node); -} - -inline void CrossThreadPersistentRegion::TraceNodes(Visitor* visitor) { - PersistentRegionBase::TraceNodesImpl(visitor, ShouldTracePersistentNode); -} - -template <ThreadAffinity affinity, - WeaknessPersistentConfiguration weakness_configuration> -void PersistentNodePtr<affinity, weakness_configuration>::Initialize( - void* owner, - TraceCallback trace_callback) { - ThreadState* state = ThreadStateFor<affinity>::GetState(); - DCHECK(state->CheckThread()); - PersistentRegion* region = - weakness_configuration == kWeakPersistentConfiguration - ? state->GetWeakPersistentRegion() - : state->GetPersistentRegion(); - ptr_ = region->AllocateNode(owner, trace_callback); -#if DCHECK_IS_ON() - state_ = state; -#endif -} - -template <ThreadAffinity affinity, - WeaknessPersistentConfiguration weakness_configuration> -void PersistentNodePtr<affinity, weakness_configuration>::Uninitialize() { - if (!ptr_) - return; - ThreadState* state = ThreadStateFor<affinity>::GetState(); - DCHECK(state->CheckThread()); -#if DCHECK_IS_ON() - DCHECK_EQ(state_, state) - << "must be initialized and uninitialized on the same thread"; - state_ = nullptr; -#endif - PersistentRegion* region = - weakness_configuration == kWeakPersistentConfiguration - ? state->GetWeakPersistentRegion() - : state->GetPersistentRegion(); - region->FreeNode(ptr_); - ptr_ = nullptr; -} - -template <WeaknessPersistentConfiguration weakness_configuration> -void CrossThreadPersistentNodePtr<weakness_configuration>::Initialize( - void* owner, - TraceCallback trace_callback) { - PersistentMutexTraits<kCrossThreadPersistentConfiguration>::AssertAcquired(); - CrossThreadPersistentRegion& region = - weakness_configuration == kWeakPersistentConfiguration - ? ProcessHeap::GetCrossThreadWeakPersistentRegion() - : ProcessHeap::GetCrossThreadPersistentRegion(); - PersistentNode* node = region.AllocateNode(owner, trace_callback); - ptr_.store(node, std::memory_order_release); -} - -template <WeaknessPersistentConfiguration weakness_configuration> -void CrossThreadPersistentNodePtr<weakness_configuration>::Uninitialize() { - PersistentMutexTraits<kCrossThreadPersistentConfiguration>::AssertAcquired(); - CrossThreadPersistentRegion& region = - weakness_configuration == kWeakPersistentConfiguration - ? ProcessHeap::GetCrossThreadWeakPersistentRegion() - : ProcessHeap::GetCrossThreadPersistentRegion(); - region.FreeNode(ptr_.load(std::memory_order_relaxed)); - ptr_.store(nullptr, std::memory_order_release); -} - -template <WeaknessPersistentConfiguration weakness_configuration> -void CrossThreadPersistentNodePtr<weakness_configuration>::ClearWithLockHeld() { - PersistentMutexTraits<kCrossThreadPersistentConfiguration>::AssertAcquired(); - CrossThreadPersistentRegion& region = - weakness_configuration == kWeakPersistentConfiguration - ? ProcessHeap::GetCrossThreadWeakPersistentRegion() - : ProcessHeap::GetCrossThreadPersistentRegion(); - region.FreeNode(ptr_.load(std::memory_order_relaxed)); - ptr_.store(nullptr, std::memory_order_release); -} - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_PERSISTENT_NODE_H_
diff --git a/third_party/blink/renderer/platform/heap/impl/process_heap.cc b/third_party/blink/renderer/platform/heap/impl/process_heap.cc deleted file mode 100644 index 7390044..0000000 --- a/third_party/blink/renderer/platform/heap/impl/process_heap.cc +++ /dev/null
@@ -1,51 +0,0 @@ -// 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/heap/process_heap.h" - -#include "base/sampling_heap_profiler/poisson_allocation_sampler.h" -#include "third_party/blink/public/common/features.h" -#include "third_party/blink/renderer/platform/heap/heap.h" -#include "third_party/blink/renderer/platform/heap/impl/gc_info.h" -#include "third_party/blink/renderer/platform/heap/impl/persistent_node.h" - -namespace blink { - -void ProcessHeap::Init() { - DCHECK(!base::FeatureList::IsEnabled( - blink::features::kBlinkHeapConcurrentMarking) || - base::FeatureList::IsEnabled( - blink::features::kBlinkHeapIncrementalMarking)); - - total_allocated_space_ = 0; - total_allocated_object_size_ = 0; - - GCInfoTable::CreateGlobalTable(); -} - -void ProcessHeap::ResetHeapCounters() { - total_allocated_object_size_ = 0; -} - -CrossThreadPersistentRegion& ProcessHeap::GetCrossThreadPersistentRegion() { - DEFINE_THREAD_SAFE_STATIC_LOCAL(CrossThreadPersistentRegion, - persistent_region, ()); - return persistent_region; -} - -CrossThreadPersistentRegion& ProcessHeap::GetCrossThreadWeakPersistentRegion() { - DEFINE_THREAD_SAFE_STATIC_LOCAL(CrossThreadPersistentRegion, - persistent_region, ()); - return persistent_region; -} - -Mutex& ProcessHeap::CrossThreadPersistentMutex() { - DEFINE_THREAD_SAFE_STATIC_LOCAL(Mutex, mutex, ()); - return mutex; -} - -std::atomic_size_t ProcessHeap::total_allocated_space_{0}; -std::atomic_size_t ProcessHeap::total_allocated_object_size_{0}; - -} // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/impl/process_heap.h b/third_party/blink/renderer/platform/heap/impl/process_heap.h deleted file mode 100644 index 91112a7c..0000000 --- a/third_party/blink/renderer/platform/heap/impl/process_heap.h +++ /dev/null
@@ -1,69 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_PROCESS_HEAP_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_PROCESS_HEAP_H_ - -#include <atomic> -#include "third_party/blink/renderer/platform/platform_export.h" -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" -#include "third_party/blink/renderer/platform/wtf/threading_primitives.h" - -namespace blink { - -class CrossThreadPersistentRegion; - -class PLATFORM_EXPORT ProcessHeap { - STATIC_ONLY(ProcessHeap); - - public: - static void Init(); - - static CrossThreadPersistentRegion& GetCrossThreadPersistentRegion(); - static CrossThreadPersistentRegion& GetCrossThreadWeakPersistentRegion(); - - // Access to the CrossThreadPersistentRegion from multiple threads has to be - // prevented as allocation, freeing, and iteration of nodes may otherwise - // cause data races. - // - // Examples include: - // - Iteration of strong cross-thread Persistents. - // - Iteration and processing of weak cross-thread Persistents. The lock - // needs to span both operations as iteration of weak persistents only - // registers memory regions that are then processed afterwards. - // - Marking phase in garbage collection: The whole phase requires locking - // as CrossThreadWeakPersistents may be converted to CrossThreadPersistent - // which must observe GC as an atomic operation. - static Mutex& CrossThreadPersistentMutex(); - - static void IncreaseTotalAllocatedObjectSize(size_t delta) { - total_allocated_object_size_.fetch_add(delta, std::memory_order_relaxed); - } - static void DecreaseTotalAllocatedObjectSize(size_t delta) { - total_allocated_object_size_.fetch_sub(delta, std::memory_order_relaxed); - } - static size_t TotalAllocatedObjectSize() { - return total_allocated_object_size_.load(std::memory_order_relaxed); - } - static void IncreaseTotalAllocatedSpace(size_t delta) { - total_allocated_space_.fetch_add(delta, std::memory_order_relaxed); - } - static void DecreaseTotalAllocatedSpace(size_t delta) { - total_allocated_space_.fetch_sub(delta, std::memory_order_relaxed); - } - static size_t TotalAllocatedSpace() { - return total_allocated_space_.load(std::memory_order_relaxed); - } - static void ResetHeapCounters(); - - private: - static std::atomic_size_t total_allocated_space_; - static std::atomic_size_t total_allocated_object_size_; - - friend class ThreadState; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_PROCESS_HEAP_H_
diff --git a/third_party/blink/renderer/platform/heap/impl/test/card_table_test.cc b/third_party/blink/renderer/platform/heap/impl/test/card_table_test.cc deleted file mode 100644 index 6f975c5..0000000 --- a/third_party/blink/renderer/platform/heap/impl/test/card_table_test.cc +++ /dev/null
@@ -1,182 +0,0 @@ -// Copyright 2020 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 <vector> - -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/renderer/platform/heap/heap_test_utilities.h" -#include "third_party/blink/renderer/platform/heap/impl/heap_page.h" -#include "third_party/blink/renderer/platform/heap/trace_traits.h" - -namespace blink { - -namespace { - -class BaseObject : public GarbageCollected<BaseObject> { - public: - size_t CardNumber() const; - void Trace(Visitor*) const {} -}; - -} // namespace - -class CardTableTest : public TestSupportingGC { - public: - static constexpr size_t kCardSize = NormalPage::CardTable::kCardSize; - - CardTableTest() { ClearOutOldGarbage(); } - - static void CheckObjects(const std::vector<BaseObject*>& objects, - const NormalPage& page) { - page.IterateCardTable([&objects](HeapObjectHeader* header) { - const BaseObject* object = - reinterpret_cast<BaseObject*>(header->Payload()); - auto it = std::find(objects.begin(), objects.end(), object); - EXPECT_NE(it, objects.end()); - }); - } - - static void MarkCardForObject(BaseObject* object) { - NormalPage* page = static_cast<NormalPage*>(PageFromObject(object)); - page->MarkCard(reinterpret_cast<Address>(object)); - } - - static bool IsCardMarked(const NormalPage& page, size_t card_number) { - return page.card_table_.IsMarked(card_number); - } - - static size_t ObjectsInCard(const NormalPage& page, size_t card_number) { - const NormalPage::CardTable& cards = page.card_table_; - - size_t objects = 0; - Address card_begin = - RoundToBlinkPageStart(page.GetAddress()) + (card_number * kCardSize); - const Address card_end = card_begin + kCardSize; - if (card_number == cards.begin().index) { - // First card is misaligned due to padding. - card_begin = page.Payload(); - } - - page.ArenaForNormalPage()->MakeConsistentForGC(); - - page.IterateOnCard( - [card_begin, card_end, &objects](HeapObjectHeader* header) { - const Address header_address = reinterpret_cast<Address>(header); - if (header_address < card_begin) { - const Address next_header_address = header_address + header->size(); - EXPECT_GT(next_header_address, card_begin); - } else { - objects++; - EXPECT_LT(header_address, card_end); - } - }, - card_number); - - return objects; - } - - static size_t MarkedObjects(const NormalPage& page) { - size_t objects = 0; - page.ArenaForNormalPage()->MakeConsistentForGC(); - page.IterateCardTable([&objects](HeapObjectHeader*) { ++objects; }); - return objects; - } - - static void ClearCardTable(NormalPage& page) { page.card_table_.Clear(); } -}; - -namespace { - -size_t BaseObject::CardNumber() const { - return (reinterpret_cast<uintptr_t>(this) & kBlinkPageOffsetMask) / - CardTableTest::kCardSize; -} - -template <size_t Size> -class Object : public BaseObject { - private: - uint8_t array[Size]; -}; - -} // namespace - -TEST_F(CardTableTest, Empty) { - BaseObject* obj = MakeGarbageCollected<BaseObject>(); - EXPECT_EQ(0u, MarkedObjects(*static_cast<NormalPage*>(PageFromObject(obj)))); -} - -TEST_F(CardTableTest, SingleObjectOnFirstCard) { - BaseObject* obj = MakeGarbageCollected<BaseObject>(); - MarkCardForObject(obj); - - const NormalPage& page = *static_cast<NormalPage*>(PageFromObject(obj)); - const size_t card_number = obj->CardNumber(); - EXPECT_TRUE(IsCardMarked(page, card_number)); - - const size_t objects = ObjectsInCard(page, card_number); - EXPECT_EQ(1u, objects); -} - -TEST_F(CardTableTest, SingleObjectOnSecondCard) { - MakeGarbageCollected<Object<kCardSize>>(); - BaseObject* obj = MakeGarbageCollected<Object<kCardSize>>(); - MarkCardForObject(obj); - - const NormalPage& page = *static_cast<NormalPage*>(PageFromObject(obj)); - const size_t card_number = obj->CardNumber(); - EXPECT_TRUE(IsCardMarked(page, card_number)); - - const size_t objects = ObjectsInCard(page, card_number); - EXPECT_EQ(1u, objects); -} - -TEST_F(CardTableTest, TwoObjectsOnSecondCard) { - static constexpr size_t kHalfCardSize = kCardSize / 2; - MakeGarbageCollected<Object<kHalfCardSize>>(); - MakeGarbageCollected<Object<kHalfCardSize>>(); - // The card on which 'obj' resides is guaranteed to have two objects, either - // the previously allocated one or the following one. - BaseObject* obj = MakeGarbageCollected<Object<kHalfCardSize>>(); - MakeGarbageCollected<Object<kHalfCardSize>>(); - MarkCardForObject(obj); - - const NormalPage& page = *static_cast<NormalPage*>(PageFromObject(obj)); - const size_t card_number = obj->CardNumber(); - EXPECT_TRUE(IsCardMarked(page, card_number)); - - const size_t objects = ObjectsInCard(page, card_number); - EXPECT_EQ(2u, objects); -} - -TEST_F(CardTableTest, Clear) { - MakeGarbageCollected<Object<kCardSize>>(); - MakeGarbageCollected<Object<kCardSize / 2>>(); - BaseObject* obj = MakeGarbageCollected<Object<kCardSize / 2>>(); - MarkCardForObject(obj); - - NormalPage& page = *static_cast<NormalPage*>(PageFromObject(obj)); - ClearCardTable(page); - - const size_t card_number = obj->CardNumber(); - EXPECT_FALSE(IsCardMarked(page, card_number)); -} - -TEST_F(CardTableTest, MultipleObjects) { - std::vector<BaseObject*> objects; - BaseObject* obj = MakeGarbageCollected<Object<kCardSize>>(); - BasePage* const first_page = PageFromObject(obj); - BasePage* new_page = first_page; - - while (first_page == new_page) { - objects.push_back(obj); - MarkCardForObject(obj); - - obj = MakeGarbageCollected<Object<kCardSize>>(); - new_page = PageFromObject(obj); - } - - CheckObjects(objects, *static_cast<NormalPage*>(first_page)); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/impl/test/gc_info_test.cc b/third_party/blink/renderer/platform/heap/impl/test/gc_info_test.cc deleted file mode 100644 index 3e007c35..0000000 --- a/third_party/blink/renderer/platform/heap/impl/test/gc_info_test.cc +++ /dev/null
@@ -1,45 +0,0 @@ -// 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/heap/impl/gc_info.h" - -#include "testing/gtest/include/gtest/gtest.h" - -namespace blink { - -TEST(GCInfoTest, InitialEmpty) { - GCInfoTable table; - EXPECT_EQ(GCInfoTable::kMinIndex, table.NumberOfGCInfos()); -} - -TEST(GCInfoTest, ResizeToMaxIndex) { - GCInfoTable table; - GCInfo info = {nullptr, nullptr, nullptr, false}; - std::atomic<GCInfoIndex> slot{0}; - for (GCInfoIndex i = GCInfoTable::kMinIndex; i < GCInfoTable::kMaxIndex; - i++) { - slot = 0; - GCInfoIndex index = table.EnsureGCInfoIndex(&info, &slot); - EXPECT_EQ(index, slot); - EXPECT_LT(0u, slot); - EXPECT_EQ(&info, &table.GCInfoFromIndex(index)); - } -} - -TEST(GCInfoDeathTest, MoreThanMaxIndexInfos) { - ::testing::FLAGS_gtest_death_test_style = "threadsafe"; - GCInfoTable table; - GCInfo info = {nullptr, nullptr, nullptr, false}; - std::atomic<GCInfoIndex> slot{0}; - // Create GCInfoTable::kMaxIndex entries. - for (GCInfoIndex i = GCInfoTable::kMinIndex; i < GCInfoTable::kMaxIndex; - i++) { - slot = 0; - table.EnsureGCInfoIndex(&info, &slot); - } - slot = 0; - EXPECT_DEATH(table.EnsureGCInfoIndex(&info, &slot), ""); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/impl/test/heap_internals_test.cc b/third_party/blink/renderer/platform/heap/impl/test/heap_internals_test.cc deleted file mode 100644 index 829db0d..0000000 --- a/third_party/blink/renderer/platform/heap/impl/test/heap_internals_test.cc +++ /dev/null
@@ -1,2201 +0,0 @@ -// Copyright 2021 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 "base/test/scoped_feature_list.h" -#include "build/build_config.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/public/common/features.h" -#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h" -#include "third_party/blink/renderer/platform/heap/handle.h" -#include "third_party/blink/renderer/platform/heap/heap_stats_collector.h" -#include "third_party/blink/renderer/platform/heap/heap_test_objects.h" -#include "third_party/blink/renderer/platform/heap/heap_test_utilities.h" -#include "third_party/blink/renderer/platform/heap/self_keep_alive.h" -#include "third_party/blink/renderer/platform/wtf/size_assertions.h" - -namespace blink { - -namespace { -class HeapInternalsTest : public TestSupportingGC {}; -} // namespace - -namespace { - -class IntWrapper : public GarbageCollected<IntWrapper> { - public: - virtual ~IntWrapper() { - destructor_calls_.fetch_add(1, std::memory_order_relaxed); - } - - static std::atomic_int destructor_calls_; - void Trace(Visitor* visitor) const {} - - int Value() const { return x_; } - - bool operator==(const IntWrapper& other) const { - return other.Value() == Value(); - } - - unsigned GetHash() { return IntHash<int>::GetHash(x_); } - - explicit IntWrapper(int x) : x_(x) {} - - IntWrapper() = delete; - - private: - int x_; -}; -std::atomic_int IntWrapper::destructor_calls_{0}; - -struct SameSizeAsPersistent { - void* pointers[2]; -#if DCHECK_IS_ON() - void* pointers_dcheck_[2]; -#endif -#if BUILDFLAG(RAW_HEAP_SNAPSHOTS) - PersistentLocation location; -#endif // BUILDFLAG(RAW_HEAP_SNAPSHOTS) -}; -ASSERT_SIZE(Persistent<IntWrapper>, SameSizeAsPersistent); - -} // namespace - -class TestGCScope { - STACK_ALLOCATED(); - - public: - explicit TestGCScope(BlinkGC::StackState state) { - DCHECK(ThreadState::Current()->CheckThread()); - ThreadState::Current()->Heap().stats_collector()->NotifyMarkingStarted( - BlinkGC::CollectionType::kMajor, BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - ThreadState::Current()->AtomicPauseMarkPrologue( - BlinkGC::CollectionType::kMajor, state, BlinkGC::kAtomicMarking, - BlinkGC::GCReason::kForcedGCForTesting); - } - ~TestGCScope() { - ThreadState::Current()->AtomicPauseMarkEpilogue(BlinkGC::kAtomicMarking); - ThreadState::Current()->AtomicPauseSweepAndCompact( - BlinkGC::CollectionType::kMajor, BlinkGC::kAtomicMarking, - BlinkGC::kEagerSweeping); - ThreadState::Current()->AtomicPauseEpilogue(); - ThreadState::Current()->CompleteSweep(); - } -}; - -namespace { -class SimpleObject : public GarbageCollected<SimpleObject> { - public: - SimpleObject() = default; - virtual void Trace(Visitor* visitor) const {} - char GetPayload(int i) { return payload[i]; } - // This virtual method is unused but it is here to make sure - // that this object has a vtable. This object is used - // as the super class for objects that also have garbage - // collected mixins and having a virtual here makes sure - // that adjustment is needed both for marking and for isAlive - // checks. - virtual void VirtualMethod() {} - - protected: - char payload[64]; -}; - -class LargeHeapObject final : public GarbageCollected<LargeHeapObject> { - public: - LargeHeapObject() { int_wrapper_ = MakeGarbageCollected<IntWrapper>(23); } - ~LargeHeapObject() { destructor_calls_++; } - - char Get(size_t i) { return data_[i]; } - void Set(size_t i, char c) { data_[i] = c; } - size_t length() { return kLength; } - void Trace(Visitor* visitor) const { visitor->Trace(int_wrapper_); } - static int destructor_calls_; - - private: - static const size_t kLength = 1024 * 1024; - Member<IntWrapper> int_wrapper_; - char data_[kLength]; -}; -int LargeHeapObject::destructor_calls_ = 0; - -void ExpectObjectMarkedAndUnmark(MarkingWorklist* worklist, void* expected) { - MarkingItem item; - CHECK(worklist->Pop(0, &item)); - CHECK_EQ(expected, item.base_object_payload); - HeapObjectHeader* header = - HeapObjectHeader::FromPayload(item.base_object_payload); - CHECK(header->IsMarked()); - header->Unmark(); - CHECK(worklist->IsGlobalEmpty()); -} -} // namespace - -TEST_F(HeapInternalsTest, CheckAndMarkPointer) { - // This test ensures that conservative marking primitives can use any address - // contained within an object to mark the corresponding object. - - ThreadHeap& heap = ThreadState::Current()->Heap(); - ClearOutOldGarbage(); - - Vector<Address> object_addresses; - Vector<Address> end_addresses; - for (int i = 0; i < 10; i++) { - auto* object = MakeGarbageCollected<SimpleObject>(); - Address object_address = reinterpret_cast<Address>(object); - object_addresses.push_back(object_address); - end_addresses.push_back(object_address + sizeof(SimpleObject) - 1); - } - Address large_object_address = - reinterpret_cast<Address>(MakeGarbageCollected<LargeHeapObject>()); - Address large_object_end_address = - large_object_address + sizeof(LargeHeapObject) - 1; - - { - TestGCScope scope(BlinkGC::kHeapPointersOnStack); - MarkingVisitor visitor(ThreadState::Current(), - MarkingVisitor::kGlobalMarking); - // Record marking speed as counter generation requires valid marking timings - // for heaps >1MB. - ThreadHeapStatsCollector::Scope stats_scope( - heap.stats_collector(), - ThreadHeapStatsCollector::kAtomicPauseMarkTransitiveClosure); - - // Conservative marker should find the interesting objects by using anything - // between object start and end. - MarkingWorklist* worklist = heap.GetMarkingWorklist(); - CHECK(worklist->IsGlobalEmpty()); - for (wtf_size_t i = 0; i < object_addresses.size(); i++) { - heap.CheckAndMarkPointer(&visitor, object_addresses[i]); - ExpectObjectMarkedAndUnmark(worklist, object_addresses[i]); - heap.CheckAndMarkPointer(&visitor, end_addresses[i]); - ExpectObjectMarkedAndUnmark(worklist, object_addresses[i]); - } - heap.CheckAndMarkPointer(&visitor, large_object_address); - ExpectObjectMarkedAndUnmark(worklist, large_object_address); - heap.CheckAndMarkPointer(&visitor, large_object_end_address); - ExpectObjectMarkedAndUnmark(worklist, large_object_address); - } - - // This forces a GC without stack scanning which results in the objects - // being collected. This will also rebuild the above mentioned freelists, - // however we don't rely on that below since we don't have any allocations. - ClearOutOldGarbage(); - - { - TestGCScope scope(BlinkGC::kHeapPointersOnStack); - MarkingVisitor visitor(ThreadState::Current(), - MarkingVisitor::kGlobalMarking); - // Record marking speed as counter generation requires valid marking timings - // for heaps >1MB. - ThreadHeapStatsCollector::Scope stats_scope( - heap.stats_collector(), - ThreadHeapStatsCollector::kAtomicPauseMarkTransitiveClosure); - - // After collecting all interesting objects the conservative marker should - // not find them anymore. - MarkingWorklist* worklist = heap.GetMarkingWorklist(); - CHECK(worklist->IsGlobalEmpty()); - for (wtf_size_t i = 0; i < object_addresses.size(); i++) { - heap.CheckAndMarkPointer(&visitor, object_addresses[i]); - CHECK(worklist->IsGlobalEmpty()); - heap.CheckAndMarkPointer(&visitor, end_addresses[i]); - CHECK(worklist->IsGlobalEmpty()); - } - heap.CheckAndMarkPointer(&visitor, large_object_address); - CHECK(worklist->IsGlobalEmpty()); - heap.CheckAndMarkPointer(&visitor, large_object_end_address); - CHECK(worklist->IsGlobalEmpty()); - } -} - -TEST_F(HeapInternalsTest, LazySweepingLargeObjectPages) { - // Disable concurrent sweeping to check lazy sweeping on allocation. - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndDisableFeature( - blink::features::kBlinkHeapConcurrentSweeping); - - ClearOutOldGarbage(); - - // Create free lists that can be reused for IntWrappers created in - // MakeGarbageCollected<LargeHeapObject>(). - Persistent<IntWrapper> p1 = MakeGarbageCollected<IntWrapper>(1); - for (int i = 0; i < 100; i++) { - MakeGarbageCollected<IntWrapper>(i); - } - Persistent<IntWrapper> p2 = MakeGarbageCollected<IntWrapper>(2); - PreciselyCollectGarbage(); - PreciselyCollectGarbage(); - - LargeHeapObject::destructor_calls_ = 0; - EXPECT_EQ(0, LargeHeapObject::destructor_calls_); - for (int i = 0; i < 10; i++) - MakeGarbageCollected<LargeHeapObject>(); - ThreadState::Current()->CollectGarbageForTesting( - BlinkGC::CollectionType::kMajor, BlinkGC::kNoHeapPointersOnStack, - BlinkGC::kAtomicMarking, BlinkGC::kConcurrentAndLazySweeping, - BlinkGC::GCReason::kForcedGCForTesting); - EXPECT_EQ(0, LargeHeapObject::destructor_calls_); - for (int i = 0; i < 10; i++) { - MakeGarbageCollected<LargeHeapObject>(); - EXPECT_EQ(i + 1, LargeHeapObject::destructor_calls_); - } - MakeGarbageCollected<LargeHeapObject>(); - MakeGarbageCollected<LargeHeapObject>(); - EXPECT_EQ(10, LargeHeapObject::destructor_calls_); - ThreadState::Current()->CollectGarbageForTesting( - BlinkGC::CollectionType::kMajor, BlinkGC::kNoHeapPointersOnStack, - BlinkGC::kAtomicMarking, BlinkGC::kConcurrentAndLazySweeping, - BlinkGC::GCReason::kForcedGCForTesting); - EXPECT_EQ(10, LargeHeapObject::destructor_calls_); - PreciselyCollectGarbage(); - EXPECT_EQ(22, LargeHeapObject::destructor_calls_); -} - -namespace { -class Mixin : public GarbageCollectedMixin { - public: - void Trace(Visitor* visitor) const override {} - - virtual char GetPayload(int i) { return padding_[i]; } - - protected: - int padding_[8]; -}; - -class UseMixin : public SimpleObject, public Mixin { - public: - UseMixin() { - // Verify that WTF::IsGarbageCollectedType<> works as expected for mixins. - static_assert(WTF::IsGarbageCollectedType<UseMixin>::value, - "IsGarbageCollectedType<> sanity check failed for GC mixin."); - trace_count_ = 0; - } - - static int trace_count_; - void Trace(Visitor* visitor) const override { - SimpleObject::Trace(visitor); - Mixin::Trace(visitor); - ++trace_count_; - } -}; -int UseMixin::trace_count_ = 0; -} // namespace - -TEST_F(HeapInternalsTest, NeedsAdjustPointer) { - // class Mixin : public GarbageCollectedMixin {}; - static_assert(NeedsAdjustPointer<Mixin>::value, - "A Mixin pointer needs adjustment"); - static_assert(NeedsAdjustPointer<const Mixin>::value, - "A const Mixin pointer needs adjustment"); - - // class SimpleObject : public GarbageCollected<SimpleObject> {}; - static_assert(!NeedsAdjustPointer<SimpleObject>::value, - "A SimpleObject pointer does not need adjustment"); - static_assert(!NeedsAdjustPointer<const SimpleObject>::value, - "A const SimpleObject pointer does not need adjustment"); - - // class UseMixin : public SimpleObject, public Mixin {}; - static_assert(!NeedsAdjustPointer<UseMixin>::value, - "A UseMixin pointer does not need adjustment"); - static_assert(!NeedsAdjustPointer<const UseMixin>::value, - "A const UseMixin pointer does not need adjustment"); -} - -namespace { -class DeepEagerly final : public GarbageCollected<DeepEagerly> { - public: - explicit DeepEagerly(DeepEagerly* next) : next_(next) {} - - void Trace(Visitor* visitor) const { - int calls = ++s_trace_calls_; - if (s_trace_lazy_ <= 2) - visitor->Trace(next_); - if (s_trace_calls_ == calls) - s_trace_lazy_++; - } - - Member<DeepEagerly> next_; - - static int s_trace_calls_; - static int s_trace_lazy_; -}; -int DeepEagerly::s_trace_calls_ = 0; -int DeepEagerly::s_trace_lazy_ = 0; -} // namespace - -TEST_F(HeapInternalsTest, TraceDeepEagerly) { -// The allocation & GC overhead is considerable for this test, -// straining debug builds and lower-end targets too much to be -// worth running. -#if !DCHECK_IS_ON() && !defined(OS_ANDROID) - DeepEagerly* obj = nullptr; - for (int i = 0; i < 10000000; i++) - obj = MakeGarbageCollected<DeepEagerly>(obj); - - Persistent<DeepEagerly> persistent(obj); - PreciselyCollectGarbage(); - - // Verify that the DeepEagerly chain isn't completely unravelled - // by performing eager trace() calls, but the explicit mark - // stack is switched once some nesting limit is exceeded. - EXPECT_GT(DeepEagerly::s_trace_lazy_, 2); -#endif -} - -#if defined(ADDRESS_SANITIZER) -TEST_F(HeapInternalsTest, SuccessfulUnsanitizedAccessToObjectHeader) { - auto* ptr = MakeGarbageCollected<IntWrapper>(1); - HeapObjectHeader* header = HeapObjectHeader::FromPayload(ptr); - auto* low = reinterpret_cast<uint16_t*>(header); - volatile uint16_t half = internal::AsUnsanitizedAtomic(low)->load(); - internal::AsUnsanitizedAtomic(low)->store(half); -} - -TEST(HeapInternalsDeathTest, DieOnPoisonedObjectHeaderAccess) { - auto* ptr = MakeGarbageCollected<IntWrapper>(1); - HeapObjectHeader* header = HeapObjectHeader::FromPayload(ptr); - auto* low = reinterpret_cast<uint16_t*>(header); - auto access = [low] { - volatile uint16_t half = WTF::AsAtomicPtr(low)->load(); - WTF::AsAtomicPtr(low)->store(half); - }; - EXPECT_DEATH(access(), ""); -} -#endif // ADDRESS_SANITIZER - -namespace { -class LargeMixin : public GarbageCollected<LargeMixin>, public Mixin { - protected: - char data[65536]; -}; -} // namespace - -TEST(HeapInternalsDeathTest, LargeGarbageCollectedMixin) { - EXPECT_DEATH(MakeGarbageCollected<LargeMixin>(AdditionalBytes(1)), ""); -} - -namespace { -class PreFinalizerAllocationForbidden - : public GarbageCollected<PreFinalizerAllocationForbidden> { - USING_PRE_FINALIZER(PreFinalizerAllocationForbidden, Dispose); - - public: - void Dispose() { - EXPECT_FALSE(ThreadState::Current()->IsAllocationAllowed()); -#if DCHECK_IS_ON() - EXPECT_DEATH(MakeGarbageCollected<IntWrapper>(1), ""); -#endif // DCHECK_IS_ON() - } - - void Trace(Visitor* visitor) const {} -}; -} // namespace - -TEST(HeapInternalsDeathTest, PreFinalizerAllocationForbidden) { - MakeGarbageCollected<PreFinalizerAllocationForbidden>(); - TestSupportingGC::PreciselyCollectGarbage(); -} - -namespace { -class Bar : public GarbageCollected<Bar> { - public: - Bar() : magic_(kMagic) { live_++; } - - virtual ~Bar() { - EXPECT_TRUE(magic_ == kMagic); - magic_ = 0; - live_--; - } - bool HasBeenFinalized() const { return !magic_; } - - virtual void Trace(Visitor* visitor) const {} - static unsigned live_; - - protected: - static const int kMagic = 1337; - int magic_; -}; - -unsigned Bar::live_ = 0; - -class Bars final : public Bar { - public: - Bars() { - for (auto& bar : bars_) { - bar = MakeGarbageCollected<Bar>(); - width_++; - } - } - - void Trace(Visitor* visitor) const override { - Bar::Trace(visitor); - for (unsigned i = 0; i < width_; i++) - visitor->Trace(bars_[i]); - } - - unsigned GetWidth() const { return width_; } - - static const unsigned kWidth = 7500; - - private: - unsigned width_ = 0; - Member<Bar> bars_[kWidth]; -}; -} // namespace - -TEST_F(HeapInternalsTest, WideTest) { - ClearOutOldGarbage(); - Bar::live_ = 0; - { - auto* bars = MakeGarbageCollected<Bars>(); - unsigned width = Bars::kWidth; - EXPECT_EQ(width + 1, Bar::live_); - ConservativelyCollectGarbage(); - EXPECT_EQ(width + 1, Bar::live_); - // Use bars here to make sure that it will be on the stack - // for the conservative stack scan to find. - EXPECT_EQ(width, bars->GetWidth()); - } - EXPECT_EQ(Bars::kWidth + 1, Bar::live_); - PreciselyCollectGarbage(); - EXPECT_EQ(0u, Bar::live_); -} - -namespace { -// The accounting for memory includes the memory used by rounding up object -// sizes. This is done in a different way on 32 bit and 64 bit, so we have to -// have some slack in the tests. -template <typename T> -void CheckWithSlack(T expected, T actual, int slack) { - EXPECT_LE(expected, actual); - EXPECT_GE((intptr_t)expected + slack, (intptr_t)actual); -} -} // namespace - -TEST_F(HeapInternalsTest, LargeHeapObjects) { - ThreadHeap& heap = ThreadState::Current()->Heap(); - ClearOutOldGarbage(); - size_t initial_object_payload_size = heap.ObjectPayloadSizeForTesting(); - size_t initial_allocated_space = - heap.stats_collector()->allocated_space_bytes(); - IntWrapper::destructor_calls_ = 0; - LargeHeapObject::destructor_calls_ = 0; - { - int slack = - 8; // LargeHeapObject points to an IntWrapper that is also allocated. - Persistent<LargeHeapObject> object = - MakeGarbageCollected<LargeHeapObject>(); -#if DCHECK_IS_ON() - DCHECK(ThreadState::Current()->Heap().FindPageFromAddress(object)); - DCHECK(ThreadState::Current()->Heap().FindPageFromAddress( - reinterpret_cast<char*>(object.Get()) + sizeof(LargeHeapObject) - 1)); -#endif - ClearOutOldGarbage(); - size_t after_allocation = heap.stats_collector()->allocated_space_bytes(); - { - object->Set(0, 'a'); - EXPECT_EQ('a', object->Get(0)); - object->Set(object->length() - 1, 'b'); - EXPECT_EQ('b', object->Get(object->length() - 1)); - size_t expected_large_heap_object_payload_size = - ThreadHeap::AllocationSizeFromSize(sizeof(LargeHeapObject)) - - sizeof(HeapObjectHeader); - size_t expected_object_payload_size = - expected_large_heap_object_payload_size + sizeof(IntWrapper); - size_t actual_object_payload_size = - heap.ObjectPayloadSizeForTesting() - initial_object_payload_size; - CheckWithSlack(expected_object_payload_size, actual_object_payload_size, - slack); - // There is probably space for the IntWrapper in a heap page without - // allocating extra pages. However, the IntWrapper allocation might cause - // the addition of a heap page. - size_t large_object_allocation_size = - sizeof(LargeObjectPage) + expected_large_heap_object_payload_size; - size_t allocated_space_lower_bound = - initial_allocated_space + large_object_allocation_size; - size_t allocated_space_upper_bound = - allocated_space_lower_bound + slack + kBlinkPageSize; - EXPECT_LE(allocated_space_lower_bound, after_allocation); - EXPECT_LE(after_allocation, allocated_space_upper_bound); - EXPECT_EQ(0, IntWrapper::destructor_calls_); - EXPECT_EQ(0, LargeHeapObject::destructor_calls_); - for (int i = 0; i < 10; i++) - object = MakeGarbageCollected<LargeHeapObject>(); - } - ClearOutOldGarbage(); - EXPECT_EQ(after_allocation, - heap.stats_collector()->allocated_space_bytes()); - EXPECT_EQ(10, IntWrapper::destructor_calls_); - EXPECT_EQ(10, LargeHeapObject::destructor_calls_); - } - ClearOutOldGarbage(); - EXPECT_TRUE(initial_object_payload_size == - heap.ObjectPayloadSizeForTesting()); - EXPECT_EQ(initial_allocated_space, - heap.stats_collector()->allocated_space_bytes()); - EXPECT_EQ(11, IntWrapper::destructor_calls_); - EXPECT_EQ(11, LargeHeapObject::destructor_calls_); - PreciselyCollectGarbage(); -} - -namespace { -class MixinA : public GarbageCollectedMixin { - public: - MixinA() : obj_(MakeGarbageCollected<IntWrapper>(100)) {} - void Trace(Visitor* visitor) const override { - trace_count_++; - visitor->Trace(obj_); - } - - static int trace_count_; - - Member<IntWrapper> obj_; -}; - -int MixinA::trace_count_ = 0; - -class MixinB : public GarbageCollectedMixin { - public: - MixinB() : obj_(MakeGarbageCollected<IntWrapper>(101)) {} - void Trace(Visitor* visitor) const override { visitor->Trace(obj_); } - Member<IntWrapper> obj_; -}; - -class MultipleMixins : public GarbageCollected<MultipleMixins>, - public MixinA, - public MixinB { - public: - MultipleMixins() : obj_(MakeGarbageCollected<IntWrapper>(102)) {} - void Trace(Visitor* visitor) const override { - visitor->Trace(obj_); - MixinA::Trace(visitor); - MixinB::Trace(visitor); - } - Member<IntWrapper> obj_; -}; - -static const bool kIsMixinTrue = IsGarbageCollectedMixin<MultipleMixins>::value; -static const bool kIsMixinFalse = IsGarbageCollectedMixin<IntWrapper>::value; -} // namespace - -TEST_F(HeapInternalsTest, MultipleMixins) { - EXPECT_TRUE(kIsMixinTrue); - EXPECT_FALSE(kIsMixinFalse); - - ClearOutOldGarbage(); - IntWrapper::destructor_calls_ = 0; - MultipleMixins* obj = MakeGarbageCollected<MultipleMixins>(); - { - Persistent<MixinA> a = obj; - PreciselyCollectGarbage(); - EXPECT_EQ(0, IntWrapper::destructor_calls_); - } - { - Persistent<MixinB> b = obj; - PreciselyCollectGarbage(); - EXPECT_EQ(0, IntWrapper::destructor_calls_); - } - PreciselyCollectGarbage(); - EXPECT_EQ(3, IntWrapper::destructor_calls_); -} - -namespace { -class DerivedMultipleMixins : public MultipleMixins { - public: - DerivedMultipleMixins() : obj_(MakeGarbageCollected<IntWrapper>(103)) {} - - void Trace(Visitor* visitor) const override { - trace_called_++; - visitor->Trace(obj_); - MultipleMixins::Trace(visitor); - } - - static int trace_called_; - - private: - Member<IntWrapper> obj_; -}; -int DerivedMultipleMixins::trace_called_ = 0; -} // namespace - -TEST_F(HeapInternalsTest, DerivedMultipleMixins) { - ClearOutOldGarbage(); - IntWrapper::destructor_calls_ = 0; - DerivedMultipleMixins::trace_called_ = 0; - - DerivedMultipleMixins* obj = MakeGarbageCollected<DerivedMultipleMixins>(); - { - Persistent<MixinA> a = obj; - PreciselyCollectGarbage(); - EXPECT_EQ(0, IntWrapper::destructor_calls_); - EXPECT_LT(0, DerivedMultipleMixins::trace_called_); - } - { - Persistent<MixinB> b = obj; - PreciselyCollectGarbage(); - EXPECT_EQ(0, IntWrapper::destructor_calls_); - EXPECT_LT(0, DerivedMultipleMixins::trace_called_); - } - PreciselyCollectGarbage(); - EXPECT_EQ(4, IntWrapper::destructor_calls_); -} - -namespace { -static bool AllocateAndReturnBool() { - TestSupportingGC::ConservativelyCollectGarbage(); - return true; -} - -class AllocInSuperConstructorArgumentSuper - : public GarbageCollected<AllocInSuperConstructorArgumentSuper> { - public: - explicit AllocInSuperConstructorArgumentSuper(bool value) : value_(value) {} - virtual ~AllocInSuperConstructorArgumentSuper() = default; - virtual void Trace(Visitor* visitor) const {} - bool Value() { return value_; } - - private: - bool value_; -}; - -class AllocInSuperConstructorArgument - : public AllocInSuperConstructorArgumentSuper { - public: - AllocInSuperConstructorArgument() - : AllocInSuperConstructorArgumentSuper(AllocateAndReturnBool()) {} -}; -} // namespace - -// Regression test for crbug.com/404511. Tests conservative marking of -// an object with an uninitialized vtable. -TEST_F(HeapInternalsTest, AllocationInSuperConstructorArgument) { - AllocInSuperConstructorArgument* object = - MakeGarbageCollected<AllocInSuperConstructorArgument>(); - EXPECT_TRUE(object); - ThreadState::Current()->CollectAllGarbageForTesting(); -} - -namespace { -class TestMixinAllocationA : public GarbageCollected<TestMixinAllocationA>, - public GarbageCollectedMixin { - public: - TestMixinAllocationA() = default; - - void Trace(Visitor* visitor) const override {} -}; - -class TestMixinAllocationB : public TestMixinAllocationA { - public: - TestMixinAllocationB() - // Construct object during a mixin construction. - : a_(MakeGarbageCollected<TestMixinAllocationA>()) {} - - void Trace(Visitor* visitor) const override { - visitor->Trace(a_); - TestMixinAllocationA::Trace(visitor); - } - - private: - Member<TestMixinAllocationA> a_; -}; - -class TestMixinAllocationC final : public TestMixinAllocationB { - public: - TestMixinAllocationC() { DCHECK(!ThreadState::Current()->IsGCForbidden()); } - - void Trace(Visitor* visitor) const override { - TestMixinAllocationB::Trace(visitor); - } -}; -} // namespace - -TEST_F(HeapInternalsTest, NestedMixinConstruction) { - TestMixinAllocationC* object = MakeGarbageCollected<TestMixinAllocationC>(); - EXPECT_TRUE(object); -} - -TEST_F(HeapInternalsTest, IsHeapObjectAliveForConstPointer) { - // See http://crbug.com/661363. - auto* object = MakeGarbageCollected<SimpleObject>(); - HeapObjectHeader* header = HeapObjectHeader::FromPayload(object); - LivenessBroker broker = internal::LivenessBrokerFactory::Create(); - EXPECT_TRUE(header->TryMark()); - EXPECT_TRUE(broker.IsHeapObjectAlive(object)); - const SimpleObject* const_object = const_cast<const SimpleObject*>(object); - EXPECT_TRUE(broker.IsHeapObjectAlive(const_object)); -} - -namespace { -// This test class served a more important role while Blink -// was transitioned over to using Oilpan. That required classes -// that were hybrid, both ref-counted and on the Oilpan heap -// (the RefCountedGarbageCollected<> class providing just that.) -// -// There's no current need for having a ref-counted veneer on -// top of a GCed class, but we preserve it here to exercise the -// implementation technique that it used -- keeping an internal -// "keep alive" persistent reference that is set & cleared across -// ref-counting operations. -// -class RefCountedAndGarbageCollected final - : public GarbageCollected<RefCountedAndGarbageCollected> { - public: - RefCountedAndGarbageCollected() : keep_alive_(PERSISTENT_FROM_HERE) {} - ~RefCountedAndGarbageCollected() { ++destructor_calls_; } - - void AddRef() { - if (UNLIKELY(!ref_count_)) { -#if DCHECK_IS_ON() - DCHECK(ThreadState::Current()->Heap().FindPageFromAddress( - reinterpret_cast<Address>(this))); -#endif - keep_alive_ = this; - } - ++ref_count_; - } - - void Release() { - DCHECK_GT(ref_count_, 0); - if (!--ref_count_) - keep_alive_.Clear(); - } - - void Trace(Visitor* visitor) const {} - - static int destructor_calls_; - - private: - int ref_count_ = 0; - SelfKeepAlive<RefCountedAndGarbageCollected> keep_alive_; -}; -int RefCountedAndGarbageCollected::destructor_calls_ = 0; - -class SuperClass; - -class PointsBack final : public GarbageCollected<PointsBack> { - public: - PointsBack() : back_pointer_(nullptr) { ++alive_count_; } - ~PointsBack() { --alive_count_; } - - void SetBackPointer(SuperClass* back_pointer) { - back_pointer_ = back_pointer; - } - - SuperClass* BackPointer() const { return back_pointer_; } - - void Trace(Visitor* visitor) const { visitor->Trace(back_pointer_); } - - static int alive_count_; - - private: - WeakMember<SuperClass> back_pointer_; -}; -int PointsBack::alive_count_ = 0; - -class SuperClass : public GarbageCollected<SuperClass> { - public: - explicit SuperClass(PointsBack* points_back) : points_back_(points_back) { - points_back_->SetBackPointer(this); - ++alive_count_; - } - virtual ~SuperClass() { --alive_count_; } - - void DoStuff(SuperClass* target, - PointsBack* points_back, - int super_class_count) { - TestSupportingGC::ConservativelyCollectGarbage(); - EXPECT_EQ(points_back, target->GetPointsBack()); - EXPECT_EQ(super_class_count, SuperClass::alive_count_); - } - - virtual void Trace(Visitor* visitor) const { visitor->Trace(points_back_); } - - PointsBack* GetPointsBack() const { return points_back_.Get(); } - - static int alive_count_; - - private: - Member<PointsBack> points_back_; -}; - -int SuperClass::alive_count_ = 0; -class SubData final : public GarbageCollected<SubData> { - public: - SubData() { ++alive_count_; } - ~SubData() { --alive_count_; } - - void Trace(Visitor* visitor) const {} - - static int alive_count_; -}; -int SubData::alive_count_ = 0; - -class SubClass : public SuperClass { - public: - explicit SubClass(PointsBack* points_back) - : SuperClass(points_back), data_(MakeGarbageCollected<SubData>()) { - ++alive_count_; - } - ~SubClass() override { --alive_count_; } - - void Trace(Visitor* visitor) const override { - visitor->Trace(data_); - SuperClass::Trace(visitor); - } - - static int alive_count_; - - private: - Member<SubData> data_; -}; -int SubClass::alive_count_ = 0; -} // namespace - -TEST_F(HeapInternalsTest, Transition) { - { - RefCountedAndGarbageCollected::destructor_calls_ = 0; - Persistent<RefCountedAndGarbageCollected> ref_counted = - MakeGarbageCollected<RefCountedAndGarbageCollected>(); - PreciselyCollectGarbage(); - EXPECT_EQ(0, RefCountedAndGarbageCollected::destructor_calls_); - } - PreciselyCollectGarbage(); - EXPECT_EQ(1, RefCountedAndGarbageCollected::destructor_calls_); - RefCountedAndGarbageCollected::destructor_calls_ = 0; - - Persistent<PointsBack> points_back1 = MakeGarbageCollected<PointsBack>(); - Persistent<PointsBack> points_back2 = MakeGarbageCollected<PointsBack>(); - Persistent<SuperClass> super_class = - MakeGarbageCollected<SuperClass>(points_back1); - Persistent<SubClass> sub_class = MakeGarbageCollected<SubClass>(points_back2); - EXPECT_EQ(2, PointsBack::alive_count_); - EXPECT_EQ(2, SuperClass::alive_count_); - EXPECT_EQ(1, SubClass::alive_count_); - EXPECT_EQ(1, SubData::alive_count_); - - PreciselyCollectGarbage(); - EXPECT_EQ(0, RefCountedAndGarbageCollected::destructor_calls_); - EXPECT_EQ(2, PointsBack::alive_count_); - EXPECT_EQ(2, SuperClass::alive_count_); - EXPECT_EQ(1, SubClass::alive_count_); - EXPECT_EQ(1, SubData::alive_count_); - - super_class->DoStuff(super_class.Release(), points_back1.Get(), 2); - PreciselyCollectGarbage(); - EXPECT_EQ(2, PointsBack::alive_count_); - EXPECT_EQ(1, SuperClass::alive_count_); - EXPECT_EQ(1, SubClass::alive_count_); - EXPECT_EQ(1, SubData::alive_count_); - EXPECT_EQ(nullptr, points_back1->BackPointer()); - - points_back1.Release(); - PreciselyCollectGarbage(); - EXPECT_EQ(1, PointsBack::alive_count_); - EXPECT_EQ(1, SuperClass::alive_count_); - EXPECT_EQ(1, SubClass::alive_count_); - EXPECT_EQ(1, SubData::alive_count_); - - sub_class->DoStuff(sub_class.Release(), points_back2.Get(), 1); - PreciselyCollectGarbage(); - EXPECT_EQ(1, PointsBack::alive_count_); - EXPECT_EQ(0, SuperClass::alive_count_); - EXPECT_EQ(0, SubClass::alive_count_); - EXPECT_EQ(0, SubData::alive_count_); - EXPECT_EQ(nullptr, points_back2->BackPointer()); - - points_back2.Release(); - PreciselyCollectGarbage(); - EXPECT_EQ(0, PointsBack::alive_count_); - EXPECT_EQ(0, SuperClass::alive_count_); - EXPECT_EQ(0, SubClass::alive_count_); - EXPECT_EQ(0, SubData::alive_count_); - - EXPECT_TRUE(super_class == sub_class); -} - -namespace { -class DynamicallySizedObject : public GarbageCollected<DynamicallySizedObject> { - public: - static DynamicallySizedObject* Create(size_t size) { - return MakeGarbageCollected<DynamicallySizedObject>(AdditionalBytes( - base::checked_cast<wtf_size_t>(size - sizeof(DynamicallySizedObject)))); - } - - uint8_t Get(int i) { return *(reinterpret_cast<uint8_t*>(this) + i); } - - void Trace(Visitor* visitor) const {} -}; -} // namespace - -TEST_F(HeapInternalsTest, BasicFunctionality) { - ThreadHeap& heap = ThreadState::Current()->Heap(); - ClearOutOldGarbage(); - size_t initial_object_payload_size = heap.ObjectPayloadSizeForTesting(); - { - wtf_size_t slack = 0; - - // When the test starts there may already have been leaked some memory - // on the heap, so we establish a base line. - size_t base_level = initial_object_payload_size; - bool test_pages_allocated = !base_level; - if (test_pages_allocated) - EXPECT_EQ(0ul, heap.stats_collector()->allocated_space_bytes()); - - // This allocates objects on the general heap which should add a page of - // memory. - DynamicallySizedObject* alloc32 = DynamicallySizedObject::Create(32); - slack += 4; - memset(alloc32, 40, 32); - DynamicallySizedObject* alloc64 = DynamicallySizedObject::Create(64); - slack += 4; - memset(alloc64, 27, 64); - - size_t total = 96; - - CheckWithSlack(base_level + total, heap.ObjectPayloadSizeForTesting(), - slack); - if (test_pages_allocated) { - EXPECT_EQ(kBlinkPageSize * 2, - heap.stats_collector()->allocated_space_bytes()); - } - - EXPECT_EQ(alloc32->Get(0), 40); - EXPECT_EQ(alloc32->Get(31), 40); - EXPECT_EQ(alloc64->Get(0), 27); - EXPECT_EQ(alloc64->Get(63), 27); - - ConservativelyCollectGarbage(); - - EXPECT_EQ(alloc32->Get(0), 40); - EXPECT_EQ(alloc32->Get(31), 40); - EXPECT_EQ(alloc64->Get(0), 27); - EXPECT_EQ(alloc64->Get(63), 27); - } - - ClearOutOldGarbage(); - size_t total = 0; - wtf_size_t slack = 0; - size_t base_level = heap.ObjectPayloadSizeForTesting(); - bool test_pages_allocated = !base_level; - if (test_pages_allocated) - EXPECT_EQ(0ul, heap.stats_collector()->allocated_space_bytes()); - - size_t big = 1008; - Persistent<DynamicallySizedObject> big_area = - DynamicallySizedObject::Create(big); - total += big; - slack += 4; - - size_t persistent_count = 0; - const size_t kNumPersistents = 100000; - Persistent<DynamicallySizedObject>* persistents[kNumPersistents]; - - for (int i = 0; i < 1000; i++) { - size_t size = 128 + i * 8; - total += size; - persistents[persistent_count++] = new Persistent<DynamicallySizedObject>( - DynamicallySizedObject::Create(size)); - slack += 4; - // The allocations in the loop may trigger GC with lazy sweeping. - if (ThreadState::Current()->IsSweepingInProgress()) - ThreadState::Current()->CompleteSweep(); - CheckWithSlack(base_level + total, heap.ObjectPayloadSizeForTesting(), - slack); - if (test_pages_allocated) { - EXPECT_EQ(0ul, heap.stats_collector()->allocated_space_bytes() & - (kBlinkPageSize - 1)); - } - } - - { - DynamicallySizedObject* alloc32b(DynamicallySizedObject::Create(32)); - slack += 4; - memset(alloc32b, 40, 32); - DynamicallySizedObject* alloc64b(DynamicallySizedObject::Create(64)); - slack += 4; - memset(alloc64b, 27, 64); - EXPECT_TRUE(alloc32b != alloc64b); - - total += 96; - CheckWithSlack(base_level + total, heap.ObjectPayloadSizeForTesting(), - slack); - if (test_pages_allocated) { - EXPECT_EQ(0ul, heap.stats_collector()->allocated_space_bytes() & - (kBlinkPageSize - 1)); - } - } - - ClearOutOldGarbage(); - total -= 96; - slack -= 8; - if (test_pages_allocated) { - EXPECT_EQ(0ul, heap.stats_collector()->allocated_space_bytes() & - (kBlinkPageSize - 1)); - } - - // Clear the persistent, so that the big area will be garbage collected. - big_area.Release(); - ClearOutOldGarbage(); - - total -= big; - slack -= 4; - CheckWithSlack(base_level + total, heap.ObjectPayloadSizeForTesting(), slack); - if (test_pages_allocated) { - EXPECT_EQ(0ul, heap.stats_collector()->allocated_space_bytes() & - (kBlinkPageSize - 1)); - } - - CheckWithSlack(base_level + total, heap.ObjectPayloadSizeForTesting(), slack); - if (test_pages_allocated) { - EXPECT_EQ(0ul, heap.stats_collector()->allocated_space_bytes() & - (kBlinkPageSize - 1)); - } - - for (size_t i = 0; i < persistent_count; i++) { - delete persistents[i]; - persistents[i] = nullptr; - } -} - -namespace { -class HeapAllocatedArray : public GarbageCollected<HeapAllocatedArray> { - public: - HeapAllocatedArray() { - for (int i = 0; i < kArraySize; ++i) { - array_[i] = i % 128; - } - } - - int8_t at(size_t i) { return array_[i]; } - void Trace(Visitor* visitor) const {} - - private: - static const int kArraySize = 1000; - int8_t array_[kArraySize]; -}; -} // namespace - -TEST_F(HeapInternalsTest, SimpleAllocation) { - ThreadHeap& heap = ThreadState::Current()->Heap(); - ClearOutOldGarbage(); - EXPECT_EQ(0ul, heap.ObjectPayloadSizeForTesting()); - - // Allocate an object in the heap. - HeapAllocatedArray* array = MakeGarbageCollected<HeapAllocatedArray>(); - EXPECT_TRUE(heap.ObjectPayloadSizeForTesting() >= sizeof(HeapAllocatedArray)); - - // Sanity check of the contents in the heap. - EXPECT_EQ(0, array->at(0)); - EXPECT_EQ(42, array->at(42)); - EXPECT_EQ(0, array->at(128)); - EXPECT_EQ(999 % 128, array->at(999)); -} - -namespace { -class TraceCounter final : public GarbageCollected<TraceCounter> { - public: - void Trace(Visitor* visitor) const { trace_count_++; } - int TraceCount() const { return trace_count_; } - - private: - mutable int trace_count_ = 0; -}; - -class ClassWithMember : public GarbageCollected<ClassWithMember> { - public: - ClassWithMember() : trace_counter_(MakeGarbageCollected<TraceCounter>()) {} - - void Trace(Visitor* visitor) const { visitor->Trace(trace_counter_); } - int TraceCount() const { return trace_counter_->TraceCount(); } - - private: - Member<TraceCounter> trace_counter_; -}; -} // namespace - -TEST_F(HeapInternalsTest, SimplePersistent) { - Persistent<TraceCounter> trace_counter = MakeGarbageCollected<TraceCounter>(); - EXPECT_EQ(0, trace_counter->TraceCount()); - PreciselyCollectGarbage(); - int saved_trace_count = trace_counter->TraceCount(); - EXPECT_LT(0, saved_trace_count); - - Persistent<ClassWithMember> class_with_member = - MakeGarbageCollected<ClassWithMember>(); - EXPECT_EQ(0, class_with_member->TraceCount()); - PreciselyCollectGarbage(); - EXPECT_LT(0, class_with_member->TraceCount()); - EXPECT_LT(saved_trace_count, trace_counter->TraceCount()); -} - -namespace { -class SimpleFinalizedObject final - : public GarbageCollected<SimpleFinalizedObject> { - public: - SimpleFinalizedObject() = default; - ~SimpleFinalizedObject() { ++destructor_calls_; } - - static int destructor_calls_; - - void Trace(Visitor* visitor) const {} -}; -int SimpleFinalizedObject::destructor_calls_ = 0; -} // namespace - -TEST_F(HeapInternalsTest, SimpleFinalization) { - ClearOutOldGarbage(); - { - SimpleFinalizedObject::destructor_calls_ = 0; - Persistent<SimpleFinalizedObject> finalized = - MakeGarbageCollected<SimpleFinalizedObject>(); - EXPECT_EQ(0, SimpleFinalizedObject::destructor_calls_); - PreciselyCollectGarbage(); - EXPECT_EQ(0, SimpleFinalizedObject::destructor_calls_); - } - - PreciselyCollectGarbage(); - EXPECT_EQ(1, SimpleFinalizedObject::destructor_calls_); -} - -#if DCHECK_IS_ON() || defined(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER) -TEST_F(HeapInternalsTest, FreelistReuse) { - ClearOutOldGarbage(); - - for (int i = 0; i < 100; i++) - MakeGarbageCollected<IntWrapper>(i); - IntWrapper* p1 = MakeGarbageCollected<IntWrapper>(100); - PreciselyCollectGarbage(); - // In non-production builds, we delay reusing freed memory for at least - // one GC cycle. - for (int i = 0; i < 100; i++) { - IntWrapper* p2 = MakeGarbageCollected<IntWrapper>(i); - EXPECT_NE(p1, p2); - } - - PreciselyCollectGarbage(); - PreciselyCollectGarbage(); - // Now the freed memory in the first GC should be reused. - bool reused_memory_found = false; - for (int i = 0; i < 10000; i++) { - IntWrapper* p2 = MakeGarbageCollected<IntWrapper>(i); - if (p1 == p2) { - reused_memory_found = true; - break; - } - } - EXPECT_TRUE(reused_memory_found); -} -#endif - -TEST_F(HeapInternalsTest, LazySweepingPages) { - ClearOutOldGarbage(); - - SimpleFinalizedObject::destructor_calls_ = 0; - EXPECT_EQ(0, SimpleFinalizedObject::destructor_calls_); - for (int i = 0; i < 1000; i++) - MakeGarbageCollected<SimpleFinalizedObject>(); - ThreadState::Current()->CollectGarbageForTesting( - BlinkGC::CollectionType::kMajor, BlinkGC::kNoHeapPointersOnStack, - BlinkGC::kAtomicMarking, BlinkGC::kConcurrentAndLazySweeping, - BlinkGC::GCReason::kForcedGCForTesting); - EXPECT_EQ(0, SimpleFinalizedObject::destructor_calls_); - for (int i = 0; i < 10000; i++) - MakeGarbageCollected<SimpleFinalizedObject>(); - EXPECT_EQ(1000, SimpleFinalizedObject::destructor_calls_); - PreciselyCollectGarbage(); - EXPECT_EQ(11000, SimpleFinalizedObject::destructor_calls_); -} - -namespace { -class HeapTestSuperClass : public GarbageCollected<HeapTestSuperClass> { - public: - HeapTestSuperClass() = default; - virtual ~HeapTestSuperClass() { ++destructor_calls_; } - - static int destructor_calls_; - void Trace(Visitor* visitor) const {} -}; -int HeapTestSuperClass::destructor_calls_ = 0; - -class HeapTestOtherSuperClass { - public: - int payload; -}; - -class HeapTestSubClass : public HeapTestSuperClass, - public HeapTestOtherSuperClass { - static constexpr size_t kClassMagic = 0xABCDDBCA; - - public: - HeapTestSubClass() : magic_(kClassMagic) {} - ~HeapTestSubClass() override { - EXPECT_EQ(kClassMagic, magic_); - ++destructor_calls_; - } - - static int destructor_calls_; - - private: - const size_t magic_; -}; -int HeapTestSubClass::destructor_calls_ = 0; -constexpr size_t HeapTestSubClass::kClassMagic; -} // namespace - -TEST_F(HeapInternalsTest, Finalization) { - { - HeapTestSubClass::destructor_calls_ = 0; - HeapTestSuperClass::destructor_calls_ = 0; - auto* t1 = MakeGarbageCollected<HeapTestSubClass>(); - auto* t2 = MakeGarbageCollected<HeapTestSubClass>(); - auto* t3 = MakeGarbageCollected<HeapTestSuperClass>(); - // FIXME(oilpan): Ignore unused variables. - (void)t1; - (void)t2; - (void)t3; - } - // Nothing is marked so the GC should free everything and call - // the finalizer on all three objects. - PreciselyCollectGarbage(); - EXPECT_EQ(2, HeapTestSubClass::destructor_calls_); - EXPECT_EQ(3, HeapTestSuperClass::destructor_calls_); - // Destructors not called again when GCing again. - PreciselyCollectGarbage(); - EXPECT_EQ(2, HeapTestSubClass::destructor_calls_); - EXPECT_EQ(3, HeapTestSuperClass::destructor_calls_); -} - -namespace { -class IntNode : public GarbageCollected<IntNode> { - public: - template <typename T> - static void* AllocateObject(size_t size) { - ThreadState* state = ThreadState::Current(); - const char* type_name = WTF_HEAP_PROFILER_TYPE_NAME(IntNode); - return state->Heap().AllocateOnArenaIndex( - state, size, BlinkGC::kNodeArenaIndex, - GCInfoTrait<GCInfoFoldedType<IntNode>>::Index(), type_name); - } - - explicit IntNode(int i) : value_(i) {} - - static IntNode* Create(int i) { return MakeGarbageCollected<IntNode>(i); } - - void Trace(Visitor* visitor) const {} - - int Value() { return value_; } - - private: - int value_; -}; -} // namespace - -TEST_F(HeapInternalsTest, TypedArenaSanity) { - // We use TraceCounter for allocating an object on the general heap. - Persistent<TraceCounter> general_heap_object = - MakeGarbageCollected<TraceCounter>(); - Persistent<IntNode> typed_heap_object = IntNode::Create(0); - EXPECT_NE(PageFromObject(general_heap_object.Get()), - PageFromObject(typed_heap_object.Get())); -} - -TEST_F(HeapInternalsTest, NoAllocation) { - ThreadState* state = ThreadState::Current(); - EXPECT_TRUE(state->IsAllocationAllowed()); - { - // Disallow allocation - ThreadState::NoAllocationScope no_allocation_scope(state); - EXPECT_FALSE(state->IsAllocationAllowed()); - } - EXPECT_TRUE(state->IsAllocationAllowed()); -} - -namespace { -class Baz : public GarbageCollected<Baz> { - public: - explicit Baz(Bar* bar) : bar_(bar) {} - - void Trace(Visitor* visitor) const { visitor->Trace(bar_); } - - void Clear() { bar_.Release(); } - - // willFinalize is called by FinalizationObserver. - void WillFinalize() { EXPECT_TRUE(!bar_->HasBeenFinalized()); } - - private: - Member<Bar> bar_; -}; -} // namespace - -TEST_F(HeapInternalsTest, Members) { - ClearOutOldGarbage(); - Bar::live_ = 0; - { - Persistent<Baz> h1; - Persistent<Baz> h2; - { - h1 = MakeGarbageCollected<Baz>(MakeGarbageCollected<Bar>()); - PreciselyCollectGarbage(); - EXPECT_EQ(1u, Bar::live_); - h2 = MakeGarbageCollected<Baz>(MakeGarbageCollected<Bar>()); - PreciselyCollectGarbage(); - EXPECT_EQ(2u, Bar::live_); - } - PreciselyCollectGarbage(); - EXPECT_EQ(2u, Bar::live_); - h1->Clear(); - PreciselyCollectGarbage(); - EXPECT_EQ(1u, Bar::live_); - } - PreciselyCollectGarbage(); - EXPECT_EQ(0u, Bar::live_); -} - -namespace { -class Foo final : public Bar { - public: - explicit Foo(Bar* bar) : bar_(bar), points_to_foo_(false) {} - - explicit Foo(Foo* foo) : bar_(foo), points_to_foo_(true) {} - - void Trace(Visitor* visitor) const override { - Bar::Trace(visitor); - if (points_to_foo_) - visitor->Trace(static_cast<const Foo*>(bar_.Get())); - else - visitor->Trace(bar_); - } - - private: - const Member<Bar> bar_; - const bool points_to_foo_; -}; -} // namespace - -TEST_F(HeapInternalsTest, MarkTest) { - ClearOutOldGarbage(); - { - Bar::live_ = 0; - Persistent<Bar> bar = MakeGarbageCollected<Bar>(); -#if DCHECK_IS_ON() - DCHECK(ThreadState::Current()->Heap().FindPageFromAddress(bar)); -#endif - EXPECT_EQ(1u, Bar::live_); - { - auto* foo = MakeGarbageCollected<Foo>(bar); -#if DCHECK_IS_ON() - DCHECK(ThreadState::Current()->Heap().FindPageFromAddress(foo)); -#endif - EXPECT_EQ(2u, Bar::live_); - EXPECT_TRUE(reinterpret_cast<Address>(foo) != - reinterpret_cast<Address>(bar.Get())); - ConservativelyCollectGarbage(); - EXPECT_TRUE(foo != bar); // To make sure foo is kept alive. - EXPECT_EQ(2u, Bar::live_); - } - PreciselyCollectGarbage(); - EXPECT_EQ(1u, Bar::live_); - } - PreciselyCollectGarbage(); - EXPECT_EQ(0u, Bar::live_); -} - -TEST_F(HeapInternalsTest, DeepTest) { - ClearOutOldGarbage(); - const unsigned kDepth = 100000; - Bar::live_ = 0; - { - auto* bar = MakeGarbageCollected<Bar>(); -#if DCHECK_IS_ON() - DCHECK(ThreadState::Current()->Heap().FindPageFromAddress(bar)); -#endif - auto* foo = MakeGarbageCollected<Foo>(bar); -#if DCHECK_IS_ON() - DCHECK(ThreadState::Current()->Heap().FindPageFromAddress(foo)); -#endif - EXPECT_EQ(2u, Bar::live_); - for (unsigned i = 0; i < kDepth; i++) { - auto* foo2 = MakeGarbageCollected<Foo>(foo); - foo = foo2; -#if DCHECK_IS_ON() - DCHECK(ThreadState::Current()->Heap().FindPageFromAddress(foo)); -#endif - } - EXPECT_EQ(kDepth + 2, Bar::live_); - ConservativelyCollectGarbage(); - EXPECT_TRUE(foo != bar); // To make sure foo and bar are kept alive. - EXPECT_EQ(kDepth + 2, Bar::live_); - } - PreciselyCollectGarbage(); - EXPECT_EQ(0u, Bar::live_); -} - -namespace { -class ConstructorAllocation : public GarbageCollected<ConstructorAllocation> { - public: - ConstructorAllocation() { - int_wrapper_ = MakeGarbageCollected<IntWrapper>(42); - } - - void Trace(Visitor* visitor) const { visitor->Trace(int_wrapper_); } - - private: - Member<IntWrapper> int_wrapper_; -}; -} // namespace - -TEST_F(HeapInternalsTest, NestedAllocation) { - ThreadHeap& heap = ThreadState::Current()->Heap(); - ClearOutOldGarbage(); - size_t initial_object_payload_size = heap.ObjectPayloadSizeForTesting(); - { - Persistent<ConstructorAllocation> constructor_allocation = - MakeGarbageCollected<ConstructorAllocation>(); - } - ClearOutOldGarbage(); - size_t after_free = heap.ObjectPayloadSizeForTesting(); - EXPECT_TRUE(initial_object_payload_size == after_free); -} - -namespace { -class Weak final : public Bar { - public: - Weak(Bar* strong_bar, Bar* weak_bar) - : strong_bar_(strong_bar), weak_bar_(weak_bar) {} - - void Trace(Visitor* visitor) const override { - Bar::Trace(visitor); - visitor->Trace(strong_bar_); - visitor->template RegisterWeakCallbackMethod<Weak, &Weak::ZapWeakMembers>( - this); - } - - void ZapWeakMembers(const LivenessBroker& info) { - if (!info.IsHeapObjectAlive(weak_bar_)) - weak_bar_ = nullptr; - } - - bool StrongIsThere() { return !!strong_bar_; } - bool WeakIsThere() { return !!weak_bar_; } - - private: - Member<Bar> strong_bar_; - UntracedMember<Bar> weak_bar_; -}; - -class WithWeakMember final : public Bar { - public: - WithWeakMember(Bar* strong_bar, Bar* weak_bar) - : strong_bar_(strong_bar), weak_bar_(weak_bar) {} - - void Trace(Visitor* visitor) const override { - Bar::Trace(visitor); - visitor->Trace(strong_bar_); - visitor->Trace(weak_bar_); - } - - bool StrongIsThere() { return !!strong_bar_; } - bool WeakIsThere() { return !!weak_bar_; } - - private: - Member<Bar> strong_bar_; - WeakMember<Bar> weak_bar_; -}; -} // namespace - -TEST_F(HeapInternalsTest, WeakMembers) { - ClearOutOldGarbage(); - Bar::live_ = 0; - { - Persistent<Bar> h1 = MakeGarbageCollected<Bar>(); - Persistent<Weak> h4; - Persistent<WithWeakMember> h5; - PreciselyCollectGarbage(); - ASSERT_EQ(1u, Bar::live_); // h1 is live. - { - auto* h2 = MakeGarbageCollected<Bar>(); - auto* h3 = MakeGarbageCollected<Bar>(); - h4 = MakeGarbageCollected<Weak>(h2, h3); - h5 = MakeGarbageCollected<WithWeakMember>(h2, h3); - ConservativelyCollectGarbage(); - EXPECT_EQ(5u, Bar::live_); // The on-stack pointer keeps h3 alive. - EXPECT_FALSE(h3->HasBeenFinalized()); - EXPECT_TRUE(h4->StrongIsThere()); - EXPECT_TRUE(h4->WeakIsThere()); - EXPECT_TRUE(h5->StrongIsThere()); - EXPECT_TRUE(h5->WeakIsThere()); - } - // h3 is collected, weak pointers from h4 and h5 don't keep it alive. - PreciselyCollectGarbage(); - EXPECT_EQ(4u, Bar::live_); - EXPECT_TRUE(h4->StrongIsThere()); - EXPECT_FALSE(h4->WeakIsThere()); // h3 is gone from weak pointer. - EXPECT_TRUE(h5->StrongIsThere()); - EXPECT_FALSE(h5->WeakIsThere()); // h3 is gone from weak pointer. - h1.Release(); // Zero out h1. - PreciselyCollectGarbage(); - EXPECT_EQ(3u, Bar::live_); // Only h4, h5 and h2 are left. - EXPECT_TRUE(h4->StrongIsThere()); // h2 is still pointed to from h4. - EXPECT_TRUE(h5->StrongIsThere()); // h2 is still pointed to from h5. - } - // h4 and h5 have gone out of scope now and they were keeping h2 alive. - PreciselyCollectGarbage(); - EXPECT_EQ(0u, Bar::live_); // All gone. -} - -namespace { -class Observable final : public GarbageCollected<Observable> { - USING_PRE_FINALIZER(Observable, WillFinalize); - - public: - explicit Observable(Bar* bar) : bar_(bar), was_destructed_(false) {} - ~Observable() { was_destructed_ = true; } - void Trace(Visitor* visitor) const { visitor->Trace(bar_); } - - // willFinalize is called by FinalizationObserver. willFinalize can touch - // other on-heap objects. - void WillFinalize() { - EXPECT_FALSE(was_destructed_); - EXPECT_FALSE(bar_->HasBeenFinalized()); - will_finalize_was_called_ = true; - } - static bool will_finalize_was_called_; - - private: - Member<Bar> bar_; - bool was_destructed_; -}; -bool Observable::will_finalize_was_called_ = false; - -template <typename T> -class FinalizationObserver : public GarbageCollected<FinalizationObserver<T>> { - public: - explicit FinalizationObserver(T* data) - : data_(data), did_call_will_finalize_(false) {} - - bool DidCallWillFinalize() const { return did_call_will_finalize_; } - - void Trace(Visitor* visitor) const { - visitor->template RegisterWeakCallbackMethod< - FinalizationObserver<T>, &FinalizationObserver<T>::ZapWeakMembers>( - this); - } - - void ZapWeakMembers(const LivenessBroker& info) { - if (data_ && !info.IsHeapObjectAlive(data_)) { - data_->WillFinalize(); - data_ = nullptr; - did_call_will_finalize_ = true; - } - } - - private: - UntracedMember<T> data_; - bool did_call_will_finalize_; -}; - -class FinalizationObserverWithHashMap { - public: - typedef HeapHashMap<WeakMember<Observable>, - std::unique_ptr<FinalizationObserverWithHashMap>> - ObserverMap; - - explicit FinalizationObserverWithHashMap(Observable* target) - : target_(target) {} - ~FinalizationObserverWithHashMap() { - target_->WillFinalize(); - did_call_will_finalize_ = true; - } - - static ObserverMap& Observe(Observable* target) { - ObserverMap& map = Observers(); - ObserverMap::AddResult result = map.insert(target, nullptr); - if (result.is_new_entry) { - result.stored_value->value = - std::make_unique<FinalizationObserverWithHashMap>(target); - } else { - DCHECK(result.stored_value->value); - } - return map; - } - - static void ClearObservers() { - delete observer_map_; - observer_map_ = nullptr; - } - - static bool did_call_will_finalize_; - - private: - static ObserverMap& Observers() { - if (!observer_map_) { - observer_map_ = - new Persistent<ObserverMap>(MakeGarbageCollected<ObserverMap>()); - } - return **observer_map_; - } - - UntracedMember<Observable> target_; - static Persistent<ObserverMap>* observer_map_; -}; -bool FinalizationObserverWithHashMap::did_call_will_finalize_ = false; -Persistent<FinalizationObserverWithHashMap::ObserverMap>* - FinalizationObserverWithHashMap::observer_map_; -} // namespace - -TEST_F(HeapInternalsTest, FinalizationObserver) { - Persistent<FinalizationObserver<Observable>> o; - { - auto* foo = MakeGarbageCollected<Observable>(MakeGarbageCollected<Bar>()); - // |o| observes |foo|. - o = MakeGarbageCollected<FinalizationObserver<Observable>>(foo); - } - // FinalizationObserver doesn't have a strong reference to |foo|. So |foo| - // and its member will be collected. - PreciselyCollectGarbage(); - EXPECT_EQ(0u, Bar::live_); - EXPECT_TRUE(o->DidCallWillFinalize()); - - FinalizationObserverWithHashMap::did_call_will_finalize_ = false; - auto* foo = MakeGarbageCollected<Observable>(MakeGarbageCollected<Bar>()); - FinalizationObserverWithHashMap::ObserverMap& map = - FinalizationObserverWithHashMap::Observe(foo); - EXPECT_EQ(1u, map.size()); - foo = nullptr; - // FinalizationObserverWithHashMap doesn't have a strong reference to - // |foo|. So |foo| and its member will be collected. - PreciselyCollectGarbage(); - EXPECT_EQ(0u, Bar::live_); - EXPECT_EQ(0u, map.size()); - EXPECT_TRUE(FinalizationObserverWithHashMap::did_call_will_finalize_); - - FinalizationObserverWithHashMap::ClearObservers(); -} - -TEST_F(HeapInternalsTest, PreFinalizer) { - Observable::will_finalize_was_called_ = false; - { MakeGarbageCollected<Observable>(MakeGarbageCollected<Bar>()); } - PreciselyCollectGarbage(); - EXPECT_TRUE(Observable::will_finalize_was_called_); -} - -namespace { -class ObservableWithPreFinalizer final - : public GarbageCollected<ObservableWithPreFinalizer> { - USING_PRE_FINALIZER(ObservableWithPreFinalizer, Dispose); - - public: - ~ObservableWithPreFinalizer() { was_destructed_ = true; } - void Trace(Visitor* visitor) const {} - void Dispose() { - EXPECT_FALSE(was_destructed_); - dispose_was_called_ = true; - } - static bool dispose_was_called_; - - protected: - bool was_destructed_ = false; -}; -bool ObservableWithPreFinalizer::dispose_was_called_ = false; -} // namespace - -TEST_F(HeapInternalsTest, PreFinalizerUnregistersItself) { - ObservableWithPreFinalizer::dispose_was_called_ = false; - MakeGarbageCollected<ObservableWithPreFinalizer>(); - PreciselyCollectGarbage(); - EXPECT_TRUE(ObservableWithPreFinalizer::dispose_was_called_); - // Don't crash, and assertions don't fail. -} - -namespace { -bool g_dispose_was_called_for_pre_finalizer_base = false; -bool g_dispose_was_called_for_pre_finalizer_mixin = false; -bool g_dispose_was_called_for_pre_finalizer_sub_class = false; - -class PreFinalizerBase : public GarbageCollected<PreFinalizerBase> { - USING_PRE_FINALIZER(PreFinalizerBase, Dispose); - - public: - virtual ~PreFinalizerBase() { was_destructed_ = true; } - virtual void Trace(Visitor* visitor) const {} - void Dispose() { - EXPECT_FALSE(g_dispose_was_called_for_pre_finalizer_base); - EXPECT_TRUE(g_dispose_was_called_for_pre_finalizer_sub_class); - EXPECT_TRUE(g_dispose_was_called_for_pre_finalizer_mixin); - EXPECT_FALSE(was_destructed_); - g_dispose_was_called_for_pre_finalizer_base = true; - } - - protected: - bool was_destructed_ = false; -}; - -class PreFinalizerMixin : public GarbageCollectedMixin { - USING_PRE_FINALIZER(PreFinalizerMixin, Dispose); - - public: - ~PreFinalizerMixin() { was_destructed_ = true; } - void Trace(Visitor* visitor) const override {} - void Dispose() { - EXPECT_FALSE(g_dispose_was_called_for_pre_finalizer_base); - EXPECT_TRUE(g_dispose_was_called_for_pre_finalizer_sub_class); - EXPECT_FALSE(g_dispose_was_called_for_pre_finalizer_mixin); - EXPECT_FALSE(was_destructed_); - g_dispose_was_called_for_pre_finalizer_mixin = true; - } - - protected: - bool was_destructed_ = false; -}; - -class PreFinalizerSubClass : public PreFinalizerBase, public PreFinalizerMixin { - USING_PRE_FINALIZER(PreFinalizerSubClass, Dispose); - - public: - ~PreFinalizerSubClass() override { was_destructed_ = true; } - void Trace(Visitor* visitor) const override { - PreFinalizerBase::Trace(visitor); - PreFinalizerMixin::Trace(visitor); - } - void Dispose() { - EXPECT_FALSE(g_dispose_was_called_for_pre_finalizer_base); - EXPECT_FALSE(g_dispose_was_called_for_pre_finalizer_sub_class); - EXPECT_FALSE(g_dispose_was_called_for_pre_finalizer_mixin); - EXPECT_FALSE(was_destructed_); - g_dispose_was_called_for_pre_finalizer_sub_class = true; - } - - protected: - bool was_destructed_ = false; -}; -} // namespace - -TEST_F(HeapInternalsTest, NestedPreFinalizer) { - g_dispose_was_called_for_pre_finalizer_base = false; - g_dispose_was_called_for_pre_finalizer_sub_class = false; - g_dispose_was_called_for_pre_finalizer_mixin = false; - MakeGarbageCollected<PreFinalizerSubClass>(); - PreciselyCollectGarbage(); - EXPECT_TRUE(g_dispose_was_called_for_pre_finalizer_base); - EXPECT_TRUE(g_dispose_was_called_for_pre_finalizer_sub_class); - EXPECT_TRUE(g_dispose_was_called_for_pre_finalizer_mixin); - // Don't crash, and assertions don't fail. -} - -TEST_F(HeapInternalsTest, Comparisons) { - Persistent<Bar> bar_persistent = MakeGarbageCollected<Bar>(); - Persistent<Foo> foo_persistent = MakeGarbageCollected<Foo>(bar_persistent); - EXPECT_TRUE(bar_persistent != foo_persistent); - bar_persistent = foo_persistent; - EXPECT_TRUE(bar_persistent == foo_persistent); -} - -namespace { -class DisableHeapVerificationScope { - public: - explicit DisableHeapVerificationScope(const char*) { - ThreadState::Current()->EnterNoHeapVerificationScopeForTesting(); - } - ~DisableHeapVerificationScope() { - ThreadState::Current()->LeaveNoHeapVerificationScopeForTesting(); - } -}; -} // namespace - -TEST_F(HeapInternalsTest, GarbageCollectedMixin) { - ClearOutOldGarbage(); - - Persistent<UseMixin> usemixin = MakeGarbageCollected<UseMixin>(); - EXPECT_EQ(0, UseMixin::trace_count_); - { - DisableHeapVerificationScope scope( - "Avoid tracing UseMixin during verification"); - PreciselyCollectGarbage(); - } - EXPECT_EQ(1, UseMixin::trace_count_); - - Persistent<Mixin> mixin = usemixin; - usemixin = nullptr; - { - DisableHeapVerificationScope scope( - "Avoid tracing UseMixin during verification"); - PreciselyCollectGarbage(); - } - EXPECT_EQ(2, UseMixin::trace_count_); - - Persistent<HeapHashSet<WeakMember<Mixin>>> weak_map = - MakeGarbageCollected<HeapHashSet<WeakMember<Mixin>>>(); - weak_map->insert(MakeGarbageCollected<UseMixin>()); - PreciselyCollectGarbage(); - EXPECT_EQ(0u, weak_map->size()); -} - -namespace { -class OneKiloByteObject final : public GarbageCollected<OneKiloByteObject> { - public: - ~OneKiloByteObject() { destructor_calls_++; } - char* Data() { return data_; } - void Trace(Visitor* visitor) const {} - static int destructor_calls_; - - private: - static const size_t kLength = 1024; - char data_[kLength]; -}; -int OneKiloByteObject::destructor_calls_ = 0; - -class FinalizationAllocator final - : public GarbageCollected<FinalizationAllocator> { - public: - explicit FinalizationAllocator(Persistent<IntWrapper>* wrapper) { - wrapper_ = wrapper; - } - - ~FinalizationAllocator() { - for (int i = 0; i < 10; ++i) - *wrapper_ = MakeGarbageCollected<IntWrapper>(42); - for (int i = 0; i < 512; ++i) - MakeGarbageCollected<OneKiloByteObject>(); - for (int i = 0; i < 32; ++i) - MakeGarbageCollected<LargeHeapObject>(); - } - - void Trace(Visitor* visitor) const {} - - private: - static Persistent<IntWrapper>* wrapper_; -}; - -Persistent<IntWrapper>* FinalizationAllocator::wrapper_; -} // namespace - -TEST_F(HeapInternalsTest, AllocationDuringFinalization) { - ClearOutOldGarbage(); - IntWrapper::destructor_calls_ = 0; - OneKiloByteObject::destructor_calls_ = 0; - LargeHeapObject::destructor_calls_ = 0; - - Persistent<IntWrapper> wrapper; - MakeGarbageCollected<FinalizationAllocator>(&wrapper); - - PreciselyCollectGarbage(); - EXPECT_EQ(0, IntWrapper::destructor_calls_); - EXPECT_EQ(0, OneKiloByteObject::destructor_calls_); - EXPECT_EQ(0, LargeHeapObject::destructor_calls_); - // Check that the wrapper allocated during finalization is not - // swept away and zapped later in the same sweeping phase. - EXPECT_EQ(42, wrapper->Value()); - - wrapper.Clear(); - PreciselyCollectGarbage(); - // The 42 IntWrappers were the ones allocated in ~FinalizationAllocator - // and the ones allocated in LargeHeapObject. - EXPECT_EQ(42, IntWrapper::destructor_calls_); - EXPECT_EQ(512, OneKiloByteObject::destructor_calls_); - EXPECT_EQ(32, LargeHeapObject::destructor_calls_); -} - -namespace { -class MixinInstanceWithoutTrace - : public GarbageCollected<MixinInstanceWithoutTrace>, - public MixinA { - public: - MixinInstanceWithoutTrace() = default; -}; -} // namespace - -TEST_F(HeapInternalsTest, MixinInstanceWithoutTrace) { - // Verify that a mixin instance without any traceable - // references inherits the mixin's trace implementation. - ClearOutOldGarbage(); - MixinA::trace_count_ = 0; - MixinInstanceWithoutTrace* obj = - MakeGarbageCollected<MixinInstanceWithoutTrace>(); - int saved_trace_count = 0; - { - Persistent<MixinA> a = obj; - PreciselyCollectGarbage(); - saved_trace_count = MixinA::trace_count_; - EXPECT_LT(0, saved_trace_count); - } - { - Persistent<MixinInstanceWithoutTrace> b = obj; - PreciselyCollectGarbage(); - EXPECT_LT(saved_trace_count, MixinA::trace_count_); - saved_trace_count = MixinA::trace_count_; - } - PreciselyCollectGarbage(); - // Oilpan might still call trace on dead objects for various reasons which is - // valid before sweeping started. - EXPECT_LE(saved_trace_count, MixinA::trace_count_); -} - -namespace { -class PartObjectWithVirtualMethod { - public: - virtual void Trace(Visitor* visitor) const {} -}; - -class ObjectWithVirtualPartObject - : public GarbageCollected<ObjectWithVirtualPartObject> { - public: - ObjectWithVirtualPartObject() : dummy_(AllocateAndReturnBool()) {} - void Trace(Visitor* visitor) const { visitor->Trace(part_); } - - private: - bool dummy_; - PartObjectWithVirtualMethod part_; -}; -} // namespace - -TEST_F(HeapInternalsTest, PartObjectWithVirtualMethod) { - ObjectWithVirtualPartObject* object = - MakeGarbageCollected<ObjectWithVirtualPartObject>(); - EXPECT_TRUE(object); -} - -namespace { -class NonNodeAllocatingNodeInDestructor final - : public GarbageCollected<NonNodeAllocatingNodeInDestructor> { - public: - ~NonNodeAllocatingNodeInDestructor() { - node_ = new Persistent<IntNode>(IntNode::Create(10)); - } - - void Trace(Visitor* visitor) const {} - - static Persistent<IntNode>* node_; -}; - -Persistent<IntNode>* NonNodeAllocatingNodeInDestructor::node_ = nullptr; -} // namespace - -TEST_F(HeapInternalsTest, NonNodeAllocatingNodeInDestructor) { - MakeGarbageCollected<NonNodeAllocatingNodeInDestructor>(); - PreciselyCollectGarbage(); - EXPECT_EQ(10, (*NonNodeAllocatingNodeInDestructor::node_)->Value()); - delete NonNodeAllocatingNodeInDestructor::node_; - NonNodeAllocatingNodeInDestructor::node_ = nullptr; -} - -namespace { -class WeakPersistentHolder final { - public: - explicit WeakPersistentHolder(IntWrapper* object) : object_(object) {} - IntWrapper* Object() const { return object_; } - - private: - WeakPersistent<IntWrapper> object_; -}; -} // namespace - -TEST_F(HeapInternalsTest, WeakPersistent) { - Persistent<IntWrapper> object = MakeGarbageCollected<IntWrapper>(20); - std::unique_ptr<WeakPersistentHolder> holder = - std::make_unique<WeakPersistentHolder>(object); - PreciselyCollectGarbage(); - EXPECT_TRUE(holder->Object()); - object = nullptr; - PreciselyCollectGarbage(); - EXPECT_FALSE(holder->Object()); -} - -namespace { -class WithWeakConstObject final : public GarbageCollected<WithWeakConstObject> { - public: - explicit WithWeakConstObject(const IntWrapper* int_wrapper) - : wrapper_(int_wrapper) {} - - void Trace(Visitor* visitor) const { visitor->Trace(wrapper_); } - - const IntWrapper* Value() const { return wrapper_; } - - private: - WeakMember<const IntWrapper> wrapper_; -}; -} // namespace - -TEST_F(HeapInternalsTest, TestWeakConstObject) { - Persistent<WithWeakConstObject> weak_wrapper; - { - const auto* wrapper = MakeGarbageCollected<IntWrapper>(42); - weak_wrapper = MakeGarbageCollected<WithWeakConstObject>(wrapper); - ConservativelyCollectGarbage(); - EXPECT_EQ(wrapper, weak_wrapper->Value()); - // Stub out any stack reference. - wrapper = nullptr; - } - PreciselyCollectGarbage(); - EXPECT_EQ(nullptr, weak_wrapper->Value()); -} - -namespace { -class EmptyMixin : public GarbageCollectedMixin {}; -class UseMixinFromLeftmostInherited : public UseMixin, public EmptyMixin { - public: - ~UseMixinFromLeftmostInherited() = default; -}; -} // namespace - -TEST_F(HeapInternalsTest, IsGarbageCollected) { - // Static sanity checks covering the correct operation of - // IsGarbageCollectedType<>. - - static_assert(WTF::IsGarbageCollectedType<SimpleObject>::value, - "GarbageCollected<>"); - static_assert(WTF::IsGarbageCollectedType<const SimpleObject>::value, - "const GarbageCollected<>"); - static_assert(WTF::IsGarbageCollectedType<IntWrapper>::value, - "GarbageCollected<>"); - static_assert(WTF::IsGarbageCollectedType<GarbageCollectedMixin>::value, - "GarbageCollectedMixin"); - static_assert(WTF::IsGarbageCollectedType<const GarbageCollectedMixin>::value, - "const GarbageCollectedMixin"); - static_assert(WTF::IsGarbageCollectedType<UseMixin>::value, - "GarbageCollectedMixin instance"); - static_assert(WTF::IsGarbageCollectedType<const UseMixin>::value, - "const GarbageCollectedMixin instance"); - static_assert( - WTF::IsGarbageCollectedType<UseMixinFromLeftmostInherited>::value, - "GarbageCollectedMixin derived instance"); - static_assert(WTF::IsGarbageCollectedType<MultipleMixins>::value, - "GarbageCollectedMixin"); - - static_assert( - WTF::IsGarbageCollectedType<HeapHashSet<Member<IntWrapper>>>::value, - "HeapHashSet"); - static_assert( - WTF::IsGarbageCollectedType<HeapLinkedHashSet<Member<IntWrapper>>>::value, - "HeapLinkedHashSet"); - static_assert(WTF::IsGarbageCollectedType< - HeapHashCountedSet<Member<IntWrapper>>>::value, - "HeapHashCountedSet"); - static_assert( - WTF::IsGarbageCollectedType<HeapHashMap<int, Member<IntWrapper>>>::value, - "HeapHashMap"); - static_assert( - WTF::IsGarbageCollectedType<HeapVector<Member<IntWrapper>>>::value, - "HeapVector"); - static_assert( - WTF::IsGarbageCollectedType<HeapDeque<Member<IntWrapper>>>::value, - "HeapDeque"); -} - -TEST_F(HeapInternalsTest, ShrinkVector) { - // Regression test: https://crbug.com/823289 - - HeapVector<Member<IntWrapper>> vector; - vector.ReserveCapacity(32); - for (int i = 0; i < 4; i++) { - vector.push_back(MakeGarbageCollected<IntWrapper>(i)); - } - - ConservativelyCollectGarbage(BlinkGC::kConcurrentAndLazySweeping); - - // The following call tries to promptly free the left overs. In the buggy - // scenario that would create a free HeapObjectHeader that is assumed to be - // black which it is not. - vector.ShrinkToFit(); -} - -TEST_F(HeapInternalsTest, GarbageCollectedInConstruction) { - using O = ObjectWithCallbackBeforeInitializer<IntWrapper>; - MakeGarbageCollected<O>(base::BindOnce([](O* thiz) { - CHECK(HeapObjectHeader::FromPayload(thiz)->IsInConstruction()); - })); -} - -TEST_F(HeapInternalsTest, GarbageCollectedMixinInConstruction) { - using O = ObjectWithMixinWithCallbackBeforeInitializer<IntWrapper>; - MakeGarbageCollected<O>(base::BindOnce([](O::Mixin* thiz) { - const HeapObjectHeader* const header = - HeapObjectHeader::FromInnerAddress(reinterpret_cast<Address>(thiz)); - CHECK(header->IsInConstruction()); - })); -} - -TEST_F(HeapInternalsTest, PersistentAssignsDeletedValue) { - // Regression test: https://crbug.com/982313 - - Persistent<IntWrapper> deleted(WTF::kHashTableDeletedValue); - Persistent<IntWrapper> pre_initialized(MakeGarbageCollected<IntWrapper>(1)); - pre_initialized = deleted; - PreciselyCollectGarbage(); -} - -namespace { -struct HeapHashMapWrapper final : GarbageCollected<HeapHashMapWrapper> { - HeapHashMapWrapper() { - for (int i = 0; i < 100; ++i) { - map_.insert(MakeGarbageCollected<IntWrapper>(i), - NonTriviallyDestructible()); - } - } - // This should call ~HeapHapMap() -> ~HashMap() -> ~HashTable(). - ~HeapHashMapWrapper() = default; - - void Trace(Visitor* visitor) const { visitor->Trace(map_); } - - private: - struct NonTriviallyDestructible { - ~NonTriviallyDestructible() {} - }; - HeapHashMap<Member<IntWrapper>, NonTriviallyDestructible> map_; -}; -} // namespace - -TEST_F(HeapInternalsTest, AccessDeletedBackingStore) { - // Regression test: https://crbug.com/985443 - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndDisableFeature( - blink::features::kBlinkHeapConcurrentSweeping); - ClearOutOldGarbage(); - - ThreadState* thread_state = ThreadState::Current(); - - auto* map = MakeGarbageCollected<HeapHashMapWrapper>(); - // Run marking. - PreciselyCollectGarbage(BlinkGC::kConcurrentAndLazySweeping); - // Perform complete sweep on hash_arena. - BaseArena* hash_arena = - thread_state->Heap().Arena(BlinkGC::kHashTableArenaIndex); - { - ThreadState::AtomicPauseScope scope(thread_state); - ScriptForbiddenScope script_forbidden_scope; - ThreadState::SweepForbiddenScope sweep_forbidden(thread_state); - hash_arena->CompleteSweep(); - } - BaseArena* map_arena = PageFromObject(map)->Arena(); - // Sweep normal arena, but don't call finalizers. - while (!map_arena->ConcurrentSweepOnePage()) { - } - // Now complete sweeping with PerformIdleLazySweep and call finalizers. - while (thread_state->IsSweepingInProgress()) { - thread_state->PerformIdleLazySweep(base::TimeTicks::Max()); - } -} - -namespace { -class GCBase : public GarbageCollected<GCBase> { - public: - virtual void Trace(Visitor*) const {} -}; - -class GCDerived final : public GCBase { - public: - static int destructor_called; - void Trace(Visitor* visitor) const override { GCBase::Trace(visitor); } - ~GCDerived() { ++destructor_called; } -}; -int GCDerived::destructor_called = 0; -} // namespace - -TEST_F(HeapInternalsTest, CallMostDerivedFinalizer) { - MakeGarbageCollected<GCDerived>(); - PreciselyCollectGarbage(); - EXPECT_EQ(1, GCDerived::destructor_called); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/impl/test/heap_stats_collector_test.cc b/third_party/blink/renderer/platform/heap/impl/test/heap_stats_collector_test.cc deleted file mode 100644 index 6f8ac67..0000000 --- a/third_party/blink/renderer/platform/heap/impl/test/heap_stats_collector_test.cc +++ /dev/null
@@ -1,690 +0,0 @@ -// 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/heap/heap_stats_collector.h" - -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace blink { - -namespace { - -constexpr size_t kNoMarkedBytes = 0; - -} // namespace - -// ============================================================================= -// ThreadHeapStatsCollector. =================================================== -// ============================================================================= - -TEST(ThreadHeapStatsCollectorTest, InitialEmpty) { - ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - for (int i = 0; i < ThreadHeapStatsCollector::kNumScopeIds; i++) { - EXPECT_EQ(base::TimeDelta(), stats_collector.current().scope_data[i]); - } - stats_collector.NotifyMarkingCompleted(kNoMarkedBytes); - stats_collector.NotifySweepingCompleted(); -} - -TEST(ThreadHeapStatsCollectorTest, IncreaseScopeTime) { - ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.IncreaseScopeTime( - ThreadHeapStatsCollector::kIncrementalMarkingStep, - base::TimeDelta::FromMilliseconds(1)); - EXPECT_EQ(base::TimeDelta::FromMilliseconds(1), - stats_collector.current() - .scope_data[ThreadHeapStatsCollector::kIncrementalMarkingStep]); - stats_collector.NotifyMarkingCompleted(kNoMarkedBytes); - stats_collector.NotifySweepingCompleted(); -} - -TEST(ThreadHeapStatsCollectorTest, StopMovesCurrentToPrevious) { - ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.IncreaseScopeTime( - ThreadHeapStatsCollector::kIncrementalMarkingStep, - base::TimeDelta::FromMilliseconds(1)); - stats_collector.NotifyMarkingCompleted(kNoMarkedBytes); - stats_collector.NotifySweepingCompleted(); - EXPECT_EQ(base::TimeDelta::FromMilliseconds(1), - stats_collector.previous() - .scope_data[ThreadHeapStatsCollector::kIncrementalMarkingStep]); -} - -TEST(ThreadHeapStatsCollectorTest, StopResetsCurrent) { - ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.IncreaseScopeTime( - ThreadHeapStatsCollector::kIncrementalMarkingStep, - base::TimeDelta::FromMilliseconds(1)); - stats_collector.NotifyMarkingCompleted(kNoMarkedBytes); - stats_collector.NotifySweepingCompleted(); - EXPECT_EQ(base::TimeDelta(), - stats_collector.current() - .scope_data[ThreadHeapStatsCollector::kIncrementalMarkingStep]); -} - -TEST(ThreadHeapStatsCollectorTest, StartStop) { - ThreadHeapStatsCollector stats_collector; - EXPECT_FALSE(stats_collector.is_started()); - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - EXPECT_TRUE(stats_collector.is_started()); - stats_collector.NotifyMarkingCompleted(kNoMarkedBytes); - stats_collector.NotifySweepingCompleted(); - EXPECT_FALSE(stats_collector.is_started()); -} - -TEST(ThreadHeapStatsCollectorTest, ScopeToString) { - EXPECT_STREQ("BlinkGC.IncrementalMarkingStartMarking", - ThreadHeapStatsCollector::ToString( - ThreadHeapStatsCollector::kIncrementalMarkingStartMarking, - BlinkGC::CollectionType::kMajor)); -} - -TEST(ThreadHeapStatsCollectorTest, UpdateReason) { - ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.NotifyMarkingCompleted(kNoMarkedBytes); - stats_collector.UpdateReason(BlinkGC::GCReason::kForcedGCForTesting); - stats_collector.NotifySweepingCompleted(); - EXPECT_EQ(BlinkGC::GCReason::kForcedGCForTesting, - stats_collector.previous().reason); -} - -TEST(ThreadHeapStatsCollectorTest, InitialEstimatedObjectSize) { - ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - EXPECT_EQ(0u, stats_collector.object_size_in_bytes()); - stats_collector.NotifyMarkingCompleted(kNoMarkedBytes); - stats_collector.NotifySweepingCompleted(); -} - -TEST(ThreadHeapStatsCollectorTest, EstimatedObjectSizeNoMarkedBytes) { - ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.IncreaseAllocatedObjectSizeForTesting(512); - EXPECT_EQ(512u, stats_collector.object_size_in_bytes()); - stats_collector.NotifyMarkingCompleted(kNoMarkedBytes); - stats_collector.NotifySweepingCompleted(); -} - -TEST(ThreadHeapStatsCollectorTest, - EstimatedObjectSizeIgnoresPreviouslyMarkedBytes) { - ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.NotifyMarkingCompleted(128); - stats_collector.NotifySweepingCompleted(); - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.NotifyMarkingCompleted(kNoMarkedBytes); - stats_collector.IncreaseAllocatedObjectSizeForTesting(512); - EXPECT_EQ(512u, stats_collector.object_size_in_bytes()); - stats_collector.NotifySweepingCompleted(); -} - -TEST(ThreadHeapStatsCollectorTest, - EstimatedObjectSizeUsesCurrentlyMarkedBytes) { - ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.NotifyMarkingCompleted(256); - stats_collector.NotifySweepingCompleted(); - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.NotifyMarkingCompleted(128); - // Currently marked bytes should not account to the estimated object size. - stats_collector.IncreaseAllocatedObjectSizeForTesting(512); - EXPECT_EQ(640u, stats_collector.object_size_in_bytes()); - stats_collector.NotifySweepingCompleted(); -} - -TEST(ThreadHeapStatsCollectorTest, PreInitializedEstimatedMarkingTime) { - // Checks that a marking time estimate can be retrieved before the first - // garbage collection triggers. - ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.NotifyMarkingCompleted(kNoMarkedBytes); - stats_collector.NotifySweepingCompleted(); -} - -TEST(ThreadHeapStatsCollectorTest, EstimatedMarkingTime1) { - ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.IncreaseScopeTime( - ThreadHeapStatsCollector::kAtomicPauseMarkTransitiveClosure, - base::TimeDelta::FromSeconds(1)); - stats_collector.NotifyMarkingCompleted(1024); - stats_collector.NotifySweepingCompleted(); - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.NotifyMarkingCompleted(kNoMarkedBytes); - stats_collector.NotifySweepingCompleted(); -} - -TEST(ThreadHeapStatsCollectorTest, EstimatedMarkingTime2) { - ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.IncreaseScopeTime( - ThreadHeapStatsCollector::kAtomicPauseMarkTransitiveClosure, - base::TimeDelta::FromSeconds(1)); - stats_collector.NotifyMarkingCompleted(1024); - stats_collector.NotifySweepingCompleted(); - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.IncreaseAllocatedObjectSizeForTesting(512); - stats_collector.NotifyMarkingCompleted(kNoMarkedBytes); - stats_collector.NotifySweepingCompleted(); -} - -TEST(ThreadHeapStatsCollectorTest, SubMilliSecondMarkingTime) { - ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.IncreaseScopeTime( - ThreadHeapStatsCollector::kIncrementalMarkingStartMarking, - base::TimeDelta::FromMillisecondsD(.5)); - stats_collector.NotifyMarkingCompleted(kNoMarkedBytes); - stats_collector.NotifySweepingCompleted(); -} - -TEST(ThreadHeapStatsCollectorTest, AllocatedSpaceInBytesInitialZero) { - ThreadHeapStatsCollector stats_collector; - EXPECT_EQ(0u, stats_collector.allocated_space_bytes()); - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - EXPECT_EQ(0u, stats_collector.allocated_space_bytes()); - stats_collector.NotifyMarkingCompleted(kNoMarkedBytes); - EXPECT_EQ(0u, stats_collector.allocated_space_bytes()); - stats_collector.NotifySweepingCompleted(); - EXPECT_EQ(0u, stats_collector.allocated_space_bytes()); -} - -TEST(ThreadHeapStatsCollectorTest, AllocatedSpaceInBytesIncrease) { - ThreadHeapStatsCollector stats_collector; - stats_collector.IncreaseAllocatedSpace(1024); - EXPECT_EQ(1024u, stats_collector.allocated_space_bytes()); -} - -TEST(ThreadHeapStatsCollectorTest, AllocatedSpaceInBytesDecrease) { - ThreadHeapStatsCollector stats_collector; - stats_collector.IncreaseAllocatedSpace(1024); - stats_collector.DecreaseAllocatedSpace(1024); - EXPECT_EQ(0u, stats_collector.allocated_space_bytes()); -} - -// ============================================================================= -// ThreadHeapStatsCollector::Event. ============================================ -// ============================================================================= - -TEST(ThreadHeapStatsCollectorTest, EventPrevGCMarkedObjectSize) { - ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.NotifyMarkingCompleted(1024); - stats_collector.NotifySweepingCompleted(); - EXPECT_EQ(1024u, stats_collector.previous().marked_bytes); -} - -TEST(ThreadHeapStatsCollectorTest, - EventMarkingTimeFromIncrementalStandAloneGC) { - ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.IncreaseScopeTime( - ThreadHeapStatsCollector::kIncrementalMarkingStartMarking, - base::TimeDelta::FromMilliseconds(7)); - stats_collector.IncreaseScopeTime( - ThreadHeapStatsCollector::kIncrementalMarkingStep, - base::TimeDelta::FromMilliseconds(2)); - stats_collector.IncreaseScopeTime( - ThreadHeapStatsCollector::kAtomicPauseMarkTransitiveClosure, - base::TimeDelta::FromMilliseconds(4)); - stats_collector.NotifyMarkingCompleted(kNoMarkedBytes); - stats_collector.NotifySweepingCompleted(); - EXPECT_DOUBLE_EQ(13.0, - stats_collector.previous().marking_time().InMillisecondsF()); -} - -TEST(ThreadHeapStatsCollectorTest, EventMarkingTimeFromIncrementalUnifiedGC) { - ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.IncreaseScopeTime( - ThreadHeapStatsCollector::kIncrementalMarkingStartMarking, - base::TimeDelta::FromMilliseconds(7)); - stats_collector.IncreaseScopeTime( - ThreadHeapStatsCollector::kIncrementalMarkingStep, - base::TimeDelta::FromMilliseconds(2)); - stats_collector.IncreaseScopeTime( - ThreadHeapStatsCollector::kUnifiedMarkingStep, - base::TimeDelta::FromMilliseconds(1)); - stats_collector.IncreaseScopeTime( - ThreadHeapStatsCollector::kAtomicPauseMarkPrologue, - base::TimeDelta::FromMilliseconds(3)); - stats_collector.IncreaseScopeTime( - ThreadHeapStatsCollector::kAtomicPauseMarkTransitiveClosure, - base::TimeDelta::FromMilliseconds(2)); - stats_collector.IncreaseScopeTime( - ThreadHeapStatsCollector::kAtomicPauseMarkEpilogue, - base::TimeDelta::FromMilliseconds(1)); - stats_collector.NotifyMarkingCompleted(kNoMarkedBytes); - stats_collector.NotifySweepingCompleted(); - EXPECT_DOUBLE_EQ(16.0, - stats_collector.previous().marking_time().InMillisecondsF()); -} - -TEST(ThreadHeapStatsCollectorTest, EventMarkingTime) { - ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.IncreaseScopeTime( - ThreadHeapStatsCollector::kIncrementalMarkingStep, - base::TimeDelta::FromMilliseconds(2)); - stats_collector.IncreaseScopeTime( - ThreadHeapStatsCollector::kAtomicPauseMarkTransitiveClosure, - base::TimeDelta::FromMilliseconds(11)); - stats_collector.NotifyMarkingCompleted(kNoMarkedBytes); - stats_collector.NotifySweepingCompleted(); - EXPECT_DOUBLE_EQ(13.0, - stats_collector.previous().marking_time().InMillisecondsF()); -} - -TEST(ThreadHeapStatsCollectorTest, EventAtomicMarkingTime) { - ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.IncreaseScopeTime( - ThreadHeapStatsCollector::kAtomicPauseMarkPrologue, - base::TimeDelta::FromMilliseconds(5)); - stats_collector.IncreaseScopeTime( - ThreadHeapStatsCollector::kAtomicPauseMarkTransitiveClosure, - base::TimeDelta::FromMilliseconds(3)); - stats_collector.IncreaseScopeTime( - ThreadHeapStatsCollector::kAtomicPauseMarkEpilogue, - base::TimeDelta::FromMilliseconds(1)); - stats_collector.NotifyMarkingCompleted(kNoMarkedBytes); - stats_collector.NotifySweepingCompleted(); - EXPECT_EQ(base::TimeDelta::FromMilliseconds(9), - stats_collector.previous().atomic_marking_time()); -} - -TEST(ThreadHeapStatsCollectorTest, EventAtomicPause) { - ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.IncreaseScopeTime( - ThreadHeapStatsCollector::kAtomicPauseMarkTransitiveClosure, - base::TimeDelta::FromMilliseconds(17)); - stats_collector.NotifyMarkingCompleted(kNoMarkedBytes); - stats_collector.IncreaseScopeTime( - ThreadHeapStatsCollector::kAtomicPauseSweepAndCompact, - base::TimeDelta::FromMilliseconds(15)); - stats_collector.NotifySweepingCompleted(); - EXPECT_EQ(base::TimeDelta::FromMilliseconds(32), - stats_collector.previous().atomic_pause_time()); -} - -TEST(ThreadHeapStatsCollectorTest, EventSweepingTime) { - ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.NotifyMarkingCompleted(kNoMarkedBytes); - stats_collector.IncreaseScopeTime(ThreadHeapStatsCollector::kLazySweepInIdle, - base::TimeDelta::FromMilliseconds(1)); - stats_collector.IncreaseScopeTime(ThreadHeapStatsCollector::kLazySweepInIdle, - base::TimeDelta::FromMilliseconds(2)); - stats_collector.IncreaseScopeTime(ThreadHeapStatsCollector::kLazySweepInIdle, - base::TimeDelta::FromMilliseconds(3)); - stats_collector.IncreaseScopeTime( - ThreadHeapStatsCollector::kLazySweepOnAllocation, - base::TimeDelta::FromMilliseconds(4)); - stats_collector.IncreaseScopeTime(ThreadHeapStatsCollector::kCompleteSweep, - base::TimeDelta::FromMilliseconds(5)); - stats_collector.NotifySweepingCompleted(); - EXPECT_EQ(base::TimeDelta::FromMilliseconds(15), - stats_collector.previous().sweeping_time()); -} - -TEST(ThreadHeapStatsCollectorTest, EventCompactionFreedBytes) { - ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.NotifyMarkingCompleted(kNoMarkedBytes); - stats_collector.IncreaseCompactionFreedSize(512); - stats_collector.NotifySweepingCompleted(); - EXPECT_EQ(512u, stats_collector.previous().compaction_freed_bytes); -} - -TEST(ThreadHeapStatsCollectorTest, EventCompactionFreedPages) { - ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.NotifyMarkingCompleted(kNoMarkedBytes); - stats_collector.IncreaseCompactionFreedPages(3); - stats_collector.NotifySweepingCompleted(); - EXPECT_EQ(3u, stats_collector.previous().compaction_freed_pages); -} - -TEST(ThreadHeapStatsCollectorTest, EventInitialEstimatedLiveObjectRate) { - ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.NotifyMarkingCompleted(128); - stats_collector.NotifySweepingCompleted(); - EXPECT_DOUBLE_EQ(0.0, stats_collector.previous().live_object_rate); -} - -TEST(ThreadHeapStatsCollectorTest, - EventEstimatedLiveObjectRateSameMarkedBytes) { - ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.NotifyMarkingCompleted(128); - stats_collector.NotifySweepingCompleted(); - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.NotifyMarkingCompleted(128); - stats_collector.NotifySweepingCompleted(); - EXPECT_DOUBLE_EQ(1.0, stats_collector.previous().live_object_rate); -} - -TEST(ThreadHeapStatsCollectorTest, - EventEstimatedLiveObjectRateHalfMarkedBytes) { - ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.NotifyMarkingCompleted(256); - stats_collector.NotifySweepingCompleted(); - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.NotifyMarkingCompleted(128); - stats_collector.NotifySweepingCompleted(); - EXPECT_DOUBLE_EQ(0.5, stats_collector.previous().live_object_rate); -} - -TEST(ThreadHeapStatsCollectorTest, EventEstimatedLiveObjectRateNoMarkedBytes) { - ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.NotifyMarkingCompleted(256); - stats_collector.NotifySweepingCompleted(); - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.NotifySweepingCompleted(); - EXPECT_DOUBLE_EQ(0.0, stats_collector.previous().live_object_rate); -} - -TEST(ThreadHeapStatsCollectorTest, - EventEstimatedLiveObjectRateWithAllocatedBytes1) { - ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.NotifyMarkingCompleted(128); - stats_collector.NotifySweepingCompleted(); - stats_collector.IncreaseAllocatedObjectSize(128); - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.NotifyMarkingCompleted(128); - stats_collector.NotifySweepingCompleted(); - EXPECT_DOUBLE_EQ(.5, stats_collector.previous().live_object_rate); -} - -TEST(ThreadHeapStatsCollectorTest, - EventEstimatedLiveObjectRateWithAllocatedBytes2) { - ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.NotifyMarkingCompleted(kNoMarkedBytes); - stats_collector.NotifySweepingCompleted(); - stats_collector.IncreaseAllocatedObjectSize(128); - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.NotifyMarkingCompleted(128); - stats_collector.NotifySweepingCompleted(); - EXPECT_DOUBLE_EQ(1.0, stats_collector.previous().live_object_rate); -} - -TEST(ThreadHeapStatsCollectorTest, - EventEstimatedLiveObjectRateWithAllocatedBytes3) { - ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.NotifyMarkingCompleted(kNoMarkedBytes); - stats_collector.NotifySweepingCompleted(); - EXPECT_DOUBLE_EQ(0, stats_collector.previous().live_object_rate); -} - -TEST(ThreadHeapStatsCollectorTest, - EventEstimatedLiveObjectRateWithAllocatedBytes4) { - ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.NotifyMarkingCompleted(128); - stats_collector.NotifySweepingCompleted(); - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.NotifyMarkingCompleted(kNoMarkedBytes); - stats_collector.NotifySweepingCompleted(); - EXPECT_DOUBLE_EQ(0, stats_collector.previous().live_object_rate); -} - -TEST(ThreadHeapStatsCollectorTest, EventAllocatedSpaceBeforeSweeping1) { - ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.IncreaseAllocatedSpace(1024); - stats_collector.NotifyMarkingCompleted(kNoMarkedBytes); - stats_collector.IncreaseAllocatedSpace(2048); - stats_collector.NotifySweepingCompleted(); - EXPECT_EQ( - 1024u, - stats_collector.previous().allocated_space_in_bytes_before_sweeping); -} - -TEST(ThreadHeapStatsCollectorTest, EventAllocatedSpaceBeforeSweeping2) { - ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector.IncreaseAllocatedSpace(1024); - stats_collector.NotifyMarkingCompleted(kNoMarkedBytes); - stats_collector.DecreaseAllocatedSpace(1024); - stats_collector.NotifySweepingCompleted(); - EXPECT_EQ( - 1024u, - stats_collector.previous().allocated_space_in_bytes_before_sweeping); -} - -// ============================================================================= -// ThreadHeapStatsObserver. ==================================================== -// ============================================================================= - -namespace { - -class MockThreadHeapStatsObserver : public ThreadHeapStatsObserver { - public: - MOCK_METHOD1(IncreaseAllocatedSpace, void(size_t)); - MOCK_METHOD1(DecreaseAllocatedSpace, void(size_t)); - MOCK_METHOD1(ResetAllocatedObjectSize, void(size_t)); - MOCK_METHOD1(IncreaseAllocatedObjectSize, void(size_t)); - MOCK_METHOD1(DecreaseAllocatedObjectSize, void(size_t)); -}; - -void FakeGC(ThreadHeapStatsCollector* stats_collector, size_t marked_bytes) { - stats_collector->NotifyMarkingStarted(BlinkGC::CollectionType::kMajor, - BlinkGC::GCReason::kForcedGCForTesting, - true /* is_forced_gc */); - stats_collector->NotifyMarkingCompleted(marked_bytes); - stats_collector->NotifySweepingCompleted(); -} - -} // namespace - -TEST(ThreadHeapStatsCollectorTest, RegisterUnregisterObserver) { - ThreadHeapStatsCollector stats_collector; - MockThreadHeapStatsObserver observer; - stats_collector.RegisterObserver(&observer); - stats_collector.UnregisterObserver(&observer); -} - -TEST(ThreadHeapStatsCollectorTest, ObserveAllocatedSpace) { - ThreadHeapStatsCollector stats_collector; - MockThreadHeapStatsObserver observer; - stats_collector.RegisterObserver(&observer); - EXPECT_CALL(observer, IncreaseAllocatedSpace(1024)); - stats_collector.IncreaseAllocatedSpace(1024); - EXPECT_CALL(observer, DecreaseAllocatedSpace(1024)); - stats_collector.DecreaseAllocatedSpace(1024); - stats_collector.UnregisterObserver(&observer); -} - -TEST(ThreadHeapStatsCollectorTest, ObserveResetAllocatedObjectSize) { - ThreadHeapStatsCollector stats_collector; - MockThreadHeapStatsObserver observer; - stats_collector.RegisterObserver(&observer); - EXPECT_CALL(observer, ResetAllocatedObjectSize(2048)); - FakeGC(&stats_collector, 2048); - stats_collector.UnregisterObserver(&observer); -} - -TEST(ThreadHeapStatsCollectorTest, ObserveAllocatedObjectSize) { - ThreadHeapStatsCollector stats_collector; - MockThreadHeapStatsObserver observer; - stats_collector.RegisterObserver(&observer); - EXPECT_CALL(observer, IncreaseAllocatedObjectSize(1024)); - stats_collector.IncreaseAllocatedObjectSizeForTesting(1024); - EXPECT_CALL(observer, DecreaseAllocatedObjectSize(1024)); - stats_collector.DecreaseAllocatedObjectSizeForTesting(1024); - stats_collector.UnregisterObserver(&observer); -} - -namespace { - -class ObserverTriggeringGC final : public ThreadHeapStatsObserver { - public: - explicit ObserverTriggeringGC(ThreadHeapStatsCollector* stats_collector) - : stats_collector_(stats_collector) {} - - void IncreaseAllocatedObjectSize(size_t bytes) final { - increase_call_count++; - increased_size_bytes_ += bytes; - if (increase_call_count == 1) { - FakeGC(stats_collector_, bytes); - } - } - - void ResetAllocatedObjectSize(size_t marked) final { - reset_call_count++; - marked_bytes_ = marked; - } - - // Mock out the rest to trigger warnings if used. - MOCK_METHOD1(IncreaseAllocatedSpace, void(size_t)); - MOCK_METHOD1(DecreaseAllocatedSpace, void(size_t)); - MOCK_METHOD1(DecreaseAllocatedObjectSize, void(size_t)); - - size_t marked_bytes() const { return marked_bytes_; } - size_t increased_size_bytes() const { return increased_size_bytes_; } - - size_t increase_call_count = 0; - size_t reset_call_count = 0; - - private: - ThreadHeapStatsCollector* const stats_collector_; - size_t marked_bytes_ = 0; - size_t increased_size_bytes_ = 0; -}; - -} // namespace - -TEST(ThreadHeapStatsCollectorTest, ObserverTriggersGC) { - ThreadHeapStatsCollector stats_collector; - ObserverTriggeringGC gc_observer(&stats_collector); - MockThreadHeapStatsObserver mock_observer; - // Internal detail: First registered observer is also notified first. - stats_collector.RegisterObserver(&gc_observer); - stats_collector.RegisterObserver(&mock_observer); - - // mock_observer is notified after triggering GC. This means that it should - // see the reset call with the fully marked size (as gc_observer fakes a GC - // with that size). - EXPECT_CALL(mock_observer, ResetAllocatedObjectSize(1024)); - // Since the GC clears counters, it should see an increase call with a delta - // of zero bytes. - EXPECT_CALL(mock_observer, IncreaseAllocatedObjectSize(0)); - - // Trigger scenario. - stats_collector.IncreaseAllocatedObjectSizeForTesting(1024); - - // gc_observer sees both calls exactly once. - EXPECT_EQ(1u, gc_observer.increase_call_count); - EXPECT_EQ(1u, gc_observer.reset_call_count); - // gc_observer sees the increased bytes and the reset call with the fully - // marked size. - EXPECT_EQ(1024u, gc_observer.increased_size_bytes()); - EXPECT_EQ(1024u, gc_observer.marked_bytes()); - - stats_collector.UnregisterObserver(&gc_observer); - stats_collector.UnregisterObserver(&mock_observer); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/impl/test/heap_thread_test.cc b/third_party/blink/renderer/platform/heap/impl/test/heap_thread_test.cc deleted file mode 100644 index 529f259..0000000 --- a/third_party/blink/renderer/platform/heap/impl/test/heap_thread_test.cc +++ /dev/null
@@ -1,276 +0,0 @@ -// 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 "build/build_config.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/public/platform/platform.h" -#include "third_party/blink/renderer/platform/heap/handle.h" -#include "third_party/blink/renderer/platform/heap/heap.h" -#include "third_party/blink/renderer/platform/heap/heap_test_utilities.h" -#include "third_party/blink/renderer/platform/heap/thread_state.h" -#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" -#include "third_party/blink/renderer/platform/scheduler/public/thread.h" -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" -#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h" - -namespace blink { - -class HeapThreadTest : public TestSupportingGC {}; - -class HeapThreadDeathTest : public TestSupportingGC { - public: - HeapThreadDeathTest() { - testing::FLAGS_gtest_death_test_style = "threadsafe"; - } -}; - -namespace heap_thread_test { - -static Mutex& ActiveThreadMutex() { - DEFINE_THREAD_SAFE_STATIC_LOCAL(Mutex, active_thread_mutex, ()); - return active_thread_mutex; -} - -static ThreadCondition& ActiveThreadCondition() { - DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadCondition, active_thread_condition, - (ActiveThreadMutex())); - return active_thread_condition; -} - -enum ActiveThreadState { - kNoThreadActive, - kMainThreadActive, - kWorkerThreadActive, -}; - -static ActiveThreadState& ActiveThread() { - DEFINE_THREAD_SAFE_STATIC_LOCAL(ActiveThreadState, active_thread, - (kNoThreadActive)); - return active_thread; -} - -static void WakeMainThread() { - ActiveThread() = kMainThreadActive; - ActiveThreadCondition().Signal(); -} - -static void WakeWorkerThread() { - ActiveThread() = kWorkerThreadActive; - ActiveThreadCondition().Signal(); -} - -static void ParkMainThread() { - while (ActiveThread() != kMainThreadActive) { - ActiveThreadCondition().Wait(); - } -} - -static void ParkWorkerThread() { - while (ActiveThread() != kWorkerThreadActive) { - ActiveThreadCondition().Wait(); - } -} - -class Object : public GarbageCollected<Object> { - public: - Object() {} - void Trace(Visitor* visitor) const {} -}; - -class AlternatingThreadTester { - STACK_ALLOCATED(); - - public: - void Test() { - MutexLocker locker(ActiveThreadMutex()); - ActiveThread() = kMainThreadActive; - - std::unique_ptr<Thread> worker_thread = Platform::Current()->CreateThread( - ThreadCreationParams(ThreadType::kTestThread) - .SetThreadNameForTest("Test Worker Thread")); - PostCrossThreadTask( - *worker_thread->GetTaskRunner(), FROM_HERE, - CrossThreadBindOnce(&AlternatingThreadTester::StartWorkerThread, - CrossThreadUnretained(this))); - - MainThreadMain(); - } - - void SwitchToWorkerThread() { - WakeWorkerThread(); - ParkMainThread(); - } - - void SwitchToMainThread() { - WakeMainThread(); - ParkWorkerThread(); - } - - protected: - // Override with code you want to execute on the main thread. - virtual void MainThreadMain() = 0; - // Override with code you want to execute on the worker thread. At the end, - // the ThreadState is detached and we switch back to the main thread - // automatically. - virtual void WorkerThreadMain() = 0; - - private: - void StartWorkerThread() { - ThreadState::AttachCurrentThread(); - - MutexLocker locker(ActiveThreadMutex()); - - WorkerThreadMain(); - - ThreadState::DetachCurrentThread(); - WakeMainThread(); - } -}; - -class MemberSameThreadCheckTester final : public AlternatingThreadTester { - public: - MemberSameThreadCheckTester() - : object_wrapper_(MakeGarbageCollected<ObjectWrapper>()) {} - - private: - class ObjectWrapper : public GarbageCollected<ObjectWrapper> { - public: - void Trace(Visitor* visitor) const { visitor->Trace(object_); } - - Member<Object> object_; - }; - - void MainThreadMain() override { SwitchToWorkerThread(); } - - void WorkerThreadMain() override { - // Setting an object created on the worker thread to a Member allocated on - // the main thread is not allowed. - object_wrapper_->object_ = MakeGarbageCollected<Object>(); - } - - ObjectWrapper* object_wrapper_; -}; - -#if DCHECK_IS_ON() -TEST_F(HeapThreadDeathTest, MemberSameThreadCheck) { - EXPECT_DEATH(MemberSameThreadCheckTester().Test(), ""); -} -#endif - -class PersistentSameThreadCheckTester : public AlternatingThreadTester { - private: - void MainThreadMain() override { SwitchToWorkerThread(); } - - void WorkerThreadMain() override { - // Setting an object created on the worker thread to a Persistent allocated - // on the main thread is not allowed. - object_ = MakeGarbageCollected<Object>(); - } - - Persistent<Object> object_; -}; - -#if DCHECK_IS_ON() -TEST_F(HeapThreadDeathTest, PersistentSameThreadCheck) { - EXPECT_DEATH(PersistentSameThreadCheckTester().Test(), ""); -} -#endif - -class MarkingSameThreadCheckTester : public AlternatingThreadTester { - private: - class MainThreadObject final : public GarbageCollected<MainThreadObject> { - public: - void Trace(Visitor* visitor) const { visitor->Trace(set_); } - void AddToSet(Object* object) { set_.insert(42, object); } - - private: - HeapHashMap<int, Member<Object>> set_; - }; - - void MainThreadMain() override { - main_thread_object_ = MakeGarbageCollected<MainThreadObject>(); - - SwitchToWorkerThread(); - - // This will try to mark MainThreadObject when it tries to mark Object - // it should crash. - TestSupportingGC::PreciselyCollectGarbage(); - } - - void WorkerThreadMain() override { - // Adding a reference to an object created on the worker thread to a - // HeapHashMap created on the main thread is not allowed. - main_thread_object_->AddToSet(MakeGarbageCollected<Object>()); - } - - CrossThreadPersistent<MainThreadObject> main_thread_object_; -}; - -#if DCHECK_IS_ON() -TEST_F(HeapThreadDeathTest, DISABLED_MarkingSameThreadCheck) { - // This will crash during marking, at the DCHECK in Visitor::markHeader() or - // earlier. - EXPECT_DEATH(MarkingSameThreadCheckTester().Test(), ""); -} -#endif - -class DestructorLockingObject - : public GarbageCollected<DestructorLockingObject> { - public: - DestructorLockingObject() = default; - virtual ~DestructorLockingObject() { ++destructor_calls_; } - - static int destructor_calls_; - void Trace(Visitor* visitor) const {} -}; - -int DestructorLockingObject::destructor_calls_ = 0; - -class CrossThreadWeakPersistentTester : public AlternatingThreadTester { - private: - void MainThreadMain() override { - // Create an object in the worker thread, have a CrossThreadWeakPersistent - // pointing to it on the main thread, run a GC in the worker thread, and see - // if the CrossThreadWeakPersistent is cleared. - - DestructorLockingObject::destructor_calls_ = 0; - - // Step 1: Initiate a worker thread, and wait for |Object| to get allocated - // on the worker thread. - SwitchToWorkerThread(); - - // Step 3: Set up a CrossThreadWeakPersistent. - ASSERT_TRUE(object_); - EXPECT_EQ(0, DestructorLockingObject::destructor_calls_); - - // Pretend we have no pointers on stack during the step 4. - SwitchToWorkerThread(); - - // Step 5: Make sure the weak persistent is cleared. - EXPECT_FALSE(object_); - EXPECT_EQ(1, DestructorLockingObject::destructor_calls_); - - SwitchToWorkerThread(); - } - - void WorkerThreadMain() override { - // Step 2: Create an object and store the pointer. - object_ = MakeGarbageCollected<DestructorLockingObject>(); - SwitchToMainThread(); - - // Step 4: Run a GC. - ThreadState::Current()->CollectAllGarbageForTesting( - BlinkGC::kNoHeapPointersOnStack); - SwitchToMainThread(); - } - - CrossThreadWeakPersistent<DestructorLockingObject> object_; -}; - -TEST_F(HeapThreadTest, CrossThreadWeakPersistent) { - CrossThreadWeakPersistentTester().Test(); -} - -} // namespace heap_thread_test -} // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/impl/test/incremental_marking_internals_test.cc b/third_party/blink/renderer/platform/heap/impl/test/incremental_marking_internals_test.cc deleted file mode 100644 index 4b82e85..0000000 --- a/third_party/blink/renderer/platform/heap/impl/test/incremental_marking_internals_test.cc +++ /dev/null
@@ -1,617 +0,0 @@ -// Copyright 2017 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 <initializer_list> - -#include "base/bind.h" -#include "base/test/scoped_feature_list.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/public/common/features.h" -#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h" -#include "third_party/blink/renderer/platform/heap/garbage_collected.h" -#include "third_party/blink/renderer/platform/heap/heap.h" -#include "third_party/blink/renderer/platform/heap/heap_allocator.h" -#include "third_party/blink/renderer/platform/heap/heap_buildflags.h" -#include "third_party/blink/renderer/platform/heap/heap_test_objects.h" -#include "third_party/blink/renderer/platform/heap/heap_test_utilities.h" -#include "third_party/blink/renderer/platform/heap/impl/heap_compact.h" -#include "third_party/blink/renderer/platform/heap/impl/trace_traits.h" -#include "third_party/blink/renderer/platform/heap/member.h" -#include "third_party/blink/renderer/platform/heap/persistent.h" -#include "third_party/blink/renderer/platform/heap/thread_state.h" -#include "third_party/blink/renderer/platform/heap/visitor.h" -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" - -namespace blink { - -class IncrementalMarkingInternalsTest : public TestSupportingGC {}; - -namespace incremental_marking_test { - -// Visitor that expects every directly reachable object from a given backing -// store to be in the set of provided objects. -class BackingVisitor final : public Visitor { - public: - BackingVisitor(ThreadState* state, Vector<void*>* objects) - : Visitor(state), objects_(objects) {} - ~BackingVisitor() override = default; - - void ProcessBackingStore(HeapObjectHeader* header) { - EXPECT_TRUE(header->IsMarked()); - header->Unmark(); - - GCInfo::From(header->GcInfoIndex()).trace(this, header->Payload()); - } - - void Visit(const void* obj, TraceDescriptor desc) override { - EXPECT_TRUE(obj); - auto** pos = std::find(objects_->begin(), objects_->end(), obj); - if (objects_->end() != pos) - objects_->erase(pos); - // The garbage collector will find those objects so we can mark them. - HeapObjectHeader* const header = - HeapObjectHeader::FromPayload(desc.base_object_payload); - if (!header->IsMarked()) - EXPECT_TRUE(header->TryMark()); - } - - void VisitEphemeron(const void* key, TraceDescriptor value_desc) override { - if (!HeapObjectHeader::FromPayload(key)->IsMarked()) - return; - value_desc.callback(this, value_desc.base_object_payload); - } - - private: - Vector<void*>* objects_; -}; - -// Base class for initializing worklists. -class IncrementalMarkingScopeBase { - DISALLOW_NEW(); - - public: - explicit IncrementalMarkingScopeBase(ThreadState* thread_state) - : thread_state_(thread_state), heap_(thread_state_->Heap()) { - if (thread_state_->IsMarkingInProgress() || - thread_state_->IsSweepingInProgress()) { - TestSupportingGC::PreciselyCollectGarbage(); - } - heap_.SetupWorklists(false); - } - - ~IncrementalMarkingScopeBase() { - heap_.DestroyMarkingWorklists(BlinkGC::StackState::kNoHeapPointersOnStack); - heap_.DestroyCompactionWorklists(); - } - - ThreadHeap& heap() const { return heap_; } - - protected: - ThreadState* const thread_state_; - ThreadHeap& heap_; -}; - -class IncrementalMarkingScope : public IncrementalMarkingScopeBase { - STACK_ALLOCATED(); - - public: - explicit IncrementalMarkingScope(ThreadState* thread_state) - : IncrementalMarkingScopeBase(thread_state), - gc_forbidden_scope_(thread_state), - marking_worklist_(heap_.GetMarkingWorklist()), - write_barrier_worklist_(heap_.GetWriteBarrierWorklist()), - not_fully_constructed_worklist_( - heap_.GetNotFullyConstructedWorklist()) { - thread_state_->SetGCPhase(ThreadState::GCPhase::kMarking); - ThreadState::AtomicPauseScope atomic_pause_scope_(thread_state_); - ScriptForbiddenScope script_forbidden_scope; - EXPECT_TRUE(marking_worklist_->IsGlobalEmpty()); - EXPECT_TRUE(write_barrier_worklist_->IsGlobalEmpty()); - EXPECT_TRUE(not_fully_constructed_worklist_->IsGlobalEmpty()); - thread_state->EnableIncrementalMarkingBarrier(); - thread_state->current_gc_data_.visitor = std::make_unique<MarkingVisitor>( - thread_state, MarkingVisitor::kGlobalMarking); - } - - ~IncrementalMarkingScope() { - EXPECT_TRUE(marking_worklist_->IsGlobalEmpty()); - EXPECT_TRUE(write_barrier_worklist_->IsGlobalEmpty()); - EXPECT_TRUE(not_fully_constructed_worklist_->IsGlobalEmpty()); - thread_state_->DisableIncrementalMarkingBarrier(); - // Need to clear out unused worklists that might have been polluted during - // test. - heap_.GetWeakCallbackWorklist()->Clear(); - thread_state_->SetGCPhase(ThreadState::GCPhase::kSweeping); - thread_state_->SetGCPhase(ThreadState::GCPhase::kNone); - } - - MarkingWorklist* marking_worklist() const { return marking_worklist_; } - WriteBarrierWorklist* write_barrier_worklist() const { - return write_barrier_worklist_; - } - NotFullyConstructedWorklist* not_fully_constructed_worklist() const { - return not_fully_constructed_worklist_; - } - - protected: - ThreadState::GCForbiddenScope gc_forbidden_scope_; - MarkingWorklist* const marking_worklist_; - WriteBarrierWorklist* const write_barrier_worklist_; - NotFullyConstructedWorklist* const not_fully_constructed_worklist_; -}; - -// Expects that the write barrier fires for the objects passed to the -// constructor. This requires that the objects are added to the marking stack -// as well as headers being marked. -class ExpectWriteBarrierFires : public IncrementalMarkingScope { - public: - ExpectWriteBarrierFires(ThreadState* thread_state, - std::initializer_list<void*> objects) - : IncrementalMarkingScope(thread_state), - objects_(objects), - backing_visitor_(thread_state_, &objects_) { - EXPECT_TRUE(marking_worklist_->IsGlobalEmpty()); - EXPECT_TRUE(write_barrier_worklist_->IsGlobalEmpty()); - for (void* object : objects_) { - // Ensure that the object is in the normal arena so we can ignore backing - // objects on the marking stack. - CHECK(ThreadHeap::IsNormalArenaIndex( - PageFromObject(object)->Arena()->ArenaIndex())); - headers_.push_back(HeapObjectHeader::FromPayload(object)); - EXPECT_FALSE(headers_.back()->IsMarked()); - } - EXPECT_FALSE(objects_.IsEmpty()); - } - - ~ExpectWriteBarrierFires() { - // All objects watched should be on the marking or write barrier worklist. - MarkingItem item; - while (marking_worklist_->Pop(WorklistTaskId::MutatorThread, &item)) { - // Inspect backing stores to allow specifying objects that are only - // reachable through a backing store. - if (!ThreadHeap::IsNormalArenaIndex( - PageFromObject(item.base_object_payload) - ->Arena() - ->ArenaIndex())) { - backing_visitor_.ProcessBackingStore( - HeapObjectHeader::FromPayload(item.base_object_payload)); - continue; - } - auto** pos = - std::find(objects_.begin(), objects_.end(), item.base_object_payload); - if (objects_.end() != pos) - objects_.erase(pos); - } - HeapObjectHeader* header; - while ( - write_barrier_worklist_->Pop(WorklistTaskId::MutatorThread, &header)) { - // Inspect backing stores to allow specifying objects that are only - // reachable through a backing store. - if (!ThreadHeap::IsNormalArenaIndex( - PageFromObject(header->Payload())->Arena()->ArenaIndex())) { - backing_visitor_.ProcessBackingStore(header); - continue; - } - auto** pos = - std::find(objects_.begin(), objects_.end(), header->Payload()); - if (objects_.end() != pos) - objects_.erase(pos); - } - EXPECT_TRUE(objects_.IsEmpty()); - // All headers of objects watched should be marked at this point. - for (HeapObjectHeader* hdr : headers_) { - EXPECT_TRUE(hdr->IsMarked()); - hdr->Unmark(); - } - EXPECT_TRUE(marking_worklist_->IsGlobalEmpty()); - EXPECT_TRUE(write_barrier_worklist_->IsGlobalEmpty()); - } - - private: - Vector<void*> objects_; - Vector<HeapObjectHeader*> headers_; - BackingVisitor backing_visitor_; -}; - -// Expects that no write barrier fires for the objects passed to the -// constructor. This requires that the marking stack stays empty and the marking -// state of the object stays the same across the lifetime of the scope. -class ExpectNoWriteBarrierFires : public IncrementalMarkingScope { - public: - ExpectNoWriteBarrierFires(ThreadState* thread_state, - std::initializer_list<void*> objects) - : IncrementalMarkingScope(thread_state) { - EXPECT_TRUE(marking_worklist_->IsGlobalEmpty()); - EXPECT_TRUE(write_barrier_worklist_->IsGlobalEmpty()); - for (void* object : objects) { - HeapObjectHeader* header = HeapObjectHeader::FromPayload(object); - headers_.push_back(std::make_pair(header, header->IsMarked())); - } - } - - ~ExpectNoWriteBarrierFires() { - EXPECT_TRUE(marking_worklist_->IsGlobalEmpty()); - EXPECT_TRUE(write_barrier_worklist_->IsGlobalEmpty()); - for (const auto& pair : headers_) { - EXPECT_EQ(pair.second, pair.first->IsMarked()); - pair.first->Unmark(); - } - } - - private: - Vector<std::pair<HeapObjectHeader*, bool /* was marked */>> headers_; -}; - -class Object : public LinkedObject { - public: - Object() = default; - explicit Object(Object* next) : LinkedObject(next) {} - - bool IsMarked() const { - return HeapObjectHeader::FromPayload(this)->IsMarked(); - } - - void Trace(Visitor* visitor) const override { LinkedObject::Trace(visitor); } -}; - -class ObjectWithWriteBarrier : public GarbageCollected<ObjectWithWriteBarrier> { - public: - void Trace(Visitor* v) const { v->Trace(object_); } - - void Set(Object* object) { object_ = object; } - - private: - Member<Object> object_; -}; - -// ============================================================================= -// Member<T> support. ========================================================== -// ============================================================================= - -TEST_F(IncrementalMarkingInternalsTest, MemberSetUnmarkedObject) { - auto* parent = MakeGarbageCollected<Object>(); - auto* child = MakeGarbageCollected<Object>(); - { - ExpectWriteBarrierFires scope(ThreadState::Current(), {child}); - EXPECT_FALSE(child->IsMarked()); - parent->set_next(child); - EXPECT_TRUE(child->IsMarked()); - } -} - -TEST_F(IncrementalMarkingInternalsTest, MemberSetMarkedObjectNoBarrier) { - auto* parent = MakeGarbageCollected<Object>(); - auto* child = MakeGarbageCollected<Object>(); - EXPECT_TRUE(HeapObjectHeader::FromPayload(child)->TryMark()); - { - ExpectNoWriteBarrierFires scope(ThreadState::Current(), {child}); - parent->set_next(child); - } -} - -TEST_F(IncrementalMarkingInternalsTest, MemberInitializingStoreNoBarrier) { - auto* object1 = MakeGarbageCollected<Object>(); - HeapObjectHeader* object1_header = HeapObjectHeader::FromPayload(object1); - { - IncrementalMarkingScope scope(ThreadState::Current()); - EXPECT_FALSE(object1_header->IsMarked()); - auto* object2 = MakeGarbageCollected<Object>(object1); - HeapObjectHeader* object2_header = HeapObjectHeader::FromPayload(object2); - EXPECT_FALSE(object1_header->IsMarked()); - EXPECT_FALSE(object2_header->IsMarked()); - } -} - -TEST_F(IncrementalMarkingInternalsTest, MemberReferenceAssignMember) { - auto* obj = MakeGarbageCollected<LinkedObject>(); - auto* ref_obj = MakeGarbageCollected<LinkedObject>(); - Member<LinkedObject>& m2 = ref_obj->next_ref(); - Member<LinkedObject> m3(obj); - { - ExpectWriteBarrierFires scope(ThreadState::Current(), {obj}); - m2 = m3; - } -} - -TEST_F(IncrementalMarkingInternalsTest, MemberSetDeletedValueNoBarrier) { - auto* obj = MakeGarbageCollected<LinkedObject>(); - Member<LinkedObject>& m = obj->next_ref(); - { - ExpectNoWriteBarrierFires scope(ThreadState::Current(), {}); - m = WTF::kHashTableDeletedValue; - } -} - -TEST_F(IncrementalMarkingInternalsTest, MemberCopyDeletedValueNoBarrier) { - auto* obj1 = MakeGarbageCollected<LinkedObject>(); - Member<LinkedObject>& m1 = obj1->next_ref(); - m1 = WTF::kHashTableDeletedValue; - { - ExpectNoWriteBarrierFires scope(ThreadState::Current(), {}); - auto* obj2 = MakeGarbageCollected<LinkedObject>(); - obj2->next_ref() = m1; - } -} - -TEST_F(IncrementalMarkingInternalsTest, - MemberHashTraitConstructDeletedValueNoBarrier) { - auto* obj = MakeGarbageCollected<LinkedObject>(); - Member<LinkedObject>& m = obj->next_ref(); - { - ExpectNoWriteBarrierFires scope(ThreadState::Current(), {}); - HashTraits<Member<LinkedObject>>::ConstructDeletedValue(m, false); - } -} - -TEST_F(IncrementalMarkingInternalsTest, - MemberHashTraitIsDeletedValueNoBarrier) { - auto* obj = - MakeGarbageCollected<LinkedObject>(MakeGarbageCollected<LinkedObject>()); - Member<LinkedObject>& m = obj->next_ref(); - { - ExpectNoWriteBarrierFires scope(ThreadState::Current(), {}); - EXPECT_FALSE(HashTraits<Member<LinkedObject>>::IsDeletedValue(m)); - } -} - -// ============================================================================= -// Mixin support. ============================================================== -// ============================================================================= - -namespace { - -class Mixin : public GarbageCollectedMixin { - public: - Mixin() : next_(nullptr) {} - virtual ~Mixin() = default; - - void Trace(Visitor* visitor) const override { visitor->Trace(next_); } - - virtual void Bar() {} - - protected: - Member<Object> next_; -}; - -class ClassWithVirtual { - protected: - virtual void Foo() {} -}; - -class Child : public GarbageCollected<Child>, - public ClassWithVirtual, - public Mixin { - public: - Child() : ClassWithVirtual() {} - ~Child() override = default; - - void Trace(Visitor* visitor) const override { Mixin::Trace(visitor); } - - void Foo() override {} - void Bar() override {} -}; - -class ParentWithMixinPointer : public GarbageCollected<ParentWithMixinPointer> { - public: - ParentWithMixinPointer() : mixin_(nullptr) {} - - void set_mixin(Mixin* mixin) { mixin_ = mixin; } - - virtual void Trace(Visitor* visitor) const { visitor->Trace(mixin_); } - - protected: - Member<Mixin> mixin_; -}; - -} // namespace - -TEST_F(IncrementalMarkingInternalsTest, - WriteBarrierOnUnmarkedMixinApplication) { - ParentWithMixinPointer* parent = - MakeGarbageCollected<ParentWithMixinPointer>(); - auto* child = MakeGarbageCollected<Child>(); - Mixin* mixin = static_cast<Mixin*>(child); - EXPECT_NE(static_cast<void*>(child), static_cast<void*>(mixin)); - { - ExpectWriteBarrierFires scope(ThreadState::Current(), {child}); - parent->set_mixin(mixin); - } -} - -TEST_F(IncrementalMarkingInternalsTest, - NoWriteBarrierOnMarkedMixinApplication) { - ParentWithMixinPointer* parent = - MakeGarbageCollected<ParentWithMixinPointer>(); - auto* child = MakeGarbageCollected<Child>(); - EXPECT_TRUE(HeapObjectHeader::FromPayload(child)->TryMark()); - Mixin* mixin = static_cast<Mixin*>(child); - EXPECT_NE(static_cast<void*>(child), static_cast<void*>(mixin)); - { - ExpectNoWriteBarrierFires scope(ThreadState::Current(), {child}); - parent->set_mixin(mixin); - } -} - -// TODO(keishi) Non-weak hash table backings should be promptly freed but they -// are currently not because we emit write barriers for the backings, and we -// don't free marked backings. -TEST_F(IncrementalMarkingInternalsTest, - DISABLED_WeakHashMapPromptlyFreeDisabled) { - ThreadState* state = ThreadState::Current(); - state->SetGCState(ThreadState::kIncrementalMarkingStepScheduled); - Persistent<Object> obj1 = MakeGarbageCollected<Object>(); - NormalPageArena* arena = static_cast<NormalPageArena*>( - ThreadState::Current()->Heap().Arena(BlinkGC::kHashTableArenaIndex)); - CHECK(arena); - { - size_t before = arena->promptly_freed_size(); - // Create two maps so we don't promptly free at the allocation point. - HeapHashMap<WeakMember<Object>, Member<Object>> weak_map1; - HeapHashMap<WeakMember<Object>, Member<Object>> weak_map2; - weak_map1.insert(obj1, obj1); - weak_map2.insert(obj1, obj1); - weak_map1.clear(); - size_t after = arena->promptly_freed_size(); - // Weak hash table backings should not be promptly freed. - EXPECT_EQ(after, before); - } - { - size_t before = arena->promptly_freed_size(); - // Create two maps so we don't promptly free at the allocation point. - HeapHashMap<Member<Object>, Member<Object>> map1; - HeapHashMap<Member<Object>, Member<Object>> map2; - map1.insert(obj1, obj1); - map2.insert(obj1, obj1); - map1.clear(); - size_t after = arena->promptly_freed_size(); - // Non-weak hash table backings should be promptly freed. - EXPECT_GT(after, before); - } - state->SetGCState(ThreadState::kIncrementalMarkingFinalizeScheduled); - state->SetGCState(ThreadState::kNoGCScheduled); -} - -namespace { - -class RegisteringMixin; -using ObjectRegistry = HeapHashMap<void*, Member<RegisteringMixin>>; - -class RegisteringMixin : public GarbageCollectedMixin { - public: - explicit RegisteringMixin(ObjectRegistry* registry) { - HeapObjectHeader* header = HeapObjectHeader::FromPayload( - TraceTrait<RegisteringMixin>::GetTraceDescriptor(this) - .base_object_payload); - EXPECT_TRUE(header->IsInConstruction()); - registry->insert(reinterpret_cast<void*>(this), this); - } -}; - -class RegisteringObject : public GarbageCollected<RegisteringObject>, - public RegisteringMixin { - public: - explicit RegisteringObject(ObjectRegistry* registry) - : RegisteringMixin(registry) {} -}; - -} // namespace - -TEST_F(IncrementalMarkingInternalsTest, WriteBarrierDuringMixinConstruction) { - IncrementalMarkingScope scope(ThreadState::Current()); - ObjectRegistry registry; - RegisteringObject* object = - MakeGarbageCollected<RegisteringObject>(®istry); - - // Clear any objects that have been added to the regular marking worklist in - // the process of calling the constructor. - MarkingItem marking_item; - while (scope.marking_worklist()->Pop(WorklistTaskId::MutatorThread, - &marking_item)) { - HeapObjectHeader* header = - HeapObjectHeader::FromPayload(marking_item.base_object_payload); - if (header->IsMarked()) - header->Unmark(); - } - EXPECT_TRUE(scope.marking_worklist()->IsGlobalEmpty()); - // Clear any write barriers so far. - HeapObjectHeader* header; - while (scope.write_barrier_worklist()->Pop(WorklistTaskId::MutatorThread, - &header)) { - if (header->IsMarked()) - header->Unmark(); - } - EXPECT_TRUE(scope.write_barrier_worklist()->IsGlobalEmpty()); - - EXPECT_FALSE(scope.not_fully_constructed_worklist()->IsGlobalEmpty()); - NotFullyConstructedItem partial_item; - bool found_mixin_object = false; - // The same object may be on the marking work list because of expanding - // and rehashing of the backing store in the registry. - while (scope.not_fully_constructed_worklist()->Pop( - WorklistTaskId::MutatorThread, &partial_item)) { - if (object == partial_item) - found_mixin_object = true; - HeapObjectHeader* hdr = HeapObjectHeader::FromPayload(partial_item); - if (hdr->IsMarked()) - hdr->Unmark(); - } - EXPECT_TRUE(found_mixin_object); - EXPECT_TRUE(scope.not_fully_constructed_worklist()->IsGlobalEmpty()); -} - -TEST_F(IncrementalMarkingInternalsTest, OverrideAfterMixinConstruction) { - ObjectRegistry registry; - RegisteringMixin* mixin = MakeGarbageCollected<RegisteringObject>(®istry); - HeapObjectHeader* header = HeapObjectHeader::FromPayload( - TraceTrait<RegisteringMixin>::GetTraceDescriptor(mixin) - .base_object_payload); - - EXPECT_FALSE(header->IsInConstruction()); -} - -// ============================================================================= -// Tests that execute complete incremental garbage collections. ================ -// ============================================================================= - -TEST_F(IncrementalMarkingInternalsTest, - HasInlineCapacityCollectionWithHeapCompaction) { - using Store = HeapVector<Member<Object>, 2>; - - Persistent<Store> persistent(MakeGarbageCollected<Store>()); - Persistent<Store> persistent2(MakeGarbageCollected<Store>()); - - IncrementalMarkingTestDriver driver(ThreadState::Current()); - ThreadState::Current()->EnableCompactionForNextGCForTesting(); - persistent->push_back(MakeGarbageCollected<Object>()); - driver.StartGC(); - driver.FinishGC(); - - // Should collect also slots that has only inline buffer and nullptr - // references. -#if defined(ANNOTATE_CONTIGUOUS_CONTAINER) - // When ANNOTATE_CONTIGUOUS_CONTAINER is defined, inline capacity is ignored. - EXPECT_EQ(driver.GetHeapCompactLastFixupCount(), 1u); -#else - EXPECT_EQ(driver.GetHeapCompactLastFixupCount(), 2u); -#endif -} - -TEST_F(IncrementalMarkingInternalsTest, WeakHashMapHeapCompaction) { - using Store = HeapHashCountedSet<WeakMember<Object>>; - - Persistent<Store> persistent(MakeGarbageCollected<Store>()); - - IncrementalMarkingTestDriver driver(ThreadState::Current()); - ThreadState::Current()->EnableCompactionForNextGCForTesting(); - driver.StartGC(); - driver.TriggerMarkingSteps(); - persistent->insert(MakeGarbageCollected<Object>()); - driver.FinishGC(); - - // Weak callback should register the slot. - EXPECT_EQ(1u, driver.GetHeapCompactLastFixupCount()); -} - -TEST_F(IncrementalMarkingInternalsTest, - ConservativeGCWhileCompactionScheduled) { - using Store = HeapVector<Member<Object>>; - Persistent<Store> persistent(MakeGarbageCollected<Store>()); - persistent->push_back(MakeGarbageCollected<Object>()); - - IncrementalMarkingTestDriver driver(ThreadState::Current()); - ThreadState::Current()->EnableCompactionForNextGCForTesting(); - driver.StartGC(); - driver.TriggerMarkingSteps(); - ThreadState::Current()->CollectGarbageForTesting( - BlinkGC::CollectionType::kMajor, BlinkGC::kHeapPointersOnStack, - BlinkGC::kAtomicMarking, BlinkGC::kConcurrentAndLazySweeping, - BlinkGC::GCReason::kForcedGCForTesting); - - // Heap compaction should be canceled if incremental marking finishes with a - // conservative GC. - EXPECT_EQ(driver.GetHeapCompactLastFixupCount(), 0u); -} - -} // namespace incremental_marking_test -} // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/impl/test/marking_scheduling_oracle_test.cc b/third_party/blink/renderer/platform/heap/impl/test/marking_scheduling_oracle_test.cc deleted file mode 100644 index ad2839d..0000000 --- a/third_party/blink/renderer/platform/heap/impl/test/marking_scheduling_oracle_test.cc +++ /dev/null
@@ -1,98 +0,0 @@ -// Copyright 2020 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/heap/impl/marking_scheduling_oracle.h" - -#include "base/time/time.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/renderer/platform/heap/heap_stats_collector.h" - -namespace blink { - -namespace { -class MarkingSchedulingOracleTest : public testing::Test { - public: - static constexpr size_t kObjectSize = 1024 * 1024 * 1024; -}; -} // namespace - -TEST_F(MarkingSchedulingOracleTest, FirstStepReturnsDefaultDuration) { - MarkingSchedulingOracle oracle; - oracle.SetElapsedTimeForTesting(0); - EXPECT_EQ(MarkingSchedulingOracle::kDefaultIncrementalMarkingStepDuration, - oracle.GetNextIncrementalStepDurationForTask(kObjectSize)); -} - -// If marking is not behind schedule and very small time passed between steps -// the oracle should return the minimum step duration. -TEST_F(MarkingSchedulingOracleTest, NoTimePassedReturnsMinimumDuration) { - MarkingSchedulingOracle oracle; - // Add incrementally marked bytes to tell oracle this is not the first step. - oracle.UpdateIncrementalMarkingStats( - MarkingSchedulingOracle::kMinimumMarkedBytesInStep, - base::TimeDelta::FromMilliseconds(1), - base::TimeDelta::FromMilliseconds(0)); - oracle.SetElapsedTimeForTesting(0); - // Given marking speed set above, Minimum duration should be 1ms. - EXPECT_EQ(1, oracle.GetNextIncrementalStepDurationForTask(kObjectSize) - .InMilliseconds()); -} - -TEST_F(MarkingSchedulingOracleTest, OracleDoesntExccedMaximumStepDuration) { - MarkingSchedulingOracle oracle; - // Add incrementally marked bytes to tell oracle this is not the first step. - oracle.UpdateIncrementalMarkingStats( - 1, - base::TimeDelta::FromMilliseconds( - MarkingSchedulingOracle::kEstimatedMarkingTimeMs), - base::TimeDelta::FromMilliseconds(0)); - oracle.SetElapsedTimeForTesting( - MarkingSchedulingOracle::kEstimatedMarkingTimeMs); - EXPECT_EQ(MarkingSchedulingOracle::kMaximumIncrementalMarkingStepDuration, - oracle.GetNextIncrementalStepDurationForTask(kObjectSize)); -} - -TEST_F(MarkingSchedulingOracleTest, AheadOfScheduleReturnsMinimumDuration) { - MarkingSchedulingOracle oracle; - // Add incrementally marked bytes to tell oracle this is not the first step. - oracle.UpdateIncrementalMarkingStats( - MarkingSchedulingOracle::kMinimumMarkedBytesInStep, - base::TimeDelta::FromMilliseconds(1), - base::TimeDelta::FromMilliseconds(0)); - oracle.AddConcurrentlyMarkedBytes(0.6 * kObjectSize); - oracle.SetElapsedTimeForTesting( - 0.5 * MarkingSchedulingOracle::kEstimatedMarkingTimeMs); - // Given marking speed set above, Minimum duration should be 1ms. - EXPECT_EQ(1, oracle.GetNextIncrementalStepDurationForTask(kObjectSize) - .InMilliseconds()); -} - -TEST_F(MarkingSchedulingOracleTest, BehindScheduleReturnsCorrectDuration) { - static constexpr size_t kForegoundMarkingTime = 1; - MarkingSchedulingOracle oracle; - oracle.UpdateIncrementalMarkingStats( - 0.1 * kObjectSize, - base::TimeDelta::FromMilliseconds(kForegoundMarkingTime), - base::TimeDelta::FromMilliseconds(0)); - oracle.AddConcurrentlyMarkedBytes(0.25 * kObjectSize); - oracle.SetElapsedTimeForTesting( - 0.5 * MarkingSchedulingOracle::kEstimatedMarkingTimeMs); - EXPECT_EQ(1.5 * kForegoundMarkingTime, - oracle.GetNextIncrementalStepDurationForTask(kObjectSize) - .InMillisecondsF()); - oracle.AddConcurrentlyMarkedBytes(0.05 * kObjectSize); - oracle.SetElapsedTimeForTesting( - 0.5 * MarkingSchedulingOracle::kEstimatedMarkingTimeMs); - EXPECT_EQ(kForegoundMarkingTime, - oracle.GetNextIncrementalStepDurationForTask(kObjectSize) - .InMillisecondsF()); - oracle.AddConcurrentlyMarkedBytes(0.05 * kObjectSize); - oracle.SetElapsedTimeForTesting( - 0.5 * MarkingSchedulingOracle::kEstimatedMarkingTimeMs); - EXPECT_EQ(0.5 * kForegoundMarkingTime, - oracle.GetNextIncrementalStepDurationForTask(kObjectSize) - .InMillisecondsF()); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/impl/test/marking_verifier_test.cc b/third_party/blink/renderer/platform/heap/impl/test/marking_verifier_test.cc deleted file mode 100644 index 2289fc0..0000000 --- a/third_party/blink/renderer/platform/heap/impl/test/marking_verifier_test.cc +++ /dev/null
@@ -1,99 +0,0 @@ -// Copyright 2019 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/heap/impl/marking_verifier.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/renderer/platform/heap/handle.h" -#include "third_party/blink/renderer/platform/heap/heap.h" -#include "third_party/blink/renderer/platform/heap/heap_test_objects.h" -#include "third_party/blink/renderer/platform/heap/heap_test_utilities.h" -#include "third_party/blink/renderer/platform/heap/persistent.h" - -namespace blink { - -#if DCHECK_IS_ON() -class MarkingVerifierDeathTest : public TestSupportingGC {}; - -namespace { - -class ResurrectingPreFinalizer - : public GarbageCollected<ResurrectingPreFinalizer> { - USING_PRE_FINALIZER(ResurrectingPreFinalizer, Dispose); - - public: - enum TestType { - kMember, - kWeakMember, - }; - - class GlobalStorage : public GarbageCollected<GlobalStorage> { - public: - void Trace(Visitor* visitor) const { - visitor->Trace(strong); - visitor->Trace(weak); - } - - Member<LinkedObject> strong; - WeakMember<LinkedObject> weak; - }; - - ResurrectingPreFinalizer(TestType test_type, - GlobalStorage* storage, - LinkedObject* object_that_dies) - : test_type_(test_type), - storage_(storage), - object_that_dies_(object_that_dies) {} - - void Trace(Visitor* visitor) const { - visitor->Trace(storage_); - visitor->Trace(object_that_dies_); - } - - private: - void Dispose() { - switch (test_type_) { - case TestType::kMember: - storage_->strong = object_that_dies_; - break; - case TestType::kWeakMember: - storage_->weak = object_that_dies_; - break; - } - } - - TestType test_type_; - Member<GlobalStorage> storage_; - Member<LinkedObject> object_that_dies_; -}; - -} // namespace - -TEST_F(MarkingVerifierDeathTest, DiesOnResurrectedMember) { - if (!ThreadState::Current()->IsVerifyMarkingEnabled()) - return; - - Persistent<ResurrectingPreFinalizer::GlobalStorage> storage( - MakeGarbageCollected<ResurrectingPreFinalizer::GlobalStorage>()); - MakeGarbageCollected<ResurrectingPreFinalizer>( - ResurrectingPreFinalizer::kMember, storage.Get(), - MakeGarbageCollected<LinkedObject>()); - ASSERT_DEATH_IF_SUPPORTED(PreciselyCollectGarbage(), - "MarkingVerifier: Encountered unmarked object."); -} - -TEST_F(MarkingVerifierDeathTest, DiesOnResurrectedWeakMember) { - if (!ThreadState::Current()->IsVerifyMarkingEnabled()) - return; - - Persistent<ResurrectingPreFinalizer::GlobalStorage> storage( - MakeGarbageCollected<ResurrectingPreFinalizer::GlobalStorage>()); - MakeGarbageCollected<ResurrectingPreFinalizer>( - ResurrectingPreFinalizer::kWeakMember, storage.Get(), - MakeGarbageCollected<LinkedObject>()); - ASSERT_DEATH_IF_SUPPORTED(PreciselyCollectGarbage(), - "MarkingVerifier: Encountered unmarked object."); -} -#endif // DCHECK_IS_ON() - -} // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/impl/test/name_trait_test.cc b/third_party/blink/renderer/platform/heap/impl/test/name_trait_test.cc deleted file mode 100644 index f69cded..0000000 --- a/third_party/blink/renderer/platform/heap/impl/test/name_trait_test.cc +++ /dev/null
@@ -1,69 +0,0 @@ -// 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 <string.h> - -#include "build/build_config.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/renderer/platform/bindings/name_client.h" -#include "third_party/blink/renderer/platform/heap/impl/name_traits.h" - -namespace blink { - -namespace { - -class ClassWithoutName final { - public: - ClassWithoutName() = default; -}; - -class ClassWithName final : public NameClient { - public: - explicit ClassWithName(const char* name) : name_(name) {} - ~ClassWithName() final = default; - - const char* NameInHeapSnapshot() const final { return name_; } - - private: - const char* name_; -}; - -} // namespace - -TEST(NameTraitTest, InternalNamesHiddenInOfficialBuild) { - // Use a test instead of static_assert to allow local builds but block - // enabling the feature accidentally through the waterfall. - // - // Do not include such type information in official builds to - // (a) safe binary size on string literals, and - // (b) avoid exposing internal types until it has been clarified whether - // exposing internals in DevTools is fine. -#if defined(OFFICIAL_BUILD) - EXPECT_TRUE(NameClient::HideInternalName()); -#endif -} - -TEST(NameTraitTest, InternalNamesHiddenWhenFlagIsTurnedOff) { -#if !BUILDFLAG(RAW_HEAP_SNAPSHOTS) - EXPECT_TRUE(NameClient::HideInternalName()); -#endif // BUILDFLAG(RAW_HEAP_SNAPSHOTS) -} - -TEST(NameTraitTest, DefaultName) { - ClassWithoutName no_name; - const char* name = NameTrait<ClassWithoutName>::GetName(&no_name).value; - if (NameClient::HideInternalName()) { - EXPECT_EQ(0, strcmp(name, "InternalNode")); - } else { - EXPECT_NE(nullptr, strstr(name, "ClassWithoutName")); - } -} - -TEST(NameTraitTest, CustomName) { - ClassWithName with_name("CustomName"); - const char* name = NameTrait<ClassWithName>::GetName(&with_name).value; - EXPECT_EQ(0, strcmp(name, "CustomName")); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/impl/test/object_start_bitmap_test.cc b/third_party/blink/renderer/platform/heap/impl/test/object_start_bitmap_test.cc deleted file mode 100644 index cdb20c5c..0000000 --- a/third_party/blink/renderer/platform/heap/impl/test/object_start_bitmap_test.cc +++ /dev/null
@@ -1,172 +0,0 @@ -// Copyright 2017 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/heap/impl/heap_page.h" - -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" - -namespace blink { - -namespace { - -bool IsEmpty(const ObjectStartBitmap& bitmap) { - size_t count = 0; - bitmap.Iterate([&count](Address) { count++; }); - return count == 0; -} - -// Abstraction for objects that hides ObjectStartBitmap::kGranularity and -// the base address as getting either of it wrong will result in failed DCHECKs. -class Object { - STACK_ALLOCATED(); - - public: - static Address kBaseOffset; - - Object(size_t number) : number_(number) { - const size_t max_entries = ObjectStartBitmap::MaxEntries(); - EXPECT_GE(max_entries, number_); - } - - Address address() const { - return kBaseOffset + ObjectStartBitmap::Granularity() * number_; - } - - // Allow implicitly converting Object to Address. - operator Address() const { return address(); } - - private: - const size_t number_; -}; - -Address Object::kBaseOffset = reinterpret_cast<Address>(0x4000); - -} // namespace - -TEST(ObjectStartBitmapTest, MoreThanZeroEntriesPossible) { - const size_t max_entries = ObjectStartBitmap::MaxEntries(); - EXPECT_LT(0u, max_entries); -} - -TEST(ObjectStartBitmapTest, InitialEmpty) { - ObjectStartBitmap bitmap(Object::kBaseOffset); - EXPECT_TRUE(IsEmpty(bitmap)); -} - -TEST(ObjectStartBitmapTest, SetBitImpliesNonEmpty) { - ObjectStartBitmap bitmap(Object::kBaseOffset); - bitmap.SetBit(Object(0)); - EXPECT_FALSE(IsEmpty(bitmap)); -} - -TEST(ObjectStartBitmapTest, SetBitCheckBit) { - ObjectStartBitmap bitmap(Object::kBaseOffset); - Object object(7); - bitmap.SetBit(object); - EXPECT_TRUE(bitmap.CheckBit(object)); -} - -TEST(ObjectStartBitmapTest, SetBitClearbitCheckBit) { - ObjectStartBitmap bitmap(Object::kBaseOffset); - Object object(77); - bitmap.SetBit(object); - bitmap.ClearBit(object); - EXPECT_FALSE(bitmap.CheckBit(object)); -} - -TEST(ObjectStartBitmapTest, SetBitClearBitImpliesEmpty) { - ObjectStartBitmap bitmap(Object::kBaseOffset); - Object object(123); - bitmap.SetBit(object); - bitmap.ClearBit(object); - EXPECT_TRUE(IsEmpty(bitmap)); -} - -TEST(ObjectStartBitmapTest, AdjacentObjectsAtBegin) { - ObjectStartBitmap bitmap(Object::kBaseOffset); - Object object0(0); - Object object1(1); - bitmap.SetBit(object0); - bitmap.SetBit(object1); - EXPECT_FALSE(bitmap.CheckBit(Object(3))); - size_t count = 0; - bitmap.Iterate([&count, object0, object1](Address current) { - if (count == 0) { - EXPECT_EQ(object0.address(), current); - } else if (count == 1) { - EXPECT_EQ(object1.address(), current); - } - count++; - }); - EXPECT_EQ(2u, count); -} - -TEST(ObjectStartBitmapTest, AdjacentObjectsAtEnd) { - ObjectStartBitmap bitmap(Object::kBaseOffset); - const size_t last_entry_index = ObjectStartBitmap::MaxEntries() - 1; - Object object0(last_entry_index - 1); - Object object1(last_entry_index); - bitmap.SetBit(object0); - bitmap.SetBit(object1); - EXPECT_FALSE(bitmap.CheckBit(Object(last_entry_index - 2))); - size_t count = 0; - bitmap.Iterate([&count, object0, object1](Address current) { - if (count == 0) { - EXPECT_EQ(object0.address(), current); - } else if (count == 1) { - EXPECT_EQ(object1.address(), current); - } - count++; - }); - EXPECT_EQ(2u, count); -} - -TEST(ObjectStartBitmapTest, FindHeaderExact) { - ObjectStartBitmap bitmap(Object::kBaseOffset); - Object object(654); - bitmap.SetBit(object); - EXPECT_EQ(object.address(), bitmap.FindHeader(object.address())); -} - -TEST(ObjectStartBitmapTest, FindHeaderApproximate) { - static const size_t kInternalDelta = 37; - ObjectStartBitmap bitmap(Object::kBaseOffset); - Object object(654); - bitmap.SetBit(object); - EXPECT_EQ(object.address(), - bitmap.FindHeader(object.address() + kInternalDelta)); -} - -TEST(ObjectStartBitmapTest, FindHeaderIteratingWholeBitmap) { - ObjectStartBitmap bitmap(Object::kBaseOffset); - Object object_to_find(Object(0)); - Address hint_index = Object(ObjectStartBitmap::MaxEntries() - 1); - bitmap.SetBit(object_to_find); - EXPECT_EQ(object_to_find.address(), bitmap.FindHeader(hint_index)); -} - -TEST(ObjectStartBitmapTest, FindHeaderNextCell) { - // This white box test makes use of the fact that cells are of type uint8_t. - const size_t kCellSize = sizeof(uint8_t); - ObjectStartBitmap bitmap(Object::kBaseOffset); - Object object_to_find(Object(kCellSize - 1)); - Address hint = Object(kCellSize); - bitmap.SetBit(Object(0)); - bitmap.SetBit(object_to_find); - EXPECT_EQ(object_to_find.address(), bitmap.FindHeader(hint)); -} - -TEST(ObjectStartBitmapTest, FindHeaderSameCell) { - // This white box test makes use of the fact that cells are of type uint8_t. - const size_t kCellSize = sizeof(uint8_t); - ObjectStartBitmap bitmap(Object::kBaseOffset); - Object object_to_find(Object(kCellSize - 1)); - bitmap.SetBit(Object(0)); - bitmap.SetBit(object_to_find); - EXPECT_EQ(object_to_find.address(), - bitmap.FindHeader(object_to_find.address())); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/impl/test/thread_state_scheduling_test.cc b/third_party/blink/renderer/platform/heap/impl/test/thread_state_scheduling_test.cc deleted file mode 100644 index 0de0c32..0000000 --- a/third_party/blink/renderer/platform/heap/impl/test/thread_state_scheduling_test.cc +++ /dev/null
@@ -1,69 +0,0 @@ -// 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 "base/run_loop.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/public/common/features.h" -#include "third_party/blink/renderer/platform/heap/heap_test_utilities.h" -#include "third_party/blink/renderer/platform/heap/thread_state_scopes.h" -#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h" -#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h" -#include "third_party/blink/renderer/platform/wtf/functional.h" - -namespace blink { - -namespace { - -void RunLoop() { - base::RunLoop rl; - // Push quit task. - ThreadScheduler::Current()->V8TaskRunner()->PostNonNestableTask( - FROM_HERE, WTF::Bind(rl.QuitWhenIdleClosure())); - rl.Run(); -} - -} // namespace - -class ThreadStateSchedulingTest : public TestSupportingGC { - public: - void SetUp() override { - state_ = ThreadState::Current(); - ClearOutOldGarbage(); - } - - void TearDown() override { - PreciselyCollectGarbage(); - EXPECT_EQ(ThreadState::kNoGCScheduled, state_->GetGCState()); - EXPECT_FALSE(state_->IsMarkingInProgress()); - EXPECT_FALSE(state_->IsSweepingInProgress()); - } - - BlinkGC::GCReason LastReason() const { - return state_->reason_for_scheduled_gc_; - } - - void RunScheduledGC(BlinkGC::StackState stack_state) { - state_->RunScheduledGC(stack_state); - } - - ThreadState* state() { return state_; } - - private: - ThreadState* state_; -}; - -TEST_F(ThreadStateSchedulingTest, RunIncrementalGCForTesting) { - ThreadStateSchedulingTest* test = this; - - EXPECT_EQ(ThreadState::kNoGCScheduled, test->state()->GetGCState()); - test->state()->StartIncrementalMarking( - BlinkGC::GCReason::kForcedGCForTesting); - EXPECT_EQ(ThreadState::kIncrementalMarkingStepScheduled, - test->state()->GetGCState()); - - RunLoop(); - EXPECT_EQ(ThreadState::kNoGCScheduled, test->state()->GetGCState()); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/impl/test/worklist_test.cc b/third_party/blink/renderer/platform/heap/impl/test/worklist_test.cc deleted file mode 100644 index 206e6f4..0000000 --- a/third_party/blink/renderer/platform/heap/impl/test/worklist_test.cc +++ /dev/null
@@ -1,352 +0,0 @@ -// 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. -// -// Copied and adopted from V8. -// -// Copyright 2017 the V8 project 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/heap/impl/worklist.h" - -#include "testing/gtest/include/gtest/gtest.h" - -namespace blink { - -namespace { -class SomeObject {}; -} // namespace - -using TestWorklist = Worklist<SomeObject*, 64 /* entries */, 8 /* tasks */>; - -TEST(WorklistTest, SegmentCreate) { - TestWorklist::Segment segment; - EXPECT_TRUE(segment.IsEmpty()); - EXPECT_EQ(0u, segment.Size()); - EXPECT_FALSE(segment.IsFull()); -} - -TEST(WorklistTest, SegmentPush) { - TestWorklist::Segment segment; - EXPECT_EQ(0u, segment.Size()); - EXPECT_TRUE(segment.Push(nullptr)); - EXPECT_EQ(1u, segment.Size()); -} - -TEST(WorklistTest, SegmentPushPop) { - TestWorklist::Segment segment; - EXPECT_TRUE(segment.Push(nullptr)); - EXPECT_EQ(1u, segment.Size()); - SomeObject dummy; - SomeObject* object = &dummy; - EXPECT_TRUE(segment.Pop(&object)); - EXPECT_EQ(0u, segment.Size()); - EXPECT_EQ(nullptr, object); -} - -TEST(WorklistTest, SegmentIsEmpty) { - TestWorklist::Segment segment; - EXPECT_TRUE(segment.IsEmpty()); - EXPECT_TRUE(segment.Push(nullptr)); - EXPECT_FALSE(segment.IsEmpty()); -} - -TEST(WorklistTest, SegmentIsFull) { - TestWorklist::Segment segment; - EXPECT_FALSE(segment.IsFull()); - for (size_t i = 0; i < TestWorklist::Segment::kCapacity; i++) { - EXPECT_TRUE(segment.Push(nullptr)); - } - EXPECT_TRUE(segment.IsFull()); -} - -TEST(WorklistTest, SegmentClear) { - TestWorklist::Segment segment; - EXPECT_TRUE(segment.Push(nullptr)); - EXPECT_FALSE(segment.IsEmpty()); - segment.Clear(); - EXPECT_TRUE(segment.IsEmpty()); - for (size_t i = 0; i < TestWorklist::Segment::kCapacity; i++) { - EXPECT_TRUE(segment.Push(nullptr)); - } -} - -TEST(WorklistTest, SegmentFullPushFails) { - TestWorklist::Segment segment; - EXPECT_FALSE(segment.IsFull()); - for (size_t i = 0; i < TestWorklist::Segment::kCapacity; i++) { - EXPECT_TRUE(segment.Push(nullptr)); - } - EXPECT_TRUE(segment.IsFull()); - EXPECT_FALSE(segment.Push(nullptr)); -} - -TEST(WorklistTest, SegmentEmptyPopFails) { - TestWorklist::Segment segment; - EXPECT_TRUE(segment.IsEmpty()); - SomeObject* object; - EXPECT_FALSE(segment.Pop(&object)); -} - -TEST(WorklistTest, SegmentUpdateFalse) { - TestWorklist::Segment segment; - SomeObject* object; - object = reinterpret_cast<SomeObject*>(&object); - EXPECT_TRUE(segment.Push(object)); - segment.Update([](SomeObject* object, SomeObject** out) { return false; }); - EXPECT_TRUE(segment.IsEmpty()); -} - -TEST(WorklistTest, SegmentUpdate) { - TestWorklist::Segment segment; - SomeObject* objectA; - objectA = reinterpret_cast<SomeObject*>(&objectA); - SomeObject* objectB; - objectB = reinterpret_cast<SomeObject*>(&objectB); - EXPECT_TRUE(segment.Push(objectA)); - segment.Update([objectB](SomeObject* object, SomeObject** out) { - *out = objectB; - return true; - }); - SomeObject* object; - EXPECT_TRUE(segment.Pop(&object)); - EXPECT_EQ(object, objectB); -} - -TEST(WorklistTest, CreateEmpty) { - TestWorklist worklist; - TestWorklist::View worklist_view(&worklist, 0); - EXPECT_TRUE(worklist_view.IsLocalEmpty()); - EXPECT_TRUE(worklist.IsGlobalEmpty()); -} - -TEST(WorklistTest, LocalPushPop) { - TestWorklist worklist; - TestWorklist::View worklist_view(&worklist, 0); - SomeObject dummy; - SomeObject* retrieved = nullptr; - EXPECT_TRUE(worklist_view.Push(&dummy)); - EXPECT_FALSE(worklist_view.IsLocalEmpty()); - EXPECT_TRUE(worklist_view.Pop(&retrieved)); - EXPECT_EQ(&dummy, retrieved); -} - -TEST(WorklistTest, LocalIsBasedOnId) { - TestWorklist worklist; - // Use the same id. - TestWorklist::View worklist_view1(&worklist, 0); - TestWorklist::View worklist_view2(&worklist, 0); - SomeObject dummy; - SomeObject* retrieved = nullptr; - EXPECT_TRUE(worklist_view1.Push(&dummy)); - EXPECT_FALSE(worklist_view1.IsLocalEmpty()); - EXPECT_FALSE(worklist_view2.IsLocalEmpty()); - EXPECT_TRUE(worklist_view2.Pop(&retrieved)); - EXPECT_EQ(&dummy, retrieved); - EXPECT_TRUE(worklist_view1.IsLocalEmpty()); - EXPECT_TRUE(worklist_view2.IsLocalEmpty()); -} - -TEST(WorklistTest, LocalPushStaysPrivate) { - TestWorklist worklist; - TestWorklist::View worklist_view1(&worklist, 0); - TestWorklist::View worklist_view2(&worklist, 1); - SomeObject dummy; - SomeObject* retrieved = nullptr; - EXPECT_TRUE(worklist.IsGlobalEmpty()); - EXPECT_EQ(0U, worklist.GlobalPoolSize()); - EXPECT_TRUE(worklist_view1.Push(&dummy)); - EXPECT_FALSE(worklist.IsGlobalEmpty()); - EXPECT_EQ(0U, worklist.GlobalPoolSize()); - EXPECT_FALSE(worklist_view2.Pop(&retrieved)); - EXPECT_EQ(nullptr, retrieved); - EXPECT_TRUE(worklist_view1.Pop(&retrieved)); - EXPECT_EQ(&dummy, retrieved); - EXPECT_TRUE(worklist.IsGlobalEmpty()); - EXPECT_EQ(0U, worklist.GlobalPoolSize()); -} - -TEST(WorklistTest, GlobalUpdateNull) { - TestWorklist worklist; - TestWorklist::View worklist_view(&worklist, 0); - SomeObject* object; - object = reinterpret_cast<SomeObject*>(&object); - for (size_t i = 0; i < TestWorklist::kSegmentCapacity; i++) { - EXPECT_TRUE(worklist_view.Push(object)); - } - EXPECT_TRUE(worklist_view.Push(object)); - worklist.Update([](SomeObject* object, SomeObject** out) { return false; }); - EXPECT_TRUE(worklist.IsGlobalEmpty()); - EXPECT_EQ(0U, worklist.GlobalPoolSize()); -} - -TEST(WorklistTest, GlobalUpdate) { - TestWorklist worklist; - TestWorklist::View worklist_view(&worklist, 0); - SomeObject* objectA = nullptr; - objectA = reinterpret_cast<SomeObject*>(&objectA); - SomeObject* objectB = nullptr; - objectB = reinterpret_cast<SomeObject*>(&objectB); - SomeObject* objectC = nullptr; - objectC = reinterpret_cast<SomeObject*>(&objectC); - for (size_t i = 0; i < TestWorklist::kSegmentCapacity; i++) { - EXPECT_TRUE(worklist_view.Push(objectA)); - } - for (size_t i = 0; i < TestWorklist::kSegmentCapacity; i++) { - EXPECT_TRUE(worklist_view.Push(objectB)); - } - EXPECT_TRUE(worklist_view.Push(objectA)); - worklist.Update([objectA, objectC](SomeObject* object, SomeObject** out) { - if (object != objectA) { - *out = objectC; - return true; - } - return false; - }); - for (size_t i = 0; i < TestWorklist::kSegmentCapacity; i++) { - SomeObject* object; - EXPECT_TRUE(worklist_view.Pop(&object)); - EXPECT_EQ(object, objectC); - } -} - -TEST(WorklistTest, FlushToGlobalPushSegment) { - TestWorklist worklist; - TestWorklist::View worklist_view0(&worklist, 0); - TestWorklist::View worklist_view1(&worklist, 1); - SomeObject* object = nullptr; - SomeObject* objectA = nullptr; - objectA = reinterpret_cast<SomeObject*>(&objectA); - EXPECT_TRUE(worklist_view0.Push(objectA)); - worklist.FlushToGlobal(0); - EXPECT_EQ(1U, worklist.GlobalPoolSize()); - EXPECT_TRUE(worklist_view1.Pop(&object)); -} - -TEST(WorklistTest, FlushToGlobalPopSegment) { - TestWorklist worklist; - TestWorklist::View worklist_view0(&worklist, 0); - TestWorklist::View worklist_view1(&worklist, 1); - SomeObject* object = nullptr; - SomeObject* objectA = nullptr; - objectA = reinterpret_cast<SomeObject*>(&objectA); - EXPECT_TRUE(worklist_view0.Push(objectA)); - EXPECT_TRUE(worklist_view0.Push(objectA)); - EXPECT_TRUE(worklist_view0.Pop(&object)); - worklist.FlushToGlobal(0); - EXPECT_EQ(1U, worklist.GlobalPoolSize()); - EXPECT_TRUE(worklist_view1.Pop(&object)); -} - -TEST(WorklistTest, Clear) { - TestWorklist worklist; - TestWorklist::View worklist_view(&worklist, 0); - SomeObject* object; - object = reinterpret_cast<SomeObject*>(&object); - for (size_t i = 0; i < TestWorklist::kSegmentCapacity; i++) { - EXPECT_TRUE(worklist_view.Push(object)); - } - EXPECT_TRUE(worklist_view.Push(object)); - EXPECT_EQ(1U, worklist.GlobalPoolSize()); - worklist.Clear(); - EXPECT_TRUE(worklist.IsGlobalEmpty()); - EXPECT_EQ(0U, worklist.GlobalPoolSize()); -} - -TEST(WorklistTest, SingleSegmentSteal) { - TestWorklist worklist; - TestWorklist::View worklist_view1(&worklist, 0); - TestWorklist::View worklist_view2(&worklist, 1); - SomeObject dummy; - for (size_t i = 0; i < TestWorklist::kSegmentCapacity; i++) { - EXPECT_TRUE(worklist_view1.Push(&dummy)); - } - SomeObject* retrieved = nullptr; - // One more push/pop to publish the full segment. - EXPECT_TRUE(worklist_view1.Push(nullptr)); - EXPECT_TRUE(worklist_view1.Pop(&retrieved)); - EXPECT_EQ(nullptr, retrieved); - EXPECT_EQ(1U, worklist.GlobalPoolSize()); - // Stealing. - for (size_t i = 0; i < TestWorklist::kSegmentCapacity; i++) { - EXPECT_TRUE(worklist_view2.Pop(&retrieved)); - EXPECT_EQ(&dummy, retrieved); - EXPECT_FALSE(worklist_view1.Pop(&retrieved)); - } - EXPECT_TRUE(worklist.IsGlobalEmpty()); - EXPECT_EQ(0U, worklist.GlobalPoolSize()); -} - -TEST(WorklistTest, MultipleSegmentsStolen) { - TestWorklist worklist; - TestWorklist::View worklist_view1(&worklist, 0); - TestWorklist::View worklist_view2(&worklist, 1); - TestWorklist::View worklist_view3(&worklist, 2); - SomeObject dummy1; - SomeObject dummy2; - for (size_t i = 0; i < TestWorklist::kSegmentCapacity; i++) { - EXPECT_TRUE(worklist_view1.Push(&dummy1)); - } - for (size_t i = 0; i < TestWorklist::kSegmentCapacity; i++) { - EXPECT_TRUE(worklist_view1.Push(&dummy2)); - } - SomeObject* retrieved = nullptr; - SomeObject dummy3; - // One more push/pop to publish the full segment. - EXPECT_TRUE(worklist_view1.Push(&dummy3)); - EXPECT_TRUE(worklist_view1.Pop(&retrieved)); - EXPECT_EQ(&dummy3, retrieved); - EXPECT_EQ(2U, worklist.GlobalPoolSize()); - // Stealing. - EXPECT_TRUE(worklist_view2.Pop(&retrieved)); - SomeObject* const expect_bag2 = retrieved; - EXPECT_TRUE(worklist_view3.Pop(&retrieved)); - SomeObject* const expect_bag3 = retrieved; - EXPECT_EQ(0U, worklist.GlobalPoolSize()); - EXPECT_NE(expect_bag2, expect_bag3); - EXPECT_TRUE(expect_bag2 == &dummy1 || expect_bag2 == &dummy2); - EXPECT_TRUE(expect_bag3 == &dummy1 || expect_bag3 == &dummy2); - for (size_t i = 1; i < TestWorklist::kSegmentCapacity; i++) { - EXPECT_TRUE(worklist_view2.Pop(&retrieved)); - EXPECT_EQ(expect_bag2, retrieved); - EXPECT_FALSE(worklist_view1.Pop(&retrieved)); - } - for (size_t i = 1; i < TestWorklist::kSegmentCapacity; i++) { - EXPECT_TRUE(worklist_view3.Pop(&retrieved)); - EXPECT_EQ(expect_bag3, retrieved); - EXPECT_FALSE(worklist_view1.Pop(&retrieved)); - } - EXPECT_TRUE(worklist.IsGlobalEmpty()); -} - -TEST(WorklistTest, MergeGlobalPool) { - TestWorklist worklist1; - TestWorklist::View worklist_view1(&worklist1, 0); - SomeObject dummy; - for (size_t i = 0; i < TestWorklist::kSegmentCapacity; i++) { - EXPECT_TRUE(worklist_view1.Push(&dummy)); - } - SomeObject* retrieved = nullptr; - // One more push/pop to publish the full segment. - EXPECT_TRUE(worklist_view1.Push(nullptr)); - EXPECT_TRUE(worklist_view1.Pop(&retrieved)); - EXPECT_EQ(nullptr, retrieved); - EXPECT_EQ(1U, worklist1.GlobalPoolSize()); - // Merging global pool into a new Worklist. - TestWorklist worklist2; - TestWorklist::View worklist_view2(&worklist2, 0); - EXPECT_EQ(0U, worklist2.GlobalPoolSize()); - worklist2.MergeGlobalPool(&worklist1); - EXPECT_EQ(1U, worklist2.GlobalPoolSize()); - EXPECT_FALSE(worklist2.IsGlobalEmpty()); - for (size_t i = 0; i < TestWorklist::kSegmentCapacity; i++) { - EXPECT_TRUE(worklist_view2.Pop(&retrieved)); - EXPECT_EQ(&dummy, retrieved); - EXPECT_FALSE(worklist_view1.Pop(&retrieved)); - } - EXPECT_TRUE(worklist1.IsGlobalEmpty()); - EXPECT_TRUE(worklist2.IsGlobalEmpty()); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/impl/thread_state.cc b/third_party/blink/renderer/platform/heap/impl/thread_state.cc deleted file mode 100644 index 101dc30..0000000 --- a/third_party/blink/renderer/platform/heap/impl/thread_state.cc +++ /dev/null
@@ -1,1798 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "third_party/blink/renderer/platform/heap/thread_state.h" - -#include <algorithm> -#include <iomanip> -#include <limits> -#include <memory> - -#include "base/atomicops.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/memory/scoped_refptr.h" -#include "base/numerics/safe_conversions.h" -#include "base/task_runner.h" -#include "base/trace_event/process_memory_dump.h" -#include "build/build_config.h" -#include "third_party/blink/public/common/features.h" -#include "third_party/blink/public/platform/platform.h" -#include "third_party/blink/renderer/platform/bindings/active_script_wrappable_base.h" -#include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h" -#include "third_party/blink/renderer/platform/bindings/runtime_call_stats.h" -#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h" -#include "third_party/blink/renderer/platform/bindings/script_wrappable.h" -#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h" -#include "third_party/blink/renderer/platform/bindings/wrapper_type_info.h" -#include "third_party/blink/renderer/platform/heap/blink_gc.h" -#include "third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider.h" -#include "third_party/blink/renderer/platform/heap/handle.h" -#include "third_party/blink/renderer/platform/heap/heap.h" -#include "third_party/blink/renderer/platform/heap/heap_buildflags.h" -#include "third_party/blink/renderer/platform/heap/heap_stats_collector.h" -#include "third_party/blink/renderer/platform/heap/impl/heap_compact.h" -#include "third_party/blink/renderer/platform/heap/impl/marking_scheduling_oracle.h" -#include "third_party/blink/renderer/platform/heap/impl/marking_visitor.h" -#include "third_party/blink/renderer/platform/heap/impl/page_pool.h" -#include "third_party/blink/renderer/platform/heap/persistent.h" -#include "third_party/blink/renderer/platform/heap/thread_state_scopes.h" -#include "third_party/blink/renderer/platform/heap/unified_heap_controller.h" -#include "third_party/blink/renderer/platform/heap/unified_heap_marking_visitor.h" -#include "third_party/blink/renderer/platform/heap/visitor.h" -#include "third_party/blink/renderer/platform/instrumentation/histogram.h" -#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h" -#include "third_party/blink/renderer/platform/instrumentation/tracing/web_memory_allocator_dump.h" -#include "third_party/blink/renderer/platform/instrumentation/tracing/web_process_memory_dump.h" -#include "third_party/blink/renderer/platform/scheduler/public/post_cancellable_task.h" -#include "third_party/blink/renderer/platform/scheduler/public/thread.h" -#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h" -#include "third_party/blink/renderer/platform/scheduler/public/worker_pool.h" -#include "third_party/blink/renderer/platform/wtf/allocator/partitions.h" -#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h" -#include "third_party/blink/renderer/platform/wtf/stack_util.h" -#include "third_party/blink/renderer/platform/wtf/threading_primitives.h" -#include "v8/include/v8-profiler.h" -#include "v8/include/v8.h" - -#if defined(OS_WIN) -#include <stddef.h> -#include <windows.h> -#include <winnt.h> -#endif - -#if defined(MEMORY_SANITIZER) -#include <sanitizer/msan_interface.h> -#endif - -#if defined(OS_FREEBSD) -#include <pthread_np.h> -#endif - -namespace blink { - -WTF::ThreadSpecific<ThreadState*>* ThreadState::thread_specific_ = nullptr; -uint8_t ThreadState::main_thread_state_storage_[sizeof(ThreadState)]; - -namespace { - -constexpr double kMarkingScheduleRatioBeforeConcurrentPriorityIncrease = 0.5; - -// Helper function to convert a byte count to a KB count, capping at -// INT_MAX if the number is larger than that. -constexpr base::Histogram::Sample CappedSizeInKB(size_t size_in_bytes) { - return base::saturated_cast<base::Histogram::Sample>(size_in_bytes / 1024); -} - -class WorkerPoolTaskRunner : public base::TaskRunner { - public: - bool PostDelayedTask(const base::Location& location, - base::OnceClosure task, - base::TimeDelta) override { - worker_pool::PostTask(location, WTF::CrossThreadBindOnce(std::move(task))); - return true; - } -}; - -} // namespace - -class ThreadState::IncrementalMarkingScheduler { - public: - explicit IncrementalMarkingScheduler(ThreadState* thread_state) - : thread_state_(thread_state) {} - - // Starts incremental marking with further scheduled steps. - void Start(BlinkGC::GCReason reason) { - Init(reason); - thread_state_->IncrementalMarkingStart(reason_); - ScheduleTask(); - } - - void Restart() { - DCHECK(!task_.IsActive()); - ScheduleTask(); - } - - // Cancels incremental marking task in case there is any pending. - void Cancel() { task_.Cancel(); } - - private: - void Init(BlinkGC::GCReason reason) { - DCHECK(!task_.IsActive()); - reason_ = reason; - } - - void ScheduleTask() { - // Reassigning to the task will cancel the currently scheduled one. - task_ = PostNonNestableCancellableTask( - *ThreadScheduler::Current()->V8TaskRunner(), FROM_HERE, - WTF::Bind(&IncrementalMarkingScheduler::Dispatch, - WTF::Unretained(this))); - } - - void Dispatch() { - switch (thread_state_->GetGCState()) { - case ThreadState::kIncrementalMarkingStepScheduled: - thread_state_->IncrementalMarkingStep(BlinkGC::kNoHeapPointersOnStack); - if (thread_state_->GetGCState() != - ThreadState::kIncrementalMarkingStepPaused) { - ScheduleTask(); - } - break; - case ThreadState::kIncrementalMarkingFinalizeScheduled: - thread_state_->IncrementalMarkingFinalize(); - break; - default: - break; - } - } - - ThreadState* thread_state_; - BlinkGC::GCReason reason_; - TaskHandle task_; -}; - -ThreadState::ThreadState() - : thread_(CurrentThread()), - persistent_region_(std::make_unique<PersistentRegion>()), - weak_persistent_region_(std::make_unique<PersistentRegion>()), - start_of_stack_(reinterpret_cast<Address*>(WTF::GetStackStart())), -#if defined(ADDRESS_SANITIZER) - asan_fake_stack_(__asan_get_current_fake_stack()), -#endif - incremental_marking_scheduler_( - std::make_unique<IncrementalMarkingScheduler>(this)) { - DCHECK(CheckThread()); - DCHECK(!**thread_specific_); - **thread_specific_ = this; - heap_ = std::make_unique<ThreadHeap>(this); -} - -ThreadState::~ThreadState() { - DCHECK(CheckThread()); - if (IsMainThread()) - DCHECK_EQ(0u, Heap().stats_collector()->allocated_space_bytes()); - CHECK(GetGCState() == ThreadState::kNoGCScheduled); - - **thread_specific_ = nullptr; -} - -ThreadState* ThreadState::AttachMainThreadForTesting(v8::Platform*) { - return AttachMainThread(); -} - -ThreadState* ThreadState::AttachMainThread() { - thread_specific_ = new WTF::ThreadSpecific<ThreadState*>(); - return new (main_thread_state_storage_) ThreadState(); -} - -ThreadState* ThreadState::AttachCurrentThread() { - return new ThreadState(); -} - -ThreadState* ThreadState::AttachCurrentThreadForTesting(v8::Platform*) { - return AttachCurrentThread(); -} - -void ThreadState::DetachCurrentThread() { - ThreadState* state = Current(); - DCHECK(!state->IsMainThread()); - state->RunTerminationGC(); - delete state; -} - -namespace { - -// See platform/heap/v8_wrapper/thread_state.cc version for details. -class BlinkRootsHandler final : public v8::EmbedderRootsHandler { - public: - explicit BlinkRootsHandler(ThreadState& thread_state) - : thread_state_(thread_state) {} - ~BlinkRootsHandler() final = default; - - bool IsRoot(const v8::TracedReference<v8::Value>& handle) final { - const uint16_t class_id = handle.WrapperClassId(); - // Stand-alone reference or kCustomWrappableId. Keep as root as - // we don't know better. - if (class_id != WrapperTypeInfo::kNodeClassId && - class_id != WrapperTypeInfo::kObjectClassId) - return true; - - const v8::TracedReference<v8::Object>& traced = - handle.template As<v8::Object>(); - if (ToWrapperTypeInfo(traced)->IsActiveScriptWrappable() && - ToScriptWrappable(traced)->HasPendingActivity()) { - return true; - } - - if (ToScriptWrappable(traced)->HasEventListeners()) { - return true; - } - - return false; - } - - bool IsRoot(const v8::TracedGlobal<v8::Value>& handle) final { - CHECK(false) << "Blink does not use v8::TracedGlobal."; - return false; - } - - void ResetRoot(const v8::TracedReference<v8::Value>& handle) final { - const uint16_t class_id = handle.WrapperClassId(); - // Only consider handles that have not been treated as roots, see - // IsRootForNonTracingGCInternal. - if (class_id != WrapperTypeInfo::kNodeClassId && - class_id != WrapperTypeInfo::kObjectClassId) - return; - - // Clearing the wrapper below adjusts the DOM wrapper store which may - // re-allocate its backing. We have to avoid report memory to V8 as that may - // trigger GC during GC. - ThreadState::GCForbiddenScope no_gc(&thread_state_); - const v8::TracedReference<v8::Object>& traced = handle.As<v8::Object>(); - bool success = DOMWrapperWorld::UnsetSpecificWrapperIfSet( - ToScriptWrappable(traced), traced); - // Since V8 found a handle, Blink needs to find it as well when trying to - // remove it. - CHECK(success); - } - - private: - ThreadState& thread_state_; -}; - -} // namespace - -void ThreadState::AttachToIsolate( - v8::Isolate* isolate, - V8BuildEmbedderGraphCallback v8_build_embedder_graph) { - DCHECK(isolate); - isolate_ = isolate; - v8_build_embedder_graph_ = v8_build_embedder_graph; - unified_heap_controller_ = std::make_unique<UnifiedHeapController>(this); - isolate_->SetEmbedderHeapTracer(unified_heap_controller_.get()); - unified_heap_controller_.get()->SetStackStart(WTF::GetStackStart()); - if (v8::HeapProfiler* profiler = isolate->GetHeapProfiler()) { - profiler->AddBuildEmbedderGraphCallback(v8_build_embedder_graph, nullptr); - } - embedder_roots_handler_ = std::make_unique<BlinkRootsHandler>(*this); - isolate_->SetEmbedderRootsHandler(embedder_roots_handler_.get()); -} - -void ThreadState::DetachFromIsolate() { - FinishIncrementalMarkingIfRunning( - BlinkGC::CollectionType::kMajor, BlinkGC::kHeapPointersOnStack, - BlinkGC::kAtomicMarking, BlinkGC::kEagerSweeping, - BlinkGC::GCReason::kThreadTerminationGC); - if (isolate_) { - isolate_->SetEmbedderHeapTracer(nullptr); - if (v8::HeapProfiler* profiler = isolate_->GetHeapProfiler()) { - profiler->RemoveBuildEmbedderGraphCallback(v8_build_embedder_graph_, - nullptr); - } - isolate_->SetEmbedderRootsHandler(nullptr); - } - isolate_ = nullptr; - v8_build_embedder_graph_ = nullptr; - unified_heap_controller_.reset(); -} - -void ThreadState::RunTerminationGC() { - DCHECK(!IsMainThread()); - DCHECK(CheckThread()); - - FinishIncrementalMarkingIfRunning(BlinkGC::CollectionType::kMajor, - BlinkGC::kNoHeapPointersOnStack, - BlinkGC::kIncrementalAndConcurrentMarking, - BlinkGC::kConcurrentAndLazySweeping, - BlinkGC::GCReason::kThreadTerminationGC); - // Finish sweeping. - CompleteSweep(); - - // The constant specifies how many rounds of GCs should at most be needed to - // clean up the heap. If we crash below this means that there's finalizers - // adding more objects and roots than the GC is able to clean up. - constexpr size_t kMaxTerminationGCsForHeapCleanup = 20; - size_t i = 0; - do { - CHECK_LT(i++, kMaxTerminationGCsForHeapCleanup); - // Remove strong cross-thread roots. - ProcessHeap::GetCrossThreadPersistentRegion() - .PrepareForThreadStateTermination(this); - // Remove regular roots. - GetPersistentRegion()->PrepareForThreadStateTermination(this); - CHECK_EQ(0, GetPersistentRegion()->NodesInUse()); - CollectGarbage(BlinkGC::CollectionType::kMajor, - BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking, - BlinkGC::kEagerSweeping, - BlinkGC::GCReason::kThreadTerminationGC); - } while (GetPersistentRegion()->NodesInUse() != 0); - - // All of pre-finalizers should be consumed. - CHECK(ordered_pre_finalizers_.empty()); - CHECK_EQ(GetGCState(), kNoGCScheduled); - - Heap().RemoveAllPages(); -} - -NO_SANITIZE_ADDRESS -void ThreadState::VisitAsanFakeStackForPointer(MarkingVisitor* visitor, - Address ptr, - Address* start_of_stack, - Address* end_of_stack) { -#if defined(ADDRESS_SANITIZER) - Address* fake_frame_start = nullptr; - Address* fake_frame_end = nullptr; - Address* maybe_fake_frame = reinterpret_cast<Address*>(ptr); - Address* real_frame_for_fake_frame = reinterpret_cast<Address*>( - __asan_addr_is_in_fake_stack(asan_fake_stack_, maybe_fake_frame, - reinterpret_cast<void**>(&fake_frame_start), - reinterpret_cast<void**>(&fake_frame_end))); - if (real_frame_for_fake_frame) { - // This is a fake frame from the asan fake stack. - if (real_frame_for_fake_frame > end_of_stack && - start_of_stack > real_frame_for_fake_frame) { - // The real stack address for the asan fake frame is - // within the stack range that we need to scan so we need - // to visit the values in the fake frame. - for (Address* p = fake_frame_start; p < fake_frame_end; ++p) - heap_->CheckAndMarkPointer(visitor, *p); - } - } -#endif // ADDRESS_SANITIZER -} - -// Stack scanning may overrun the bounds of local objects and/or race with -// other threads that use this stack. -NO_SANITIZE_ADDRESS -NO_SANITIZE_HWADDRESS -NO_SANITIZE_THREAD -void ThreadState::VisitStackImpl(MarkingVisitor* visitor, - Address* start_of_stack, - Address* end_of_stack) { - DCHECK_EQ(current_gc_data_.stack_state, BlinkGC::kHeapPointersOnStack); - - // Ensure that current is aligned by address size otherwise the loop below - // will read past start address. - Address* current = reinterpret_cast<Address*>( - reinterpret_cast<intptr_t>(end_of_stack) & ~(sizeof(Address) - 1)); - - for (; current < start_of_stack; ++current) { - Address ptr = *current; -#if defined(MEMORY_SANITIZER) - // |ptr| may be uninitialized by design. Mark it as initialized to keep - // MSan from complaining. - // Note: it may be tempting to get rid of |ptr| and simply use |current| - // here, but that would be incorrect. We intentionally use a local - // variable because we don't want to unpoison the original stack. - __msan_unpoison(&ptr, sizeof(ptr)); -#endif - heap_->CheckAndMarkPointer(visitor, ptr); - VisitAsanFakeStackForPointer(visitor, ptr, start_of_stack, end_of_stack); - } -} - -void ThreadState::VisitStack(MarkingVisitor* visitor, Address* end_of_stack) { - VisitStackImpl(visitor, start_of_stack_, end_of_stack); -} - -void ThreadState::VisitUnsafeStack(MarkingVisitor* visitor) { -#if HAS_FEATURE(safe_stack) - VisitStackImpl(visitor, - static_cast<Address*>(__builtin___get_unsafe_stack_top()), - static_cast<Address*>(__builtin___get_unsafe_stack_ptr())); -#endif // HAS_FEATURE(safe_stack) -} - -void ThreadState::VisitPersistents(Visitor* visitor) { - ThreadHeapStatsCollector::Scope stats_scope( - Heap().stats_collector(), - ThreadHeapStatsCollector::kVisitPersistentRoots); - { - ThreadHeapStatsCollector::Scope inner_stats_scope( - Heap().stats_collector(), - ThreadHeapStatsCollector::kVisitCrossThreadPersistents); - ProcessHeap::CrossThreadPersistentMutex().AssertAcquired(); - ProcessHeap::GetCrossThreadPersistentRegion().TraceNodes(visitor); - } - { - ThreadHeapStatsCollector::Scope inner_stats_scope( - Heap().stats_collector(), ThreadHeapStatsCollector::kVisitPersistents); - persistent_region_->TraceNodes(visitor); - } -} - -void ThreadState::VisitRememberedSets(MarkingVisitor* visitor) { - ThreadHeapStatsCollector::EnabledScope stats_scope( - Heap().stats_collector(), ThreadHeapStatsCollector::kVisitRememberedSets); - Heap().VisitRememberedSets(visitor); -} - -void ThreadState::VisitWeakPersistents(Visitor* visitor) { - ProcessHeap::GetCrossThreadWeakPersistentRegion().TraceNodes(visitor); - weak_persistent_region_->TraceNodes(visitor); -} - -void ThreadState::ScheduleForcedGCForTesting() { - DCHECK(CheckThread()); - CompleteSweep(); - SetGCState(kForcedGCForTestingScheduled); -} - -void ThreadState::ScheduleGCIfNeeded() { - VLOG(2) << "[state:" << this << "] ScheduleGCIfNeeded"; - DCHECK(CheckThread()); - - // Allocation is allowed during sweeping, but those allocations should not - // trigger nested GCs. - if (IsGCForbidden() || SweepForbidden()) - return; - - // This method should not call out to V8 during unified heap garbage - // collections. Specifically, reporting memory to V8 may trigger a marking - // step which is not allowed during construction of an object. The reason is - // that a parent object's constructor is potentially being invoked which may - // have already published the object. In that case the object may be colored - // black in a v8 marking step which invalidates the assumption that write - // barriers may be avoided when constructing an object as it is white. - if (IsUnifiedGCMarkingInProgress()) - return; - - if (GetGCState() == kNoGCScheduled && - base::FeatureList::IsEnabled( - blink::features::kBlinkHeapIncrementalMarkingStress)) { - VLOG(2) << "[state:" << this << "] " - << "ScheduleGCIfNeeded: Scheduled incremental marking for testing"; - StartIncrementalMarking(BlinkGC::GCReason::kForcedGCForTesting); - return; - } -} - -ThreadState* ThreadState::FromObject(const void* object) { - DCHECK(object); - BasePage* page = PageFromObject(object); - DCHECK(page); - DCHECK(page->Arena()); - return page->Arena()->GetThreadState(); -} - -void ThreadState::PerformIdleLazySweep(base::TimeTicks deadline) { - DCHECK(CheckThread()); - - // If we are not in a sweeping phase, there is nothing to do here. - if (!IsSweepingInProgress()) - return; - - // This check is here to prevent performIdleLazySweep() from being called - // recursively. I'm not sure if it can happen but it would be safer to have - // the check just in case. - if (SweepForbidden()) - return; - - if (!AdvanceLazySweep(deadline)) { - ScheduleIdleLazySweep(); - } -} - -bool ThreadState::AdvanceLazySweep(base::TimeTicks deadline) { - DCHECK(CheckThread()); - DCHECK(IsSweepingInProgress()); - DCHECK(!SweepForbidden()); - - RUNTIME_CALL_TIMER_SCOPE_IF_ISOLATE_EXISTS( - GetIsolate(), RuntimeCallStats::CounterId::kPerformIdleLazySweep); - - bool sweep_completed = false; - { - AtomicPauseScope atomic_pause_scope(this); - ScriptForbiddenScope script_forbidden_scope; - SweepForbiddenScope scope(this); - ThreadHeapStatsCollector::EnabledScope stats_scope( - Heap().stats_collector(), ThreadHeapStatsCollector::kLazySweepInIdle, - "idleDeltaInSeconds", (deadline - base::TimeTicks::Now()).InSecondsF()); - sweep_completed = Heap().AdvanceLazySweep(deadline); - // We couldn't finish the sweeping within the deadline. - // We request another idle task for the remaining sweeping. - if (sweep_completed) { - SynchronizeAndFinishConcurrentSweeping(); - } - } - - if (sweep_completed) { - NotifySweepDone(); - } - return sweep_completed; -} - -void ThreadState::PerformConcurrentSweep(base::JobDelegate* job) { - VLOG(2) << "[state:" << this << "] [threadid:" << CurrentThread() << "] " - << "ConcurrentSweep"; - ThreadHeapStatsCollector::EnabledConcurrentScope stats_scope( - Heap().stats_collector(), - ThreadHeapStatsCollector::kConcurrentSweepingStep); - - if (Heap().AdvanceConcurrentSweep(job)) - has_unswept_pages_.store(false, std::memory_order_relaxed); -} - -void ThreadState::StartIncrementalMarking(BlinkGC::GCReason reason) { - DCHECK(CheckThread()); - // Schedule an incremental GC only when no GC is scheduled. Otherwise, already - // scheduled GCs should be prioritized. - if (GetGCState() != kNoGCScheduled) { - return; - } - CompleteSweep(); - reason_for_scheduled_gc_ = reason; - SetGCState(kIncrementalGCScheduled); - incremental_marking_scheduler_->Start(reason); -} - -void ThreadState::ScheduleIdleLazySweep() { - ThreadScheduler::Current()->PostIdleTask( - FROM_HERE, - WTF::Bind(&ThreadState::PerformIdleLazySweep, WTF::Unretained(this))); -} - -void ThreadState::ScheduleConcurrentAndLazySweep() { - ScheduleIdleLazySweep(); - - if (!base::FeatureList::IsEnabled( - blink::features::kBlinkHeapConcurrentSweeping)) { - return; - } - - has_unswept_pages_ = true; - sweeper_handle_ = base::PostJob( - FROM_HERE, - {base::TaskPriority::USER_VISIBLE, - base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, - ConvertToBaseRepeatingCallback( - WTF::CrossThreadBindRepeating(&ThreadState::PerformConcurrentSweep, - WTF::CrossThreadUnretained(this))), - ConvertToBaseRepeatingCallback(WTF::CrossThreadBindRepeating( - [](ThreadState* state, size_t /*worker_count*/) -> size_t { - return state->has_unswept_pages_.load(std::memory_order_relaxed) - ? 1 - : 0; - }, - WTF::CrossThreadUnretained(this)))); -} - -namespace { - -#define UNEXPECTED_GCSTATE(s) \ - case ThreadState::s: \ - LOG(FATAL) << "Unexpected transition while in GCState " #s; \ - return - -void UnexpectedGCState(ThreadState::GCState gc_state) { - switch (gc_state) { - UNEXPECTED_GCSTATE(kNoGCScheduled); - UNEXPECTED_GCSTATE(kForcedGCForTestingScheduled); - UNEXPECTED_GCSTATE(kIncrementalMarkingStepPaused); - UNEXPECTED_GCSTATE(kIncrementalMarkingStepScheduled); - UNEXPECTED_GCSTATE(kIncrementalMarkingFinalizeScheduled); - UNEXPECTED_GCSTATE(kIncrementalGCScheduled); - } -} - -#undef UNEXPECTED_GCSTATE - -} // namespace - -#define VERIFY_STATE_TRANSITION(condition) \ - if (UNLIKELY(!(condition))) \ - UnexpectedGCState(gc_state_) - -void ThreadState::SetGCState(GCState gc_state) { - switch (gc_state) { - case kNoGCScheduled: - DCHECK(CheckThread()); - VERIFY_STATE_TRANSITION(gc_state_ == kNoGCScheduled || - gc_state_ == kForcedGCForTestingScheduled || - gc_state_ == kIncrementalMarkingStepPaused || - gc_state_ == kIncrementalMarkingStepScheduled || - gc_state_ == - kIncrementalMarkingFinalizeScheduled || - gc_state_ == kIncrementalGCScheduled); - break; - case kIncrementalMarkingStepScheduled: - DCHECK(CheckThread()); - VERIFY_STATE_TRANSITION(gc_state_ == kNoGCScheduled || - gc_state_ == kIncrementalMarkingStepScheduled || - gc_state_ == kIncrementalGCScheduled || - gc_state_ == kIncrementalMarkingStepPaused); - break; - case kIncrementalMarkingFinalizeScheduled: - DCHECK(CheckThread()); - VERIFY_STATE_TRANSITION(gc_state_ == kIncrementalMarkingStepScheduled); - break; - case kForcedGCForTestingScheduled: - DCHECK(CheckThread()); - DCHECK(!IsSweepingInProgress()); - VERIFY_STATE_TRANSITION(gc_state_ == kNoGCScheduled || - gc_state_ == kIncrementalMarkingStepPaused || - gc_state_ == kIncrementalMarkingStepScheduled || - gc_state_ == - kIncrementalMarkingFinalizeScheduled || - gc_state_ == kForcedGCForTestingScheduled || - gc_state_ == kIncrementalGCScheduled); - break; - case kIncrementalGCScheduled: - DCHECK(CheckThread()); - DCHECK(!IsMarkingInProgress()); - DCHECK(!IsSweepingInProgress()); - VERIFY_STATE_TRANSITION(gc_state_ == kNoGCScheduled); - break; - case kIncrementalMarkingStepPaused: - DCHECK(CheckThread()); - DCHECK(IsMarkingInProgress()); - DCHECK(!IsSweepingInProgress()); - VERIFY_STATE_TRANSITION(gc_state_ == kIncrementalMarkingStepScheduled); - break; - default: - NOTREACHED(); - } - gc_state_ = gc_state; -} - -#undef VERIFY_STATE_TRANSITION - -void ThreadState::SetGCPhase(GCPhase gc_phase) { - switch (gc_phase) { - case GCPhase::kNone: - DCHECK_EQ(gc_phase_, GCPhase::kSweeping); - break; - case GCPhase::kMarking: - DCHECK_EQ(gc_phase_, GCPhase::kNone); - break; - case GCPhase::kSweeping: - DCHECK_EQ(gc_phase_, GCPhase::kMarking); - break; - } - gc_phase_ = gc_phase; -} - -void ThreadState::RunScheduledGC(BlinkGC::StackState stack_state) { - DCHECK(CheckThread()); - if (stack_state != BlinkGC::kNoHeapPointersOnStack) - return; - - // If a safe point is entered while initiating a GC, we clearly do - // not want to do another as part of that -- the safe point is only - // entered after checking if a scheduled GC ought to run first. - // Prevent that from happening by marking GCs as forbidden while - // one is initiated and later running. - if (IsGCForbidden()) - return; - - switch (GetGCState()) { - case kForcedGCForTestingScheduled: - forced_scheduled_gc_for_testing_ = true; - CollectAllGarbageForTesting(); - forced_scheduled_gc_for_testing_ = false; - break; - default: - break; - } -} - -void ThreadState::AtomicPauseMarkPrologue( - BlinkGC::CollectionType collection_type, - BlinkGC::StackState stack_state, - BlinkGC::MarkingType marking_type, - BlinkGC::GCReason reason) { - ThreadHeapStatsCollector::EnabledScope mark_prologue_scope( - Heap().stats_collector(), - ThreadHeapStatsCollector::kAtomicPauseMarkPrologue); - EnterAtomicPause(); - EnterNoAllocationScope(); - EnterGCForbiddenScope(); - - if (HeapPointersOnStackForced()) { - stack_state = BlinkGC::kHeapPointersOnStack; - } - - if (IsMarkingInProgress()) { - // Incremental marking is already in progress. Only update the state - // that is necessary to update. - SetGCState(kNoGCScheduled); - if (base::FeatureList::IsEnabled( - blink::features::kBlinkHeapConcurrentMarking)) { - // Stop concurrent markers and wait synchronously until they have all - // returned. - marker_handle_.Cancel(); - } -#if DCHECK_IS_ON() - MarkingWorklist* marking_worklist = Heap().GetMarkingWorklist(); - WriteBarrierWorklist* write_barrier_worklist = - Heap().GetWriteBarrierWorklist(); - for (int concurrent_task = WorklistTaskId::ConcurrentThreadBase; - concurrent_task < MarkingWorklist::kNumTasks; ++concurrent_task) { - DCHECK(marking_worklist->IsLocalEmpty(concurrent_task)); - DCHECK(write_barrier_worklist->IsLocalEmpty(concurrent_task)); - } -#endif // DCHECK_IS_ON() - // Compaction needs to be canceled when incremental marking ends with a - // conservative GC. - if (stack_state == BlinkGC::kHeapPointersOnStack) - Heap().Compaction()->Cancel(); - DisableIncrementalMarkingBarrier(); - current_gc_data_.reason = reason; - current_gc_data_.stack_state = stack_state; - Heap().stats_collector()->UpdateReason(reason); - } else { - DCHECK(!Heap().Compaction()->IsCompacting()); - MarkPhasePrologue(collection_type, stack_state, marking_type, reason); - } - - if (stack_state == BlinkGC::kNoHeapPointersOnStack) { - Heap().FlushNotFullyConstructedObjects(); - } - - DCHECK(InAtomicMarkingPause()); - Heap().MakeConsistentForGC(); - // AtomicPauseMarkPrologue is the common entry point for marking. The - // requirement is to lock from roots marking to weakness processing which is - // why the lock is taken at the end of the prologue. - static_cast<MutexBase&>(ProcessHeap::CrossThreadPersistentMutex()).lock(); -} - -void ThreadState::AtomicPauseEpilogue() { - if (!IsSweepingInProgress()) { - // Sweeping was finished during the atomic pause. Update statistics needs to - // run outside of the top-most stats scope. - PostSweep(); - } -} - -void ThreadState::CompleteSweep() { - DCHECK(CheckThread()); - // If we are not in a sweeping phase, there is nothing to do here. - if (!IsSweepingInProgress()) - return; - - // CompleteSweep() can be called recursively if finalizers can allocate - // memory and the allocation triggers completeSweep(). This check prevents - // the sweeping from being executed recursively. - if (SweepForbidden()) - return; - - { - // CompleteSweep may be called during regular mutator execution, from a - // task, or from the atomic pause in which the atomic scope has already been - // opened. - const bool was_in_atomic_pause = in_atomic_pause(); - if (!was_in_atomic_pause) - EnterAtomicPause(); - ScriptForbiddenScope script_forbidden; - SweepForbiddenScope scope(this); - ThreadHeapStatsCollector::EnabledScope stats_scope( - Heap().stats_collector(), ThreadHeapStatsCollector::kCompleteSweep); - // Boost priority of sweeping job to complete ASAP and avoid taking time on - // the main thread. - if (sweeper_handle_) - sweeper_handle_.UpdatePriority(base::TaskPriority::USER_BLOCKING); - Heap().CompleteSweep(); - SynchronizeAndFinishConcurrentSweeping(); - - if (!was_in_atomic_pause) - LeaveAtomicPause(); - } - NotifySweepDone(); -} - -void ThreadState::SynchronizeAndFinishConcurrentSweeping() { - DCHECK(CheckThread()); - DCHECK(IsSweepingInProgress()); - DCHECK(SweepForbidden()); - - // Wait for concurrent sweepers. - if (sweeper_handle_) - sweeper_handle_.Cancel(); - - // Concurrent sweepers may perform some work at the last stage (e.g. - // sweeping the last page and preparing finalizers). - Heap().InvokeFinalizersOnSweptPages(); -} - -namespace { - -// Update trace counters with statistics from the current and previous garbage -// collection cycle. We allow emitting current values here since these values -// can be useful for inspecting traces. -void UpdateTraceCounters(const ThreadHeapStatsCollector& stats_collector) { - bool gc_tracing_enabled; - TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("blink_gc"), - &gc_tracing_enabled); - if (!gc_tracing_enabled) - return; - - // Previous garbage collection cycle values. - const ThreadHeapStatsCollector::Event& event = stats_collector.previous(); - const int collection_rate_percent = - static_cast<int>(100 * (1.0 - event.live_object_rate)); - TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), - "BlinkGC.CollectionRate", collection_rate_percent); - TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), - "BlinkGC.MarkedObjectSizeAtLastCompleteSweepKB", - CappedSizeInKB(event.marked_bytes)); - TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), - "BlinkGC.ObjectSizeAtLastGCKB", - CappedSizeInKB(event.object_size_in_bytes_before_sweeping)); - TRACE_COUNTER1( - TRACE_DISABLED_BY_DEFAULT("blink_gc"), "BlinkGC.AllocatedSpaceAtLastGCKB", - CappedSizeInKB(event.allocated_space_in_bytes_before_sweeping)); - TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), - "BlinkGC.PartitionAllocSizeAtLastGCKB", - CappedSizeInKB(event.partition_alloc_bytes_before_sweeping)); - - // Current values. - TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), - "BlinkGC.AllocatedSpaceKB", - CappedSizeInKB(stats_collector.allocated_space_bytes())); - size_t allocated_bytes_since_prev_gc = - stats_collector.allocated_bytes_since_prev_gc() > 0 - ? static_cast<size_t>(stats_collector.allocated_bytes_since_prev_gc()) - : 0; - TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), - "BlinkGC.AllocatedObjectSizeSincePreviousGCKB", - CappedSizeInKB(allocated_bytes_since_prev_gc)); - TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), - "PartitionAlloc.TotalSizeOfCommittedPagesKB", - CappedSizeInKB(WTF::Partitions::TotalSizeOfCommittedPages())); -} - -// Update histograms with statistics from the previous garbage collection cycle. -// Anything that is part of a histogram should have a well-defined lifetime wrt. -// to a garbage collection cycle. -void UpdateHistograms(const ThreadHeapStatsCollector::Event& event) { - UMA_HISTOGRAM_ENUMERATION("BlinkGC.GCReason", event.reason); - - UMA_HISTOGRAM_TIMES("BlinkGC.TimeForAtomicPhase", event.atomic_pause_time()); - UMA_HISTOGRAM_TIMES("BlinkGC.TimeForAtomicPhaseMarking", - event.atomic_marking_time()); - UMA_HISTOGRAM_TIMES("BlinkGC.TimeForGCCycle", event.gc_cycle_time()); - UMA_HISTOGRAM_TIMES("BlinkGC.TimeForMarkingRoots", - event.roots_marking_time()); - UMA_HISTOGRAM_TIMES("BlinkGC.TimeForIncrementalMarking", - event.incremental_marking_time()); - UMA_HISTOGRAM_TIMES("BlinkGC.TimeForMarking.Foreground", - event.foreground_marking_time()); - UMA_HISTOGRAM_TIMES("BlinkGC.TimeForMarking.Background", - event.background_marking_time()); - UMA_HISTOGRAM_TIMES("BlinkGC.TimeForMarking", event.marking_time()); - UMA_HISTOGRAM_TIMES("BlinkGC.TimeForNestedInV8", event.gc_nested_in_v8); - UMA_HISTOGRAM_TIMES("BlinkGC.TimeForSweepingForeground", - event.foreground_sweeping_time()); - UMA_HISTOGRAM_TIMES("BlinkGC.TimeForSweepingBackground", - event.background_sweeping_time()); - UMA_HISTOGRAM_TIMES("BlinkGC.TimeForSweepingSum", event.sweeping_time()); - UMA_HISTOGRAM_TIMES( - "BlinkGC.TimeForCompleteSweep", - event.scope_data[ThreadHeapStatsCollector::kCompleteSweep]); - UMA_HISTOGRAM_TIMES( - "BlinkGC.TimeForInvokingPreFinalizers", - event.scope_data[ThreadHeapStatsCollector::kInvokePreFinalizers]); - UMA_HISTOGRAM_TIMES( - "BlinkGC.TimeForHeapCompaction", - event.scope_data[ThreadHeapStatsCollector::kAtomicPauseCompaction]); - UMA_HISTOGRAM_TIMES( - "BlinkGC.TimeForGlobalWeakProcessing", - event.scope_data[ThreadHeapStatsCollector::kMarkWeakProcessing]); - - base::TimeDelta marking_duration = event.foreground_marking_time(); - constexpr size_t kMinMarkedBytesForReportingThroughput = 1024 * 1024; - if (base::TimeTicks::IsHighResolution() && - (event.marked_bytes > kMinMarkedBytesForReportingThroughput) && - !marking_duration.is_zero()) { - DCHECK_GT(marking_duration.InMillisecondsF(), 0.0); - const int main_thread_marking_throughput_mb_per_s = static_cast<int>( - static_cast<double>(event.marked_bytes) / - marking_duration.InMillisecondsF() * 1000 / 1024 / 1024); - UMA_HISTOGRAM_COUNTS_100000("BlinkGC.MainThreadMarkingThroughput", - main_thread_marking_throughput_mb_per_s); - } - - DEFINE_STATIC_LOCAL( - CustomCountHistogram, object_size_freed_by_heap_compaction, - ("BlinkGC.ObjectSizeFreedByHeapCompaction", 1, 4 * 1024 * 1024, 50)); - if (event.compaction_recorded_events) { - object_size_freed_by_heap_compaction.Count( - CappedSizeInKB(event.compaction_freed_bytes)); - } - - DEFINE_STATIC_LOCAL(CustomCountHistogram, object_size_before_gc_histogram, - ("BlinkGC.ObjectSizeBeforeGC", 1, 4 * 1024 * 1024, 50)); - object_size_before_gc_histogram.Count( - CappedSizeInKB(event.object_size_in_bytes_before_sweeping)); - DEFINE_STATIC_LOCAL(CustomCountHistogram, object_size_after_gc_histogram, - ("BlinkGC.ObjectSizeAfterGC", 1, 4 * 1024 * 1024, 50)); - object_size_after_gc_histogram.Count(CappedSizeInKB(event.marked_bytes)); - - const int collection_rate_percent = - static_cast<int>(100 * (1.0 - event.live_object_rate)); - DEFINE_STATIC_LOCAL(CustomCountHistogram, collection_rate_histogram, - ("BlinkGC.CollectionRate", 1, 100, 20)); - collection_rate_histogram.Count(collection_rate_percent); - - // Per GCReason metrics. - switch (event.reason) { -#define COUNT_BY_GC_REASON(reason) \ - case BlinkGC::GCReason::k##reason: { \ - UMA_HISTOGRAM_TIMES("BlinkGC.AtomicPhaseMarking_" #reason, \ - event.atomic_marking_time()); \ - DEFINE_STATIC_LOCAL(CustomCountHistogram, \ - collection_rate_reason_histogram, \ - ("BlinkGC.CollectionRate_" #reason, 1, 100, 20)); \ - collection_rate_reason_histogram.Count(collection_rate_percent); \ - break; \ - } - - COUNT_BY_GC_REASON(ForcedGCForTesting) - COUNT_BY_GC_REASON(ThreadTerminationGC) - COUNT_BY_GC_REASON(UnifiedHeapGC) - COUNT_BY_GC_REASON(UnifiedHeapForMemoryReductionGC) - COUNT_BY_GC_REASON(UnifiedHeapForcedForTestingGC) - -#undef COUNT_BY_GC_REASON - } -} - -} // namespace - -void ThreadState::NotifySweepDone() { - DCHECK(CheckThread()); - SetGCPhase(GCPhase::kNone); - if (!in_atomic_pause()) { - PostSweep(); - } - - ThreadState::StatisticsCollector(this).Verify(); -} - -void ThreadState::PostSweep() { - DCHECK(!in_atomic_pause()); - DCHECK(!IsSweepingInProgress()); - - Heap().stats_collector()->NotifySweepingCompleted(); - - if (IsMainThread()) - UpdateHistograms(Heap().stats_collector()->previous()); - // Emit trace counters for all threads. - UpdateTraceCounters(*Heap().stats_collector()); -} - -void ThreadState::SafePoint(BlinkGC::StackState stack_state) { - DCHECK(CheckThread()); - - RunScheduledGC(stack_state); -} - -using PushAllRegistersCallback = void (*)(ThreadState*, intptr_t*); -extern "C" void PushAllRegisters(ThreadState*, PushAllRegistersCallback); - -// static -void ThreadState::VisitStackAfterPushingRegisters(ThreadState* state, - intptr_t* end_of_stack) { - state->VisitStack(static_cast<MarkingVisitor*>(state->CurrentVisitor()), - reinterpret_cast<Address*>(end_of_stack)); -} - -void ThreadState::PushRegistersAndVisitStack() { - DCHECK(CheckThread()); - DCHECK(IsGCForbidden()); - DCHECK_EQ(current_gc_data_.stack_state, BlinkGC::kHeapPointersOnStack); - // Visit registers, native stack, and asan fake stack. - PushAllRegisters(this, ThreadState::VisitStackAfterPushingRegisters); - // For builds that use safe stack, also visit the unsafe stack. - VisitUnsafeStack(static_cast<MarkingVisitor*>(CurrentVisitor())); -} - -void ThreadState::InvokePreFinalizers() { - DCHECK(CheckThread()); - DCHECK(!SweepForbidden()); - - ThreadHeapStatsCollector::Scope stats_scope( - Heap().stats_collector(), ThreadHeapStatsCollector::kInvokePreFinalizers); - SweepForbiddenScope sweep_forbidden(this); - // Pre finalizers are forbidden from allocating objects - NoAllocationScope no_allocation_scope(this); - - // Call the prefinalizers in the opposite order to their registration. - // - // Deque does not support modification during iteration, so - // copy items first. - // - // The prefinalizer callback wrapper returns |true| when its associated - // object is unreachable garbage and the prefinalizer callback has run. - // The registered prefinalizer entry must then be removed and deleted. - LivenessBroker broker = internal::LivenessBrokerFactory::Create(); - Deque<PreFinalizer> remaining_ordered_pre_finalizers; - for (auto rit = ordered_pre_finalizers_.rbegin(); - rit != ordered_pre_finalizers_.rend(); ++rit) { - const PreFinalizer& pre_finalizer = *rit; - if (!(pre_finalizer.second)(broker, pre_finalizer.first)) - remaining_ordered_pre_finalizers.push_front(pre_finalizer); - } - - ordered_pre_finalizers_ = std::move(remaining_ordered_pre_finalizers); -} - -// static -AtomicEntryFlag ThreadState::incremental_marking_flag_; - -void ThreadState::EnableIncrementalMarkingBarrier() { - CHECK(!IsIncrementalMarking()); - incremental_marking_flag_.Enter(); - SetIncrementalMarking(true); -} - -void ThreadState::DisableIncrementalMarkingBarrier() { - CHECK(IsIncrementalMarking()); - incremental_marking_flag_.Exit(); - SetIncrementalMarking(false); -} - -void ThreadState::IncrementalMarkingStartForTesting() { - // kIncrementalGCScheduled state requires sweeping to not be in progress. - CompleteSweep(); - SetGCState(kIncrementalGCScheduled); - IncrementalMarkingStart(BlinkGC::GCReason::kForcedGCForTesting); -} - -void ThreadState::IncrementalMarkingStart(BlinkGC::GCReason reason) { - DCHECK(!IsGCForbidden()); - DCHECK_EQ(kIncrementalGCScheduled, GetGCState()); - - VLOG(2) << "[state:" << this << "] " - << "IncrementalMarking: Start"; - DCHECK(!IsMarkingInProgress()); - // Sweeping is performed in driver functions. - DCHECK(!IsSweepingInProgress()); - Heap().stats_collector()->NotifyMarkingStarted( - BlinkGC::CollectionType::kMajor, reason, IsForcedGC(reason)); - { - ThreadHeapStatsCollector::EnabledScope stats_scope( - Heap().stats_collector(), - ThreadHeapStatsCollector::kIncrementalMarkingStartMarking, "reason", - BlinkGC::ToString(reason)); - AtomicPauseScope atomic_pause_scope(this); - ScriptForbiddenScope script_forbidden_scope; - MarkPhasePrologue(BlinkGC::CollectionType::kMajor, - BlinkGC::kNoHeapPointersOnStack, - BlinkGC::kIncrementalAndConcurrentMarking, reason); - { - MutexLocker persistent_lock(ProcessHeap::CrossThreadPersistentMutex()); - MarkPhaseVisitRoots(); - } - DCHECK(Heap().GetV8ReferencesWorklist()->IsGlobalEmpty()); - EnableIncrementalMarkingBarrier(); - if (base::FeatureList::IsEnabled( - blink::features::kBlinkHeapConcurrentMarking)) { - current_gc_data_.visitor->FlushMarkingWorklists(); - static_assert( - MarkingWorklist::kNumTasks == WriteBarrierWorklist::kNumTasks, - "Marking worklist and write-barrier worklist should be the " - "same size"); - last_concurrently_marked_bytes_ = 0; - last_concurrently_marked_bytes_update_ = base::TimeTicks::Now(); - concurrent_marking_priority_increased_ = false; - ScheduleConcurrentMarking(); - } - SetGCState(kIncrementalMarkingStepScheduled); - DCHECK(IsMarkingInProgress()); - } -} - -void ThreadState::IncrementalMarkingStep(BlinkGC::StackState stack_state) { - DCHECK(IsMarkingInProgress()); - DCHECK_EQ(kIncrementalMarkingStepScheduled, GetGCState()); - - ThreadHeapStatsCollector::EnabledScope stats_scope( - Heap().stats_collector(), - ThreadHeapStatsCollector::kIncrementalMarkingStep); - VLOG(2) << "[state:" << this << "] " - << "IncrementalMarking: Step " - << "Reason: " << BlinkGC::ToString(current_gc_data_.reason); - AtomicPauseScope atomic_pause_scope(this); - ScriptForbiddenScope script_forbidden_scope; - if (stack_state == BlinkGC::kNoHeapPointersOnStack) { - Heap().FlushNotFullyConstructedObjects(); - } - - bool complete; - if (skip_incremental_marking_for_testing_) { - complete = true; - skip_incremental_marking_for_testing_ = false; - } else { - complete = MarkPhaseAdvanceMarking( - marking_scheduling_->GetNextIncrementalStepDurationForTask( - Heap().stats_collector()->object_size_in_bytes()), - EphemeronProcessing::kPartialProcessing); - } - - if (base::FeatureList::IsEnabled( - blink::features::kBlinkHeapConcurrentMarking)) { - complete = ConcurrentMarkingStep() && complete; - } - - if (complete) { - if (IsUnifiedGCMarkingInProgress()) { - // If there are no more objects to mark for unified garbage collections - // just bail out of helping incrementally using tasks. V8 will drive - // further marking if new objects are discovered. Otherwise, just process - // the rest in the atomic pause. - DCHECK(IsUnifiedGCMarkingInProgress()); - SetGCState(kIncrementalMarkingStepPaused); - } else { - SetGCState(kIncrementalMarkingFinalizeScheduled); - } - } else { - SetGCState(kIncrementalMarkingStepScheduled); - } - DCHECK(IsMarkingInProgress()); -} - -bool ThreadState::ConcurrentMarkingStep() { - current_gc_data_.visitor->FlushMarkingWorklists(); - if (Heap().HasWorkForConcurrentMarking()) { - // Notifies the scheduler that max concurrency might have increased. - // This will adjust the number of markers if necessary. - marker_handle_.NotifyConcurrencyIncrease(); - if (!concurrent_marking_priority_increased_) { - // If concurrent tasks aren't executed, it might delay GC finalization. - // As long as GC is active so is the write barrier, which incurs a - // performance cost. Marking is estimated to take overall - // |MarkingSchedulingOracle::kEstimatedMarkingTimeMs| (500ms). If - // concurrent marking tasks have not reported any progress (i.e. the - // concurrently marked bytes count as not changed) in over - // |kMarkingScheduleRatioBeforeConcurrentPriorityIncrease| (50%) of - // that expected duration, we increase the concurrent task priority - // for the duration of the current GC. This is meant to prevent the - // GC from exceeding it's expected end time. - size_t current_concurrently_marked_bytes_ = - marking_scheduling_->GetConcurrentlyMarkedBytes(); - if (current_concurrently_marked_bytes_ > - last_concurrently_marked_bytes_) { - last_concurrently_marked_bytes_ = current_concurrently_marked_bytes_; - last_concurrently_marked_bytes_update_ = base::TimeTicks::Now(); - } else if ((base::TimeTicks::Now() - - last_concurrently_marked_bytes_update_) - .InMilliseconds() > - kMarkingScheduleRatioBeforeConcurrentPriorityIncrease * - MarkingSchedulingOracle::kEstimatedMarkingTimeMs) { - marker_handle_.UpdatePriority(base::TaskPriority::USER_BLOCKING); - concurrent_marking_priority_increased_ = true; - } - } - return false; - } - return !marker_handle_.IsActive(); -} - -void ThreadState::IncrementalMarkingFinalize() { - DCHECK(IsMarkingInProgress()); - DCHECK(!IsUnifiedGCMarkingInProgress()); - DCHECK_EQ(kIncrementalMarkingFinalizeScheduled, GetGCState()); - - ThreadHeapStatsCollector::EnabledScope stats_scope( - Heap().stats_collector(), - ThreadHeapStatsCollector::kIncrementalMarkingFinalize); - VLOG(2) << "[state:" << this << "] " - << "IncrementalMarking: Finalize " - << "Reason: " << BlinkGC::ToString(current_gc_data_.reason); - // Call into the regular bottleneck instead of the internal version to get - // UMA accounting and allow follow up GCs if necessary. - DCHECK_EQ(BlinkGC::kIncrementalAndConcurrentMarking, - current_gc_data_.marking_type); - CollectGarbage(current_gc_data_.collection_type, - BlinkGC::kNoHeapPointersOnStack, current_gc_data_.marking_type, - BlinkGC::kConcurrentAndLazySweeping, current_gc_data_.reason); -} - -bool ThreadState::FinishIncrementalMarkingIfRunning( - BlinkGC::CollectionType collection_type, - BlinkGC::StackState stack_state, - BlinkGC::MarkingType marking_type, - BlinkGC::SweepingType sweeping_type, - BlinkGC::GCReason reason) { - if (IsMarkingInProgress()) { - // TODO(mlippautz): Consider improving this mechanism as it will pull in - // finalization of V8 upon Oilpan GCs during a unified GC. Alternative - // include either breaking up the GCs or avoiding the call in first place. - if (IsUnifiedGCMarkingInProgress()) { - unified_heap_controller()->FinalizeTracing(); - } else { - RunAtomicPause(collection_type, stack_state, marking_type, sweeping_type, - reason); - } - return true; - } - return false; -} - -void ThreadState::RestartIncrementalMarkingIfPaused() { - if (GetGCState() != ThreadState::kIncrementalMarkingStepPaused) - return; - SetGCState(ThreadState::kIncrementalMarkingStepScheduled); - incremental_marking_scheduler_->Restart(); -} - -void ThreadState::CollectGarbage(BlinkGC::CollectionType collection_type, - BlinkGC::StackState stack_state, - BlinkGC::MarkingType marking_type, - BlinkGC::SweepingType sweeping_type, - BlinkGC::GCReason reason) { - // Nested garbage collection invocations are not supported. - CHECK(!IsGCForbidden()); - // Garbage collection during sweeping is not supported. This can happen when - // finalizers trigger garbage collections. - if (SweepForbidden()) - return; - - base::TimeTicks start_total_collect_garbage_time = base::TimeTicks::Now(); - RUNTIME_CALL_TIMER_SCOPE_IF_ISOLATE_EXISTS( - GetIsolate(), RuntimeCallStats::CounterId::kCollectGarbage); - - const bool was_incremental_marking = FinishIncrementalMarkingIfRunning( - collection_type, stack_state, marking_type, sweeping_type, reason); - - // We don't want floating garbage for the specific garbage collection types - // mentioned below. In this case we will follow up with a regular full - // garbage collection. - const bool should_do_full_gc = - !no_followup_full_gc_for_testing_ && - (!was_incremental_marking || - reason == BlinkGC::GCReason::kForcedGCForTesting || - reason == BlinkGC::GCReason::kThreadTerminationGC); - no_followup_full_gc_for_testing_ = false; - if (should_do_full_gc) { - CompleteSweep(); - SetGCState(kNoGCScheduled); - Heap().stats_collector()->NotifyMarkingStarted(collection_type, reason, - IsForcedGC(reason)); - RunAtomicPause(collection_type, stack_state, marking_type, sweeping_type, - reason); - } - - const base::TimeDelta total_collect_garbage_time = - base::TimeTicks::Now() - start_total_collect_garbage_time; - UMA_HISTOGRAM_TIMES("BlinkGC.TimeForTotalCollectGarbage", - total_collect_garbage_time); - -#define COUNT_BY_GC_REASON(reason) \ - case BlinkGC::GCReason::k##reason: { \ - UMA_HISTOGRAM_TIMES("BlinkGC.TimeForTotalCollectGarbage_" #reason, \ - total_collect_garbage_time); \ - break; \ - } - - switch (reason) { - COUNT_BY_GC_REASON(ForcedGCForTesting) - COUNT_BY_GC_REASON(ThreadTerminationGC) - COUNT_BY_GC_REASON(UnifiedHeapGC) - COUNT_BY_GC_REASON(UnifiedHeapForMemoryReductionGC) - COUNT_BY_GC_REASON(UnifiedHeapForcedForTestingGC) - } -#undef COUNT_BY_GC_REASON - - VLOG(1) << "[state:" << this << "]" - << " CollectGarbage: time: " << std::setprecision(2) - << total_collect_garbage_time.InMillisecondsF() << "ms" - << " stack: " << BlinkGC::ToString(stack_state) - << " marking: " << BlinkGC::ToString(marking_type) - << " sweeping: " << BlinkGC::ToString(sweeping_type) - << " reason: " << BlinkGC::ToString(reason); -} - -void ThreadState::AtomicPauseMarkRoots(BlinkGC::StackState stack_state, - BlinkGC::MarkingType marking_type, - BlinkGC::GCReason reason) { - ThreadHeapStatsCollector::EnabledScope advance_tracing_scope( - Heap().stats_collector(), - ThreadHeapStatsCollector::kAtomicPauseMarkRoots); - MarkPhaseVisitRoots(); - MarkPhaseVisitNotFullyConstructedObjects(); -} - -void ThreadState::AtomicPauseMarkTransitiveClosure() { - ThreadHeapStatsCollector::EnabledScope advance_tracing_scope( - Heap().stats_collector(), - ThreadHeapStatsCollector::kAtomicPauseMarkTransitiveClosure); - // base::TimeTicks::Now() + base::TimeDelta::Max() == base::TimeTicks::Max() - CHECK(MarkPhaseAdvanceMarking(base::TimeDelta::Max(), - EphemeronProcessing::kFullProcessing)); -} - -void ThreadState::AtomicPauseMarkEpilogue(BlinkGC::MarkingType marking_type) { - ThreadHeapStatsCollector::EnabledScope stats_scope( - Heap().stats_collector(), - ThreadHeapStatsCollector::kAtomicPauseMarkEpilogue); - MarkPhaseEpilogue(marking_type); - LeaveGCForbiddenScope(); - LeaveNoAllocationScope(); - LeaveAtomicPause(); - static_cast<MutexBase&>(ProcessHeap::CrossThreadPersistentMutex()).unlock(); -} - -void ThreadState::AtomicPauseSweepAndCompact( - BlinkGC::CollectionType collection_type, - BlinkGC::MarkingType marking_type, - BlinkGC::SweepingType sweeping_type) { - ThreadHeapStatsCollector::EnabledScope stats( - Heap().stats_collector(), - ThreadHeapStatsCollector::kAtomicPauseSweepAndCompact); - AtomicPauseScope atomic_pause_scope(this); - ScriptForbiddenScope script_forbidden_scope; - - DCHECK(InAtomicMarkingPause()); - DCHECK(CheckThread()); - Heap().PrepareForSweep(collection_type); - - // We have to set the GCPhase to Sweeping before calling pre-finalizers - // to disallow a GC during the pre-finalizers. - SetGCPhase(GCPhase::kSweeping); - - InvokePreFinalizers(); - - if (collection_type == BlinkGC::CollectionType::kMajor) { - // Slots filtering requires liveness information which is only present - // before sweeping any arena. - ThreadHeapStatsCollector::Scope stats_scope( - Heap().stats_collector(), - ThreadHeapStatsCollector::kAtomicPauseCompaction); - Heap().Compaction()->FilterNonLiveSlots(); - } - - // Last point where all mark bits are present. - VerifyMarking(marking_type); - - if (collection_type == BlinkGC::CollectionType::kMajor) { - // Any sweep compaction must happen after pre-finalizers, as it will - // finalize dead objects in compactable arenas (e.g., backing stores - // for container objects.) - // - // As per-contract for prefinalizers, those finalizable objects must - // still be accessible when the prefinalizer runs, hence we cannot - // schedule compaction until those have run. - SweepForbiddenScope scope(this); - NoAllocationScope no_allocation_scope(this); - Heap().Compact(); - Heap().DestroyCompactionWorklists(); - } - -#if defined(ADDRESS_SANITIZER) - PoisonUnmarkedObjects(); -#endif // ADDRESS_SANITIZER - DCHECK(IsSweepingInProgress()); - if (sweeping_type == BlinkGC::kEagerSweeping) { - // Eager sweeping should happen only in testing. - CompleteSweep(); - } else { - DCHECK(sweeping_type == BlinkGC::kConcurrentAndLazySweeping); - // The default behavior is concurrent and lazy sweeping. - ScheduleConcurrentAndLazySweep(); - } -} - -#if defined(ADDRESS_SANITIZER) -namespace { - -// Visitor unpoisoning all handles. Unpoisoning is required when dead objects -// are poisoned until they are later on processed. -// -// The raceful operations are: -// a. Running destructor that clears the handle. -// b. Running a stand-alone V8 GC (e.g. Scavenger) that clears the handle. -// -// Both operations run on the main thread and not concurrent. -class UnpoisonHandlesVisitor final - : public v8::PersistentHandleVisitor, - public v8::EmbedderHeapTracer::TracedGlobalHandleVisitor { - public: - explicit UnpoisonHandlesVisitor(ThreadHeap* heap) : heap_(heap) {} - - void VisitPersistentHandle(v8::Persistent<v8::Value>* value, - uint16_t class_id) final { - VisitSlot(value, sizeof(v8::Persistent<v8::Value>)); - } - - void VisitTracedGlobalHandle(const v8::TracedGlobal<v8::Value>&) final { - CHECK(false) << "Blink does not use v8::TracedGlobal."; - } - - void VisitTracedReference(const v8::TracedReference<v8::Value>& value) final { - // TODO(mlippautz): Avoid const_cast after changing the API to allow - // modificaton of the handle. - VisitSlot(&const_cast<v8::TracedReference<v8::Value>&>(value), - sizeof(v8::TracedReference<v8::Value>)); - } - - private: - void VisitSlot(void* address, size_t size) { - // Filter slots not on the heap. - if (!heap_->LookupPageForAddress(reinterpret_cast<Address>(address))) - return; - - HeapObjectHeader* header = HeapObjectHeader::FromInnerAddress(address); - if (!header->IsMarked()) { - DCHECK(ASAN_REGION_IS_POISONED(address, size)); - ASAN_UNPOISON_MEMORY_REGION(address, size); - } - } - - ThreadHeap* const heap_; -}; - -} // namespace - -void ThreadState::PoisonUnmarkedObjects() { - { - // This lock must be held because other threads may access cross-thread - // persistents and should not observe them in a poisoned state. - MutexLocker lock(ProcessHeap::CrossThreadPersistentMutex()); - - Heap().PoisonUnmarkedObjects(); - - // CrossThreadPersistents in unmarked objects may be accessed from other - // threads (e.g. in CrossThreadPersistentRegion::ShouldTracePersistent) and - // that would be fine. - ProcessHeap::GetCrossThreadPersistentRegion() - .UnpoisonCrossThreadPersistents(); - ProcessHeap::GetCrossThreadWeakPersistentRegion() - .UnpoisonCrossThreadPersistents(); - } - - // Similarly, unmarked object may contain handles to V8 that may be accessed - // (cleared) until the destructors are run. - if (GetIsolate()) { - UnpoisonHandlesVisitor visitor(&Heap()); - GetIsolate()->VisitHandlesWithClassIds(&visitor); - unified_heap_controller()->IterateTracedGlobalHandles(&visitor); - } -} -#endif // ADDRESS_SANITIZER - -void ThreadState::RunAtomicPause(BlinkGC::CollectionType collection_type, - BlinkGC::StackState stack_state, - BlinkGC::MarkingType marking_type, - BlinkGC::SweepingType sweeping_type, - BlinkGC::GCReason reason) { - // Legacy scope that is used to add stand-alone Oilpan GCs to DevTools - // timeline. - TRACE_EVENT1("blink_gc,devtools.timeline", "BlinkGC.AtomicPhase", "forced", - IsForcedGC(reason)); - - AtomicPauseMarkPrologue(collection_type, stack_state, marking_type, reason); - AtomicPauseMarkRoots(stack_state, marking_type, reason); - AtomicPauseMarkTransitiveClosure(); - AtomicPauseMarkEpilogue(marking_type); - AtomicPauseSweepAndCompact(collection_type, marking_type, sweeping_type); - AtomicPauseEpilogue(); -} - -namespace { - -MarkingVisitor::MarkingMode GetMarkingMode(bool should_compact) { - return (should_compact) ? MarkingVisitor::kGlobalMarkingWithCompaction - : MarkingVisitor::kGlobalMarking; -} - -} // namespace - -void ThreadState::MarkPhasePrologue(BlinkGC::CollectionType collection_type, - BlinkGC::StackState stack_state, - BlinkGC::MarkingType marking_type, - BlinkGC::GCReason reason) { - SetGCPhase(GCPhase::kMarking); - - ThreadState::StatisticsCollector(this).Verify(); - - const bool compaction_enabled = - Heap().Compaction()->ShouldCompact(stack_state, marking_type, reason); - - Heap().SetupWorklists(compaction_enabled); - - if (compaction_enabled) { - Heap().Compaction()->Initialize(this); - } - -#if BUILDFLAG(BLINK_HEAP_YOUNG_GENERATION) - if (collection_type == BlinkGC::CollectionType::kMajor) { - // Unmark heap before doing major collection cycle. - Heap().Unmark(); - } -#endif - - current_gc_data_.reason = reason; - current_gc_data_.collection_type = collection_type; - current_gc_data_.visitor = - IsUnifiedGCMarkingInProgress() - ? std::make_unique<UnifiedHeapMarkingVisitor>( - this, GetMarkingMode(compaction_enabled), GetIsolate()) - : std::make_unique<MarkingVisitor>( - this, GetMarkingMode(compaction_enabled)); - current_gc_data_.stack_state = stack_state; - current_gc_data_.marking_type = marking_type; - - marking_scheduling_ = std::make_unique<MarkingSchedulingOracle>(); -} - -void ThreadState::MarkPhaseVisitRoots() { - ThreadHeapStatsCollector::EnabledScope stats_scope( - Heap().stats_collector(), ThreadHeapStatsCollector::kVisitRoots); - - Visitor* visitor = current_gc_data_.visitor.get(); - - VisitPersistents(visitor); - - if (current_gc_data_.stack_state == BlinkGC::kHeapPointersOnStack) { - ThreadHeapStatsCollector::Scope stack_stats_scope( - Heap().stats_collector(), ThreadHeapStatsCollector::kVisitStackRoots); - PushRegistersAndVisitStack(); - } - - // Visit remembered sets (card tables) for minor collections. - if (current_gc_data_.collection_type == BlinkGC::CollectionType::kMinor) { - VisitRememberedSets(static_cast<MarkingVisitor*>(visitor)); - } -} - -bool ThreadState::MarkPhaseAdvanceMarkingBasedOnSchedule( - base::TimeDelta max_deadline, - EphemeronProcessing ephemeron_processing) { - return MarkPhaseAdvanceMarking( - std::min(max_deadline, - marking_scheduling_->GetNextIncrementalStepDurationForTask( - Heap().stats_collector()->object_size_in_bytes())), - ephemeron_processing); -} - -bool ThreadState::MarkPhaseAdvanceMarking( - base::TimeDelta deadline, - EphemeronProcessing ephemeron_processing) { - MarkingVisitor* visitor = current_gc_data_.visitor.get(); - ThreadHeapStatsCollector::EnabledScope deadline_scope( - Heap().stats_collector(), - ThreadHeapStatsCollector::kIncrementalMarkingWithDeadline, "deadline_ms", - deadline.InMillisecondsF()); - const bool finished = Heap().AdvanceMarking( - reinterpret_cast<MarkingVisitor*>(visitor), - base::TimeTicks::Now() + deadline, ephemeron_processing); - // visitor->marked_bytes() can also include bytes marked during roots - // visitation which is not counted in worklist_processing_time_foreground. - // Since the size of the roots is usually small relative to the size of - // the object graph, this is fine. - marking_scheduling_->UpdateIncrementalMarkingStats( - visitor->marked_bytes(), - Heap().stats_collector()->worklist_processing_time_foreground(), - Heap().stats_collector()->flushing_v8_references_time()); - return finished; -} - -bool ThreadState::IsVerifyMarkingEnabled() const { - bool should_verify_marking = base::FeatureList::IsEnabled( - blink::features::kBlinkHeapIncrementalMarkingStress); -#if BUILDFLAG(BLINK_HEAP_VERIFICATION) - should_verify_marking = (disable_heap_verification_scope_ == 0); -#endif // BLINK_HEAP_VERIFICATION - return should_verify_marking; -} - -void ThreadState::MarkPhaseVisitNotFullyConstructedObjects() { - Heap().MarkNotFullyConstructedObjects( - reinterpret_cast<MarkingVisitor*>(current_gc_data_.visitor.get())); -} - -void ThreadState::MarkPhaseEpilogue(BlinkGC::MarkingType marking_type) { - MarkingVisitor* visitor = current_gc_data_.visitor.get(); - { - ProcessHeap::CrossThreadPersistentMutex().AssertAcquired(); - VisitWeakPersistents(visitor); - Heap().WeakProcessing(visitor); - } - Heap().DestroyMarkingWorklists(current_gc_data_.stack_state); - - incremental_marking_scheduler_->Cancel(); - - current_gc_data_.visitor->FlushCompactionWorklists(); - current_gc_data_.visitor.reset(); - - Heap().stats_collector()->NotifyMarkingCompleted( - marking_scheduling_->GetOverallMarkedBytes()); - marking_scheduling_.reset(); - - DEFINE_THREAD_SAFE_STATIC_LOCAL( - CustomCountHistogram, total_object_space_histogram, - ("BlinkGC.TotalObjectSpace", 0, 4 * 1024 * 1024, 50)); - total_object_space_histogram.Count( - CappedSizeInKB(ProcessHeap::TotalAllocatedObjectSize())); - DEFINE_THREAD_SAFE_STATIC_LOCAL( - CustomCountHistogram, total_allocated_space_histogram, - ("BlinkGC.TotalAllocatedSpace", 0, 4 * 1024 * 1024, 50)); - total_allocated_space_histogram.Count( - CappedSizeInKB(ProcessHeap::TotalAllocatedSpace())); -} - -void ThreadState::VerifyMarking(BlinkGC::MarkingType marking_type) { - if (IsVerifyMarkingEnabled()) - Heap().VerifyMarking(); -} - -void ThreadState::CollectGarbageForTesting( - BlinkGC::CollectionType collection_type, - BlinkGC::StackState stack_state, - BlinkGC::MarkingType marking_type, - BlinkGC::SweepingType sweeping_type, - BlinkGC::GCReason reason) { - CollectGarbage(collection_type, stack_state, marking_type, sweeping_type, - reason); -} - -void ThreadState::CollectAllGarbageForTesting(BlinkGC::StackState stack_state) { - // We need to run multiple GCs to collect a chain of persistent handles. - size_t previous_live_objects = 0; - for (int i = 0; i < 5; ++i) { - if (isolate_) { - unified_heap_controller()->GarbageCollectionForTesting( - stack_state == BlinkGC::kNoHeapPointersOnStack - ? v8::EmbedderHeapTracer::EmbedderStackState::kNoHeapPointers - : v8::EmbedderHeapTracer::EmbedderStackState:: - kMayContainHeapPointers); - } else { - CollectGarbage(BlinkGC::CollectionType::kMajor, stack_state, - BlinkGC::kAtomicMarking, BlinkGC::kEagerSweeping, - BlinkGC::GCReason::kForcedGCForTesting); - } - const size_t live_objects = - Heap().stats_collector()->previous().marked_bytes; - if (live_objects == previous_live_objects) - break; - previous_live_objects = live_objects; - } -} - -void ThreadState::EnableCompactionForNextGCForTesting() { - Heap().Compaction()->EnableCompactionForNextGCForTesting(); -} - -void ThreadState::ScheduleConcurrentMarking() { - DCHECK(base::FeatureList::IsEnabled( - blink::features::kBlinkHeapConcurrentMarking)); - - marker_handle_ = base::PostJob( - FROM_HERE, {base::TaskPriority::USER_VISIBLE}, - ConvertToBaseRepeatingCallback( - WTF::CrossThreadBindRepeating(&ThreadState::PerformConcurrentMark, - WTF::CrossThreadUnretained(this))), - ConvertToBaseRepeatingCallback(WTF::CrossThreadBindRepeating( - [](ThreadState* state, size_t active_worker_count) -> size_t { - // We need to account for local segments in addition to - // ConcurrentMarkingGlobalWorkSize(). - return std::min<size_t>( - state->Heap().ConcurrentMarkingGlobalWorkSize() + - active_worker_count, - MarkingWorklist::kNumTasks - - WorklistTaskId::ConcurrentThreadBase); - }, - WTF::CrossThreadUnretained(this)))); -} - -void ThreadState::PerformConcurrentMark(base::JobDelegate* job) { - VLOG(2) << "[state:" << this << "] [threadid:" << CurrentThread() << "] " - << "ConcurrentMark"; - ThreadHeapStatsCollector::EnabledConcurrentScope stats_scope( - Heap().stats_collector(), - ThreadHeapStatsCollector::kConcurrentMarkingStep); - - if (!Heap().HasWorkForConcurrentMarking()) - return; - - uint8_t task_id = job->GetTaskId() + 1; - - std::unique_ptr<ConcurrentMarkingVisitor> concurrent_visitor = - IsUnifiedGCMarkingInProgress() - ? std::make_unique<ConcurrentUnifiedHeapMarkingVisitor>( - this, GetMarkingMode(Heap().Compaction()->IsCompacting()), - GetIsolate(), task_id) - : std::make_unique<ConcurrentMarkingVisitor>( - this, GetMarkingMode(Heap().Compaction()->IsCompacting()), - task_id); - - Heap().AdvanceConcurrentMarking(concurrent_visitor.get(), job, - marking_scheduling_.get()); - - marking_scheduling_->AddConcurrentlyMarkedBytes( - concurrent_visitor->RecentlyMarkedBytes()); - - concurrent_visitor->FlushWorklists(); -} - -void ThreadState::NotifyGarbageCollection(v8::GCType type, - v8::GCCallbackFlags flags) { - if (!IsGCForbidden() && (flags & v8::kGCCallbackFlagForced)) { - // Forces a precise GC at the end of the current event loop. This is - // required for testing code that cannot use GC internals but rather has - // to rely on window.gc(). Only schedule additional GCs if the last GC was - // using conservative stack scanning. - if (type == v8::kGCTypeScavenge || RequiresForcedGCForTesting()) { - ScheduleForcedGCForTesting(); - } - } -} - -void ThreadState::CollectNodeAndCssStatistics( - base::OnceCallback<void(size_t allocated_node_bytes, - size_t allocated_css_bytes)> callback) { - if (IsSweepingInProgress()) { - // Help the sweeper to make progress using short-running delayed tasks. - // We use delayed tasks to give background threads a chance to sweep - // most of the heap. - const base::TimeDelta kStepSizeMs = base::TimeDelta::FromMilliseconds(5); - const base::TimeDelta kTaskDelayMs = base::TimeDelta::FromMilliseconds(10); - if (!AdvanceLazySweep(base::TimeTicks::Now() + kStepSizeMs)) { - ThreadScheduler::Current()->V8TaskRunner()->PostDelayedTask( - FROM_HERE, - WTF::Bind(&ThreadState::CollectNodeAndCssStatistics, - WTF::Unretained(this), std::move(callback)), - kTaskDelayMs); - return; - } - } - size_t allocated_node_bytes = - Heap().Arena(BlinkGC::kNodeArenaIndex)->AllocatedBytes(); - size_t allocated_css_bytes = - Heap().Arena(BlinkGC::kCSSValueArenaIndex)->AllocatedBytes(); - std::move(callback).Run(allocated_node_bytes, allocated_css_bytes); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/impl/thread_state.h b/third_party/blink/renderer/platform/heap/impl/thread_state.h deleted file mode 100644 index 3c7922d1..0000000 --- a/third_party/blink/renderer/platform/heap/impl/thread_state.h +++ /dev/null
@@ -1,686 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_THREAD_STATE_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_THREAD_STATE_H_ - -#include <atomic> -#include <memory> - -#include "base/dcheck_is_on.h" -#include "base/synchronization/lock.h" -#include "base/task/post_job.h" -#include "third_party/blink/renderer/platform/heap/blink_gc.h" -#include "third_party/blink/renderer/platform/heap/impl/atomic_entry_flag.h" -#include "third_party/blink/renderer/platform/heap/impl/threading_traits.h" -#include "third_party/blink/renderer/platform/platform_export.h" -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" -#include "third_party/blink/renderer/platform/wtf/forward.h" -#include "third_party/blink/renderer/platform/wtf/hash_map.h" -#include "third_party/blink/renderer/platform/wtf/hash_set.h" -#include "third_party/blink/renderer/platform/wtf/linked_hash_set.h" -#include "third_party/blink/renderer/platform/wtf/sanitizers.h" -#include "third_party/blink/renderer/platform/wtf/thread_specific.h" -#include "third_party/blink/renderer/platform/wtf/threading.h" -#include "third_party/blink/renderer/platform/wtf/threading_primitives.h" -#include "third_party/blink/renderer/platform/wtf/vector.h" -#include "v8/include/v8.h" - -namespace v8 { -class EmbedderGraph; -class Isolate; -} // namespace v8 - -namespace blink { - -namespace incremental_marking_test { -class IncrementalMarkingScope; -} // namespace incremental_marking_test - -class MarkingVisitor; -class MarkingSchedulingOracle; -class PersistentRegion; -class ThreadHeap; -class ThreadState; -template <ThreadAffinity affinity> -class ThreadStateFor; -class UnifiedHeapController; -class Visitor; - -// Declare that a class has a pre-finalizer which gets invoked before objects -// get swept. It is thus safe to touch on-heap objects that may be collected in -// the same GC cycle. This is useful when it's not possible to avoid touching -// on-heap objects in a destructor which is forbidden. -// -// Note that: -// (a) Pre-finalizers *must* not resurrect dead objects. -// (b) Run on the same thread they are registered. -// (c) Decrease GC performance which means that they should only be used if -// absolute necessary. -// -// Usage: -// class Foo : GarbageCollected<Foo> { -// USING_PRE_FINALIZER(Foo, Dispose); -// private: -// void Dispose() { -// bar_->...; // It is safe to touch other on-heap objects. -// } -// Member<Bar> bar_; -// }; -#define USING_PRE_FINALIZER(Class, PreFinalizer) \ - public: \ - static bool InvokePreFinalizer(const LivenessBroker& info, void* object) { \ - Class* self = reinterpret_cast<Class*>(object); \ - if (info.IsHeapObjectAlive(self)) \ - return false; \ - self->Class::PreFinalizer(); \ - return true; \ - } \ - \ - private: \ - ThreadState::PrefinalizerRegistration<Class> prefinalizer_dummy_{this}; \ - using UsingPreFinalizerMacroNeedsTrailingSemiColon = char - -class PLATFORM_EXPORT ThreadState final { - USING_FAST_MALLOC(ThreadState); - - public: - // Register the pre-finalizer for the |self| object. The class T be using - // USING_PRE_FINALIZER() macro. - template <typename T> - class PrefinalizerRegistration final { - DISALLOW_NEW(); - - public: - PrefinalizerRegistration(T* self) { // NOLINT - static_assert(sizeof(&T::InvokePreFinalizer) > 0, - "USING_PRE_FINALIZER(T) must be defined."); - ThreadState* state = - ThreadStateFor<ThreadingTrait<T>::kAffinity>::GetState(); -#if DCHECK_IS_ON() - DCHECK(state->CheckThread()); -#endif - DCHECK(!state->SweepForbidden()); - DCHECK(std::find(state->ordered_pre_finalizers_.begin(), - state->ordered_pre_finalizers_.end(), - PreFinalizer(self, T::InvokePreFinalizer)) == - state->ordered_pre_finalizers_.end()); - state->ordered_pre_finalizers_.emplace_back(self, T::InvokePreFinalizer); - } - }; - - // See setGCState() for possible state transitions. - enum GCState { - kNoGCScheduled, - kIncrementalMarkingStepPaused, - kIncrementalMarkingStepScheduled, - kIncrementalMarkingFinalizeScheduled, - kForcedGCForTestingScheduled, - kIncrementalGCScheduled, - }; - - // The phase that the GC is in. The GCPhase will not return kNone for mutators - // running during incremental marking and lazy sweeping. See SetGCPhase() for - // possible state transitions. - enum class GCPhase { - // GC is doing nothing. - kNone, - // GC is in marking phase. - kMarking, - // GC is in sweeping phase. - kSweeping, - }; - - enum class EphemeronProcessing { - kPartialProcessing, // Perofrm one ephemeron processing iteration every - // few step - kFullProcessing // Perofrm full fixed-point ephemeron processing on each - // step - }; - - class AtomicPauseScope; - class GCForbiddenScope; - class LsanDisabledScope; - class NoAllocationScope; - class StatisticsCollector; - struct Statistics; - class SweepForbiddenScope; - - using V8BuildEmbedderGraphCallback = void (*)(v8::Isolate*, - v8::EmbedderGraph*, - void*); - - // Returns true if some thread (possibly the current thread) may be doing - // incremental marking. If false is returned, the *current* thread is - // definitely not doing incremental marking. See atomic_entry_flag.h for - // details. - // - // For an exact check, use ThreadState::IsIncrementalMarking. - ALWAYS_INLINE static bool IsAnyIncrementalMarking() { - return incremental_marking_flag_.MightBeEntered(); - } - - static ThreadState* AttachMainThread(); - static ThreadState* AttachMainThreadForTesting(v8::Platform* platform); - - // Associate ThreadState object with the current thread. After this - // call thread can start using the garbage collected heap infrastructure. - // It also has to periodically check for safepoints. - static ThreadState* AttachCurrentThread(); - static ThreadState* AttachCurrentThreadForTesting(v8::Platform* platform); - - // Disassociate attached ThreadState from the current thread. The thread - // can no longer use the garbage collected heap after this call. - // - // When ThreadState is detaching from non-main thread its heap is expected to - // be empty (because it is going away). Perform registered cleanup tasks and - // garbage collection to sweep away any objects that are left on this heap. - // - // This method asserts that no objects remain after this cleanup. If assertion - // does not hold we crash as we are potentially in the dangling pointer - // situation. - static void DetachCurrentThread(); - - static ThreadState* Current() { return **thread_specific_; } - - static ThreadState* MainThreadState() { - return reinterpret_cast<ThreadState*>(main_thread_state_storage_); - } - - static ThreadState* FromObject(const void*); - - ThreadState(const ThreadState&) = delete; - ThreadState& operator=(const ThreadState&) = delete; - - bool IsMainThread() const { return this == MainThreadState(); } - bool CheckThread() const { return thread_ == CurrentThread(); } - - ThreadHeap& Heap() const { return *heap_; } - base::PlatformThreadId ThreadId() const { return thread_; } - - // Associates |ThreadState| with a given |v8::Isolate|, essentially tying - // there garbage collectors together. - void AttachToIsolate(v8::Isolate*, V8BuildEmbedderGraphCallback); - - // Removes the association from a potentially attached |v8::Isolate|. - void DetachFromIsolate(); - - // Returns an |UnifiedHeapController| if ThreadState is attached to a V8 - // isolate (see |AttachToIsolate|) and nullptr otherwise. - UnifiedHeapController* unified_heap_controller() const { - DCHECK(isolate_); - return unified_heap_controller_.get(); - } - - void PerformIdleLazySweep(base::TimeTicks deadline); - void PerformConcurrentSweep(base::JobDelegate*); - - void ScheduleForcedGCForTesting(); - void ScheduleGCIfNeeded(); - void SetGCState(GCState); - GCState GetGCState() const { return gc_state_; } - void SetGCPhase(GCPhase); - - // Immediately starts incremental marking and schedules further steps if - // necessary. - void StartIncrementalMarking(BlinkGC::GCReason); - - // Returns true if marking is in progress. - bool IsMarkingInProgress() const { return gc_phase_ == GCPhase::kMarking; } - - // Returns true if unified heap marking is in progress. - bool IsUnifiedGCMarkingInProgress() const { - return IsMarkingInProgress() && IsUnifiedHeapGC(); - } - - // Returns true if sweeping is in progress. - bool IsSweepingInProgress() const { return gc_phase_ == GCPhase::kSweeping; } - - // Returns true if the current GC is a memory reducing GC. - bool IsMemoryReducingGC() const { - return current_gc_data_.reason == - BlinkGC::GCReason::kUnifiedHeapForMemoryReductionGC || - current_gc_data_.reason == - BlinkGC::GCReason::kUnifiedHeapForcedForTestingGC; - } - - bool IsUnifiedHeapGC() const { - return current_gc_data_.reason == BlinkGC::GCReason::kUnifiedHeapGC || - current_gc_data_.reason == - BlinkGC::GCReason::kUnifiedHeapForMemoryReductionGC || - current_gc_data_.reason == - BlinkGC::GCReason::kUnifiedHeapForcedForTestingGC; - } - - bool FinishIncrementalMarkingIfRunning(BlinkGC::CollectionType, - BlinkGC::StackState, - BlinkGC::MarkingType, - BlinkGC::SweepingType, - BlinkGC::GCReason); - - void EnableIncrementalMarkingBarrier(); - void DisableIncrementalMarkingBarrier(); - - void RestartIncrementalMarkingIfPaused(); - - void CompleteSweep(); - - // Returns whether it is currently allowed to allocate an object. Mainly used - // for sanity checks asserts. - bool IsAllocationAllowed() const { - // Allocation is not allowed during atomic marking pause, but it is allowed - // during atomic sweeping pause. - return !InAtomicMarkingPause() && !no_allocation_count_; - } - - // Returns whether it is currently forbidden to trigger a GC. - bool IsGCForbidden() const { return gc_forbidden_count_; } - - // Returns whether it is currently forbidden to sweep objects. - bool SweepForbidden() const { return sweep_forbidden_; } - - bool in_atomic_pause() const { return in_atomic_pause_; } - - bool InAtomicMarkingPause() const { - return in_atomic_pause() && IsMarkingInProgress(); - } - bool InAtomicSweepingPause() const { - return in_atomic_pause() && IsSweepingInProgress(); - } - - bool IsIncrementalMarking() const { return incremental_marking_; } - void SetIncrementalMarking(bool value) { incremental_marking_ = value; } - - void SafePoint(BlinkGC::StackState); - - // A region of non-weak PersistentNodes allocated on the given thread. - PersistentRegion* GetPersistentRegion() const { - return persistent_region_.get(); - } - - // A region of PersistentNodes for WeakPersistents allocated on the given - // thread. - PersistentRegion* GetWeakPersistentRegion() const { - return weak_persistent_region_.get(); - } - - v8::Isolate* GetIsolate() const { return isolate_; } - - // Returns |true| if |object| resides on this thread's heap. - // It is well-defined to call this method on any heap allocated - // reference, provided its associated heap hasn't been detached - // and shut down. Its behavior is undefined for any other pointer - // value. - bool IsOnThreadHeap(const void* object) const { - return &FromObject(object)->Heap() == &Heap(); - } - - ALWAYS_INLINE bool IsOnStack(Address address) const { - return reinterpret_cast<Address>(start_of_stack_) >= address && - address >= reinterpret_cast<Address>(WTF::GetCurrentStackPosition()); - } - - MarkingVisitor* CurrentVisitor() const { - return current_gc_data_.visitor.get(); - } - - // Returns true if the marking verifier is enabled, false otherwise. - bool IsVerifyMarkingEnabled() const; - - void SkipIncrementalMarkingForTesting() { - skip_incremental_marking_for_testing_ = true; - } - - // Performs stand-alone garbage collections considering only C++ objects for - // testing. - // - // Since it only considers C++ objects this type of GC is mostly useful for - // unit tests. - void CollectGarbageForTesting(BlinkGC::CollectionType, - BlinkGC::StackState, - BlinkGC::MarkingType, - BlinkGC::SweepingType, - BlinkGC::GCReason); - - // Forced garbage collection for testing: - // - Performs unified heap garbage collections if ThreadState is attached to a - // v8::Isolate using ThreadState::AttachToIsolate. - // - Otherwise, performs stand-alone garbage collections. - // - Collects garbage as long as live memory decreases (capped at 5). - void CollectAllGarbageForTesting( - BlinkGC::StackState stack_state = - BlinkGC::StackState::kNoHeapPointersOnStack); - - // Enables compaction for next garbage collection. - void EnableCompactionForNextGCForTesting(); - - bool RequiresForcedGCForTesting() const { - return current_gc_data_.stack_state == - BlinkGC::StackState::kHeapPointersOnStack && - !forced_scheduled_gc_for_testing_; - } - - void EnterNoHeapVerificationScopeForTesting() { - ++disable_heap_verification_scope_; - } - void LeaveNoHeapVerificationScopeForTesting() { - --disable_heap_verification_scope_; - } - - void EnableDetachedGarbageCollectionsForTesting() { CHECK(!isolate_); } - - void NotifyGarbageCollection(v8::GCType, v8::GCCallbackFlags); - - // Waits until sweeping is done and invokes the given callback with - // the total sizes of live objects in Node and CSS arenas. - void CollectNodeAndCssStatistics( - base::OnceCallback<void(size_t allocated_node_bytes, - size_t allocated_css_bytes)>); - - void ForceNoFollowupFullGCForTesting() { - no_followup_full_gc_for_testing_ = true; - } - - private: - class IncrementalMarkingScheduler; - - // Stores whether some ThreadState is currently in incremental marking. - static AtomicEntryFlag incremental_marking_flag_; - - static WTF::ThreadSpecific<ThreadState*>* thread_specific_; - - // We can't create a static member of type ThreadState here because it will - // introduce global constructor and destructor. We would like to manage - // lifetime of the ThreadState attached to the main thread explicitly instead - // and still use normal constructor and destructor for the ThreadState class. - // For this we reserve static storage for the main ThreadState and lazily - // construct ThreadState in it using placement new. - static uint8_t main_thread_state_storage_[]; - - // Callback executed directly after pushing all callee-saved registers. - // |end_of_stack| denotes the end of the stack that can hold references to - // managed objects. - static void VisitStackAfterPushingRegisters(ThreadState*, - intptr_t* end_of_stack); - - static bool IsForcedGC(BlinkGC::GCReason reason) { - return reason == BlinkGC::GCReason::kThreadTerminationGC || - reason == BlinkGC::GCReason::kForcedGCForTesting || - reason == BlinkGC::GCReason::kUnifiedHeapForcedForTestingGC; - } - - ThreadState(); - ~ThreadState(); - - void EnterNoAllocationScope() { no_allocation_count_++; } - void LeaveNoAllocationScope() { no_allocation_count_--; } - - void EnterAtomicPause() { - DCHECK(!in_atomic_pause_); - in_atomic_pause_ = true; - } - void LeaveAtomicPause() { - DCHECK(in_atomic_pause_); - in_atomic_pause_ = false; - } - - void EnterGCForbiddenScope() { gc_forbidden_count_++; } - void LeaveGCForbiddenScope() { - DCHECK_GT(gc_forbidden_count_, 0u); - gc_forbidden_count_--; - } - - // Performs stand-alone garbage collections considering only C++ objects. - // - // Use the public *ForTesting calls for calling GC in tests. - void CollectGarbage(BlinkGC::CollectionType, - BlinkGC::StackState, - BlinkGC::MarkingType, - BlinkGC::SweepingType, - BlinkGC::GCReason); - - // The following methods are used to compose RunAtomicPause. Public users - // should use the CollectGarbage entrypoint. Internal users should use these - // methods to compose a full garbage collection. - void AtomicPauseMarkPrologue(BlinkGC::CollectionType, - BlinkGC::StackState, - BlinkGC::MarkingType, - BlinkGC::GCReason); - void AtomicPauseMarkRoots(BlinkGC::StackState, - BlinkGC::MarkingType, - BlinkGC::GCReason); - void AtomicPauseMarkTransitiveClosure(); - void AtomicPauseMarkEpilogue(BlinkGC::MarkingType); - void AtomicPauseSweepAndCompact(BlinkGC::CollectionType, - BlinkGC::MarkingType marking_type, - BlinkGC::SweepingType sweeping_type); - void AtomicPauseEpilogue(); - - // RunAtomicPause composes the final atomic pause that finishes a mark-compact - // phase of a garbage collection. Depending on SweepingType it may also finish - // sweeping or schedule lazy/concurrent sweeping. - void RunAtomicPause(BlinkGC::CollectionType, - BlinkGC::StackState, - BlinkGC::MarkingType, - BlinkGC::SweepingType, - BlinkGC::GCReason); - - // The version is needed to be able to start incremental marking. - void MarkPhasePrologue(BlinkGC::CollectionType, - BlinkGC::StackState, - BlinkGC::MarkingType, - BlinkGC::GCReason); - void MarkPhaseEpilogue(BlinkGC::MarkingType); - void MarkPhaseVisitRoots(); - void MarkPhaseVisitNotFullyConstructedObjects(); - bool MarkPhaseAdvanceMarkingBasedOnSchedule(base::TimeDelta, - EphemeronProcessing); - bool MarkPhaseAdvanceMarking(base::TimeDelta, EphemeronProcessing); - void VerifyMarking(BlinkGC::MarkingType); - - // Visit the stack after pushing registers onto the stack. - void PushRegistersAndVisitStack(); - - // Visit local thread stack and trace all pointers conservatively. Never call - // directly but always call through |PushRegistersAndVisitStack|. - void VisitStackImpl(MarkingVisitor*, Address*, Address*); - void VisitStack(MarkingVisitor*, Address*); - void VisitUnsafeStack(MarkingVisitor*); - - // Visit the asan fake stack frame corresponding to a slot on the real machine - // stack if there is one. Never call directly but always call through - // |PushRegistersAndVisitStack|. - void VisitAsanFakeStackForPointer(MarkingVisitor*, - Address, - Address*, - Address*); - - // Visit all non-weak persistents allocated on this thread. - void VisitPersistents(Visitor*); - - // Visit all weak persistents allocated on this thread. - void VisitWeakPersistents(Visitor*); - - // Visit card tables (remembered sets) containing inter-generational pointers. - void VisitRememberedSets(MarkingVisitor*); - - // Incremental marking implementation functions. - void IncrementalMarkingStartForTesting(); - void IncrementalMarkingStart(BlinkGC::GCReason); - // Incremental marking step advance marking on the mutator thread. This method - // also reschedules concurrent marking tasks if needed. The duration parameter - // applies only to incremental marking steps on the mutator thread. - void IncrementalMarkingStep(BlinkGC::StackState); - void IncrementalMarkingFinalize(); - - // Returns true if concurrent marking is finished (i.e. all current threads - // terminated and the worklist is empty) - bool ConcurrentMarkingStep(); - void ScheduleConcurrentMarking(); - void PerformConcurrentMark(base::JobDelegate* job); - - // Schedule helpers. - void ScheduleIdleLazySweep(); - void ScheduleConcurrentAndLazySweep(); - // Advances sweeping and returns true if sweeping is complete. - bool AdvanceLazySweep(base::TimeTicks deadline); - - void NotifySweepDone(); - void PostSweep(); - - // See |DetachCurrentThread|. - void RunTerminationGC(); - - void RunScheduledGC(BlinkGC::StackState); - - void SynchronizeAndFinishConcurrentSweeping(); - - void InvokePreFinalizers(); - - bool IsForcedGC() const { return IsForcedGC(current_gc_data_.reason); } - - // Returns whether stack scanning is forced. This is currently only used in - // platform tests where non nested tasks can be run with heap pointers on - // stack. - bool HeapPointersOnStackForced() const { - return heap_pointers_on_stack_forced_; - } - -#if defined(ADDRESS_SANITIZER) - // Poisons payload of unmarked objects. - // - // Also unpoisons memory areas for handles that may require resetting which - // can race with destructors. Note that cross-thread access still requires - // synchronization using a lock. - void PoisonUnmarkedObjects(); -#endif // ADDRESS_SANITIZER - - std::unique_ptr<ThreadHeap> heap_; - base::PlatformThreadId thread_; - std::unique_ptr<PersistentRegion> persistent_region_; - std::unique_ptr<PersistentRegion> weak_persistent_region_; - - // Start of the stack which is the boundary until conservative stack scanning - // needs to search for managed pointers. - Address* start_of_stack_; - - bool in_atomic_pause_ = false; - bool sweep_forbidden_ = false; - bool heap_pointers_on_stack_forced_ = false; - bool incremental_marking_ = false; - bool should_optimize_for_load_time_ = false; - bool forced_scheduled_gc_for_testing_ = false; - size_t no_allocation_count_ = 0; - size_t gc_forbidden_count_ = 0; - - GCState gc_state_ = GCState::kNoGCScheduled; - GCPhase gc_phase_ = GCPhase::kNone; - BlinkGC::GCReason reason_for_scheduled_gc_ = - BlinkGC::GCReason::kForcedGCForTesting; - - using PreFinalizerCallback = bool (*)(const LivenessBroker&, void*); - using PreFinalizer = std::pair<void*, PreFinalizerCallback>; - - // Pre-finalizers are called in the reverse order in which they are - // registered by the constructors (including constructors of Mixin objects) - // for an object, by processing the ordered_pre_finalizers_ back-to-front. - Deque<PreFinalizer> ordered_pre_finalizers_; - - v8::Isolate* isolate_ = nullptr; - V8BuildEmbedderGraphCallback v8_build_embedder_graph_ = nullptr; - std::unique_ptr<UnifiedHeapController> unified_heap_controller_; - std::unique_ptr<v8::EmbedderRootsHandler> embedder_roots_handler_; - -#if defined(ADDRESS_SANITIZER) - void* asan_fake_stack_; -#endif - - struct GCData { - BlinkGC::CollectionType collection_type; - BlinkGC::StackState stack_state; - BlinkGC::MarkingType marking_type; - BlinkGC::GCReason reason; - std::unique_ptr<MarkingVisitor> visitor; - }; - GCData current_gc_data_; - - std::unique_ptr<IncrementalMarkingScheduler> incremental_marking_scheduler_; - std::unique_ptr<MarkingSchedulingOracle> marking_scheduling_; - - base::JobHandle marker_handle_; - - base::JobHandle sweeper_handle_; - std::atomic_bool has_unswept_pages_{false}; - - size_t disable_heap_verification_scope_ = 0; - - bool skip_incremental_marking_for_testing_ = false; - - size_t last_concurrently_marked_bytes_ = 0; - base::TimeTicks last_concurrently_marked_bytes_update_; - bool concurrent_marking_priority_increased_ = false; - - bool no_followup_full_gc_for_testing_ = false; - - friend class incremental_marking_test::IncrementalMarkingScope; - friend class HeapPointersOnStackScope; - friend class IncrementalMarkingTestDriver; - friend class HeapAllocator; - template <typename T> - friend class PrefinalizerRegistration; - friend class TestGCScope; - friend class TestSupportingGC; - friend class ThreadStateSchedulingTest; - friend class UnifiedHeapController; -}; - -template <> -class ThreadStateFor<kMainThreadOnly> { - STATIC_ONLY(ThreadStateFor); - - public: - static ThreadState* GetState() { - // This specialization must only be used from the main thread. - DCHECK(ThreadState::Current()->IsMainThread()); - return ThreadState::MainThreadState(); - } -}; - -template <> -class ThreadStateFor<kAnyThread> { - STATIC_ONLY(ThreadStateFor); - - public: - static ThreadState* GetState() { return ThreadState::Current(); } -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_THREAD_STATE_H_
diff --git a/third_party/blink/renderer/platform/heap/impl/thread_state_scopes.h b/third_party/blink/renderer/platform/heap/impl/thread_state_scopes.h deleted file mode 100644 index 77fc380..0000000 --- a/third_party/blink/renderer/platform/heap/impl/thread_state_scopes.h +++ /dev/null
@@ -1,84 +0,0 @@ -// Copyright 2019 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. - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_THREAD_STATE_SCOPES_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_THREAD_STATE_SCOPES_H_ - -#include "third_party/blink/renderer/platform/heap/thread_state.h" - -#if defined(LEAK_SANITIZER) -#include "third_party/blink/renderer/platform/wtf/leak_annotations.h" -#endif - -namespace blink { - -// The NoAllocationScope class is used in debug mode to catch unwanted -// allocations. E.g. allocations during GC. -class ThreadState::NoAllocationScope final { - STACK_ALLOCATED(); - - public: - explicit NoAllocationScope(ThreadState* state) : state_(state) { - state_->EnterNoAllocationScope(); - } - NoAllocationScope(const NoAllocationScope&) = delete; - NoAllocationScope& operator=(const NoAllocationScope&) = delete; - ~NoAllocationScope() { state_->LeaveNoAllocationScope(); } - - private: - ThreadState* const state_; -}; - -class ThreadState::SweepForbiddenScope final { - STACK_ALLOCATED(); - - public: - explicit SweepForbiddenScope(ThreadState* state) : state_(state) { - DCHECK(!state_->sweep_forbidden_); - state_->sweep_forbidden_ = true; - } - SweepForbiddenScope(const SweepForbiddenScope&) = delete; - SweepForbiddenScope& operator=(const SweepForbiddenScope&) = delete; - ~SweepForbiddenScope() { - DCHECK(state_->sweep_forbidden_); - state_->sweep_forbidden_ = false; - } - - private: - ThreadState* const state_; -}; - -class ThreadState::GCForbiddenScope final { - STACK_ALLOCATED(); - - public: - explicit GCForbiddenScope(ThreadState* thread_state) - : thread_state_(thread_state) { - thread_state_->EnterGCForbiddenScope(); - } - ~GCForbiddenScope() { thread_state_->LeaveGCForbiddenScope(); } - - private: - ThreadState* const thread_state_; -}; - -// Used to mark when we are in an atomic pause for GC. -class ThreadState::AtomicPauseScope final { - STACK_ALLOCATED(); - - public: - explicit AtomicPauseScope(ThreadState* thread_state) - : thread_state_(thread_state), gc_forbidden_scope(thread_state) { - thread_state_->EnterAtomicPause(); - } - ~AtomicPauseScope() { thread_state_->LeaveAtomicPause(); } - - private: - ThreadState* const thread_state_; - GCForbiddenScope gc_forbidden_scope; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_THREAD_STATE_SCOPES_H_
diff --git a/third_party/blink/renderer/platform/heap/impl/thread_state_statistics.cc b/third_party/blink/renderer/platform/heap/impl/thread_state_statistics.cc deleted file mode 100644 index f561bc3..0000000 --- a/third_party/blink/renderer/platform/heap/impl/thread_state_statistics.cc +++ /dev/null
@@ -1,39 +0,0 @@ -// Copyright 2019 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/heap/impl/thread_state_statistics.h" - -#include "third_party/blink/renderer/platform/heap/heap.h" -#include "third_party/blink/renderer/platform/heap/heap_stats_collector.h" - -namespace blink { - -ThreadState::Statistics ThreadState::StatisticsCollector::CollectStatistics( - Statistics::DetailLevel detail_level) const { - Statistics stats; - stats.detail_level = detail_level; - if (detail_level == Statistics::kBrief) { - ThreadHeapStatsCollector* stats_collector = - thread_state_->Heap().stats_collector(); - stats.committed_size_bytes = stats_collector->allocated_space_bytes(); - stats.used_size_bytes = stats_collector->object_size_in_bytes(); - return stats; - } - - thread_state_->CompleteSweep(); - - // Detailed statistics. - thread_state_->Heap().CollectStatistics(&stats); - stats.detail_level = Statistics::kDetailed; - return stats; -} - -void ThreadState::StatisticsCollector::Verify() const { -#if BUILDFLAG(BLINK_HEAP_VERIFICATION) && DCHECK_IS_ON() - // CollectStatistics checks counter consistency with DCHECKs. - CollectStatistics(Statistics::kDetailed); -#endif // BUILDFLAG(BLINK_HEAP_VERIFICATION) && DCHECK_IS_ON() -} - -} // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/impl/thread_state_statistics.h b/third_party/blink/renderer/platform/heap/impl/thread_state_statistics.h deleted file mode 100644 index e68d12f2..0000000 --- a/third_party/blink/renderer/platform/heap/impl/thread_state_statistics.h +++ /dev/null
@@ -1,68 +0,0 @@ -// Copyright 2019 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. - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_THREAD_STATE_STATISTICS_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_THREAD_STATE_STATISTICS_H_ - -#include "third_party/blink/renderer/platform/heap/thread_state.h" - -namespace blink { - -struct PLATFORM_EXPORT ThreadState::Statistics final { - enum DetailLevel : uint32_t { - kBrief, - kDetailed, - }; - - struct ObjectStatistics { - size_t num_types = 0; - Vector<std::string> type_name; - Vector<size_t> type_count; - Vector<size_t> type_bytes; - }; - - struct PageStatistics { - size_t committed_size_bytes = 0; - size_t used_size_bytes = 0; - }; - - struct FreeListStatistics { - Vector<size_t> bucket_size; - Vector<size_t> free_count; - Vector<size_t> free_size; - }; - - struct ArenaStatistics { - std::string name; - size_t committed_size_bytes = 0; - size_t used_size_bytes = 0; - Vector<PageStatistics> page_stats; - FreeListStatistics free_list_stats; - // Only filled when NameClient::HideInternalName() is false. - ObjectStatistics object_stats; - }; - - size_t committed_size_bytes = 0; - size_t used_size_bytes = 0; - DetailLevel detail_level; - - // Only filled when detail_level is kDetailed. - Vector<ArenaStatistics> arena_stats; -}; - -class PLATFORM_EXPORT ThreadState::StatisticsCollector { - public: - explicit StatisticsCollector(ThreadState* thread_state) - : thread_state_(thread_state) {} - - ThreadState::Statistics CollectStatistics(Statistics::DetailLevel) const; - void Verify() const; - - private: - ThreadState* const thread_state_; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_THREAD_STATE_STATISTICS_H_
diff --git a/third_party/blink/renderer/platform/heap/impl/threading_traits.h b/third_party/blink/renderer/platform/heap/impl/threading_traits.h deleted file mode 100644 index 28c10e9e..0000000 --- a/third_party/blink/renderer/platform/heap/impl/threading_traits.h +++ /dev/null
@@ -1,171 +0,0 @@ -// Copyright 2015 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. - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_THREADING_TRAITS_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_THREADING_TRAITS_H_ - -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" -#include "third_party/blink/renderer/platform/wtf/deque.h" -#include "third_party/blink/renderer/platform/wtf/hash_counted_set.h" -#include "third_party/blink/renderer/platform/wtf/hash_map.h" -#include "third_party/blink/renderer/platform/wtf/hash_set.h" -#include "third_party/blink/renderer/platform/wtf/hash_table.h" -#include "third_party/blink/renderer/platform/wtf/type_traits.h" -#include "third_party/blink/renderer/platform/wtf/vector.h" - -namespace blink { - -// ThreadAffinity indicates which threads objects can be used on. We -// distinguish between objects that can be used on the main thread -// only and objects that can be used on any thread. -// -// For objects that can only be used on the main thread, we avoid going -// through thread-local storage to get to the thread state. This is -// important for performance. -enum ThreadAffinity { - kAnyThread, - kMainThreadOnly, -}; - -// TODO(haraken): These forward declarations violate dependency rules. -// Remove them. -class LayoutObject; -class Node; -class NodeList; -class NodeRareData; - -template < - typename T, - bool mainThreadOnly = - WTF::IsSubclass<typename std::remove_const<T>::type, - LayoutObject>::value || - WTF::IsSubclass<typename std::remove_const<T>::type, Node>::value || - WTF::IsSubclass<typename std::remove_const<T>::type, NodeList>::value || - WTF::IsSubclass<typename std::remove_const<T>::type, - NodeRareData>::value> -struct DefaultThreadingTrait; - -template <typename T> -struct DefaultThreadingTrait<T, false> { - STATIC_ONLY(DefaultThreadingTrait); - static const ThreadAffinity kAffinity = kAnyThread; -}; - -template <typename T> -struct DefaultThreadingTrait<T, true> { - STATIC_ONLY(DefaultThreadingTrait); - static const ThreadAffinity kAffinity = kMainThreadOnly; -}; - -class HeapAllocator; -template <typename T> -class Member; -template <typename T> -class WeakMember; - -template <typename T> -struct ThreadingTrait { - STATIC_ONLY(ThreadingTrait); - static const ThreadAffinity kAffinity = DefaultThreadingTrait<T>::kAffinity; -}; - -template <typename U> -class ThreadingTrait<const U> : public ThreadingTrait<U> {}; - -template <typename T> -struct ThreadingTrait<Member<T>> { - STATIC_ONLY(ThreadingTrait); - static const ThreadAffinity kAffinity = ThreadingTrait<T>::kAffinity; -}; - -template <typename T> -struct ThreadingTrait<WeakMember<T>> { - STATIC_ONLY(ThreadingTrait); - static const ThreadAffinity kAffinity = ThreadingTrait<T>::kAffinity; -}; - -template <typename Key, typename Value, typename T, typename U, typename V> -struct ThreadingTrait<HashMap<Key, Value, T, U, V, HeapAllocator>> { - STATIC_ONLY(ThreadingTrait); - static const ThreadAffinity kAffinity = - (ThreadingTrait<Key>::kAffinity == kMainThreadOnly) && - (ThreadingTrait<Value>::kAffinity == kMainThreadOnly) - ? kMainThreadOnly - : kAnyThread; -}; - -template <typename First, typename Second> -struct ThreadingTrait<WTF::KeyValuePair<First, Second>> { - STATIC_ONLY(ThreadingTrait); - static const ThreadAffinity kAffinity = - (ThreadingTrait<First>::kAffinity == kMainThreadOnly) && - (ThreadingTrait<Second>::kAffinity == kMainThreadOnly) - ? kMainThreadOnly - : kAnyThread; -}; - -template <typename T, typename U, typename V> -struct ThreadingTrait<HashSet<T, U, V, HeapAllocator>> { - STATIC_ONLY(ThreadingTrait); - static const ThreadAffinity kAffinity = ThreadingTrait<T>::kAffinity; -}; - -template <typename T, size_t inlineCapacity> -struct ThreadingTrait<Vector<T, inlineCapacity, HeapAllocator>> { - STATIC_ONLY(ThreadingTrait); - static const ThreadAffinity kAffinity = ThreadingTrait<T>::kAffinity; -}; - -template <typename T, size_t inlineCapacity> -struct ThreadingTrait<Deque<T, inlineCapacity, HeapAllocator>> { - STATIC_ONLY(ThreadingTrait); - static const ThreadAffinity kAffinity = ThreadingTrait<T>::kAffinity; -}; - -template <typename T, typename U, typename V> -struct ThreadingTrait<HashCountedSet<T, U, V, HeapAllocator>> { - STATIC_ONLY(ThreadingTrait); - static const ThreadAffinity kAffinity = ThreadingTrait<T>::kAffinity; -}; - -template <typename T, typename U, typename V, typename W, typename X> -class HeapHashMap; -template <typename T, typename U, typename V> -class HeapHashSet; -template <typename T, wtf_size_t inlineCapacity> -class HeapVector; -template <typename T> -class HeapDeque; -template <typename T, typename U, typename V> -class HeapHashCountedSet; - -template <typename T, typename U, typename V, typename W, typename X> -struct ThreadingTrait<HeapHashMap<T, U, V, W, X>> - : public ThreadingTrait<HashMap<T, U, V, W, X, HeapAllocator>> { - STATIC_ONLY(ThreadingTrait); -}; -template <typename T, typename U, typename V> -struct ThreadingTrait<HeapHashSet<T, U, V>> - : public ThreadingTrait<HashSet<T, U, V, HeapAllocator>> { - STATIC_ONLY(ThreadingTrait); -}; -template <typename T, size_t inlineCapacity> -struct ThreadingTrait<HeapVector<T, inlineCapacity>> - : public ThreadingTrait<Vector<T, inlineCapacity, HeapAllocator>> { - STATIC_ONLY(ThreadingTrait); -}; -template <typename T> -struct ThreadingTrait<HeapDeque<T>> - : public ThreadingTrait<Deque<T, 0, HeapAllocator>> { - STATIC_ONLY(ThreadingTrait); -}; -template <typename T, typename U, typename V> -struct ThreadingTrait<HeapHashCountedSet<T, U, V>> - : public ThreadingTrait<HashCountedSet<T, U, V, HeapAllocator>> { - STATIC_ONLY(ThreadingTrait); -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_THREADING_TRAITS_H_
diff --git a/third_party/blink/renderer/platform/heap/impl/trace_traits.h b/third_party/blink/renderer/platform/heap/impl/trace_traits.h deleted file mode 100644 index 217b252..0000000 --- a/third_party/blink/renderer/platform/heap/impl/trace_traits.h +++ /dev/null
@@ -1,125 +0,0 @@ -// Copyright 2015 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. - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_TRACE_TRAITS_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_TRACE_TRAITS_H_ - -#include "third_party/blink/renderer/platform/heap/heap.h" -#include "third_party/blink/renderer/platform/heap/impl/gc_info.h" -#include "third_party/blink/renderer/platform/heap/impl/heap_page.h" -#include "third_party/blink/renderer/platform/heap/visitor.h" -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" -#include "third_party/blink/renderer/platform/wtf/hash_counted_set.h" -#include "third_party/blink/renderer/platform/wtf/hash_map.h" -#include "third_party/blink/renderer/platform/wtf/hash_set.h" -#include "third_party/blink/renderer/platform/wtf/hash_table.h" -#include "third_party/blink/renderer/platform/wtf/linked_hash_set.h" -#include "third_party/blink/renderer/platform/wtf/type_traits.h" - -namespace blink { - -template <typename T> -struct TraceTrait; - -template <typename T, bool = NeedsAdjustPointer<T>::value> -struct AdjustPointerTrait; - -template <typename T> -struct AdjustPointerTrait<T, false> { - STATIC_ONLY(AdjustPointerTrait); - - static TraceDescriptor GetTraceDescriptor(const void* self) { - return {self, TraceTrait<T>::Trace}; - } -}; - -template <typename T> -struct AdjustPointerTrait<T, true> { - STATIC_ONLY(AdjustPointerTrait); - - static TraceDescriptor GetTraceDescriptor(const void* self) { - // Tracing an object, and more specifically GetTraceDescriptor for an - // object, implies having a reference which means the object is at least in - // construction. Therefore it is guaranteed that the ObjectStartBitmap was - // already updated to include the object, and its HeapObjectHeader was - // already created. - HeapObjectHeader* const header = HeapObjectHeader::FromInnerAddress< - HeapObjectHeader::AccessMode::kAtomic>(self); - return {header->Payload(), - GCInfo::From( - header->GcInfoIndex<HeapObjectHeader::AccessMode::kAtomic>()) - .trace}; - } -}; - -template <typename T, bool = WTF::IsTraceable<T>::value> -struct TraceIfNeeded; - -template <typename T> -struct TraceIfNeeded<T, false> { - STATIC_ONLY(TraceIfNeeded); - static void Trace(Visitor*, const T&) {} -}; - -template <typename T> -struct TraceIfNeeded<T, true> { - STATIC_ONLY(TraceIfNeeded); - static void Trace(Visitor* visitor, const T& t) { visitor->Trace(t); } -}; - -// The TraceTrait is used to specify how to trace and object for Oilpan and -// wrapper tracing. -// -// -// By default, the 'Trace' method implemented on an object itself is -// used to trace the pointers to other heap objects inside the object. -// -// However, the TraceTrait can be specialized to use a different -// implementation. A common case where a TraceTrait specialization is -// needed is when multiple inheritance leads to pointers that are not -// to the start of the object in the Blink garbage-collected heap. In -// that case the pointer has to be adjusted before marking. -template <typename T> -struct TraceTrait { - STATIC_ONLY(TraceTrait); - - public: - static TraceDescriptor GetTraceDescriptor(const void* self) { - return AdjustPointerTrait<T>::GetTraceDescriptor( - static_cast<const T*>(self)); - } - - static TraceDescriptor GetWeakTraceDescriptor(const void* self) { - return {self, nullptr}; - } - - static void Trace(Visitor*, const void* self); -}; - -template <typename T> -struct TraceTrait<const T> : public TraceTrait<T> {}; - -template <typename T> -void TraceTrait<T>::Trace(Visitor* visitor, const void* self) { - static_assert(WTF::IsTraceable<T>::value, "T should be traceable"); - static_cast<const T*>(self)->Trace(visitor); -} - -// This trace trait for std::pair will null weak members if their referent is -// collected. If you have a collection that contain weakness it does not remove -// entries from the collection that contain nulled weak members. -template <typename T, typename U> -struct TraceTrait<std::pair<T, U>> { - STATIC_ONLY(TraceTrait); - - public: - static void Trace(Visitor* visitor, const std::pair<T, U>* pair) { - TraceIfNeeded<T>::Trace(visitor, pair->first); - TraceIfNeeded<U>::Trace(visitor, pair->second); - } -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_TRACE_TRAITS_H_
diff --git a/third_party/blink/renderer/platform/heap/impl/unified_heap_controller.cc b/third_party/blink/renderer/platform/heap/impl/unified_heap_controller.cc deleted file mode 100644 index c622451..0000000 --- a/third_party/blink/renderer/platform/heap/impl/unified_heap_controller.cc +++ /dev/null
@@ -1,191 +0,0 @@ -// 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/heap/unified_heap_controller.h" - -#include "base/logging.h" -#include "third_party/blink/public/common/features.h" -#include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h" -#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h" -#include "third_party/blink/renderer/platform/bindings/script_wrappable.h" -#include "third_party/blink/renderer/platform/bindings/wrapper_type_info.h" -#include "third_party/blink/renderer/platform/heap/heap.h" -#include "third_party/blink/renderer/platform/heap/heap_stats_collector.h" -#include "third_party/blink/renderer/platform/heap/impl/marking_visitor.h" -#include "third_party/blink/renderer/platform/heap/thread_state.h" - -namespace blink { - -namespace { - -constexpr BlinkGC::StackState ToBlinkGCStackState( - v8::EmbedderHeapTracer::EmbedderStackState stack_state) { - return stack_state == - v8::EmbedderHeapTracer::EmbedderStackState::kNoHeapPointers - ? BlinkGC::kNoHeapPointersOnStack - : BlinkGC::kHeapPointersOnStack; -} - -} // namespace - -UnifiedHeapController::UnifiedHeapController(ThreadState* thread_state) - : thread_state_(thread_state) { - thread_state->Heap().stats_collector()->RegisterObserver(this); -} - -UnifiedHeapController::~UnifiedHeapController() { - thread_state_->Heap().stats_collector()->UnregisterObserver(this); -} - -void UnifiedHeapController::TracePrologue( - v8::EmbedderHeapTracer::TraceFlags v8_flags) { - VLOG(2) << "UnifiedHeapController::TracePrologue"; - ThreadHeapStatsCollector::BlinkGCInV8Scope nested_scope( - thread_state_->Heap().stats_collector()); - - // Be conservative here as a new garbage collection gets started right away. - thread_state_->FinishIncrementalMarkingIfRunning( - BlinkGC::CollectionType::kMajor, BlinkGC::kHeapPointersOnStack, - BlinkGC::kIncrementalAndConcurrentMarking, - BlinkGC::kConcurrentAndLazySweeping, - thread_state_->current_gc_data_.reason); - - thread_state_->SetGCState(ThreadState::kNoGCScheduled); - BlinkGC::GCReason gc_reason; - if (v8_flags & v8::EmbedderHeapTracer::TraceFlags::kForced) { - gc_reason = BlinkGC::GCReason::kUnifiedHeapForcedForTestingGC; - } else if (v8_flags & v8::EmbedderHeapTracer::TraceFlags::kReduceMemory) { - gc_reason = BlinkGC::GCReason::kUnifiedHeapForMemoryReductionGC; - } else { - gc_reason = BlinkGC::GCReason::kUnifiedHeapGC; - } - thread_state_->StartIncrementalMarking(gc_reason); - - is_tracing_done_ = false; -} - -void UnifiedHeapController::EnterFinalPause(EmbedderStackState stack_state) { - VLOG(2) << "UnifiedHeapController::EnterFinalPause"; - ThreadHeapStatsCollector::BlinkGCInV8Scope nested_scope( - thread_state_->Heap().stats_collector()); - thread_state_->AtomicPauseMarkPrologue( - BlinkGC::CollectionType::kMajor, ToBlinkGCStackState(stack_state), - BlinkGC::kIncrementalAndConcurrentMarking, - thread_state_->current_gc_data_.reason); - thread_state_->AtomicPauseMarkRoots(ToBlinkGCStackState(stack_state), - BlinkGC::kIncrementalAndConcurrentMarking, - thread_state_->current_gc_data_.reason); -} - -void UnifiedHeapController::TraceEpilogue( - v8::EmbedderHeapTracer::TraceSummary* summary) { - VLOG(2) << "UnifiedHeapController::TraceEpilogue"; - { - ThreadHeapStatsCollector::BlinkGCInV8Scope nested_scope( - thread_state_->Heap().stats_collector()); - thread_state_->AtomicPauseMarkEpilogue( - BlinkGC::kIncrementalAndConcurrentMarking); - const BlinkGC::SweepingType sweeping_type = - thread_state_->IsForcedGC() ? BlinkGC::kEagerSweeping - : BlinkGC::kConcurrentAndLazySweeping; - thread_state_->AtomicPauseSweepAndCompact( - BlinkGC::CollectionType::kMajor, - BlinkGC::kIncrementalAndConcurrentMarking, sweeping_type); - - ThreadHeapStatsCollector* const stats_collector = - thread_state_->Heap().stats_collector(); - summary->allocated_size = - static_cast<size_t>(stats_collector->marked_bytes()); - summary->time = stats_collector->marking_time_so_far().InMillisecondsF(); - buffered_allocated_size_ = 0; - } - thread_state_->AtomicPauseEpilogue(); -} - -void UnifiedHeapController::RegisterV8References( - const std::vector<std::pair<void*, void*>>& - internal_fields_of_potential_wrappers) { - VLOG(2) << "UnifiedHeapController::RegisterV8References"; - DCHECK(thread_state()->IsMarkingInProgress()); - - const bool was_in_atomic_pause = thread_state()->in_atomic_pause(); - if (!was_in_atomic_pause) - ThreadState::Current()->EnterAtomicPause(); - for (const auto& internal_fields : internal_fields_of_potential_wrappers) { - const WrapperTypeInfo* wrapper_type_info = - reinterpret_cast<const WrapperTypeInfo*>(internal_fields.first); - if (wrapper_type_info->gin_embedder != gin::GinEmbedder::kEmbedderBlink) { - continue; - } - is_tracing_done_ = false; - wrapper_type_info->Trace(thread_state_->CurrentVisitor(), - internal_fields.second); - } - if (!was_in_atomic_pause) - ThreadState::Current()->LeaveAtomicPause(); -} - -bool UnifiedHeapController::AdvanceTracing(double deadline_in_ms) { - VLOG(2) << "UnifiedHeapController::AdvanceTracing"; - ThreadHeapStatsCollector::BlinkGCInV8Scope nested_scope( - thread_state_->Heap().stats_collector()); - if (!thread_state_->in_atomic_pause()) { - ThreadHeapStatsCollector::EnabledScope advance_tracing_scope( - thread_state_->Heap().stats_collector(), - ThreadHeapStatsCollector::kUnifiedMarkingStep); - // V8 calls into embedder tracing from its own marking to ensure - // progress. Oilpan will additionally schedule marking steps. - ThreadState::AtomicPauseScope atomic_pause_scope(thread_state_); - ScriptForbiddenScope script_forbidden_scope; - is_tracing_done_ = thread_state_->MarkPhaseAdvanceMarkingBasedOnSchedule( - base::TimeDelta::FromMillisecondsD(deadline_in_ms), - ThreadState::EphemeronProcessing::kPartialProcessing); - if (!is_tracing_done_) { - if (base::FeatureList::IsEnabled( - blink::features::kBlinkHeapConcurrentMarking)) { - thread_state_->ConcurrentMarkingStep(); - } - thread_state_->RestartIncrementalMarkingIfPaused(); - } - return is_tracing_done_; - } - thread_state_->AtomicPauseMarkTransitiveClosure(); - is_tracing_done_ = true; - return true; -} - -bool UnifiedHeapController::IsTracingDone() { - return is_tracing_done_; -} - -void UnifiedHeapController::ReportBufferedAllocatedSizeIfPossible() { - // Avoid reporting to V8 in the following conditions as that may trigger GC - // finalizations where not allowed. - // - Recursive sweeping. - // - GC forbidden scope. - if ((thread_state()->IsSweepingInProgress() && - thread_state()->SweepForbidden()) || - thread_state()->IsGCForbidden()) { - return; - } - - if (buffered_allocated_size_ < 0) { - DecreaseAllocatedSize(static_cast<size_t>(-buffered_allocated_size_)); - } else { - IncreaseAllocatedSize(static_cast<size_t>(buffered_allocated_size_)); - } - buffered_allocated_size_ = 0; -} - -void UnifiedHeapController::IncreaseAllocatedObjectSize(size_t delta_bytes) { - buffered_allocated_size_ += static_cast<int64_t>(delta_bytes); - ReportBufferedAllocatedSizeIfPossible(); -} - -void UnifiedHeapController::DecreaseAllocatedObjectSize(size_t delta_bytes) { - buffered_allocated_size_ -= static_cast<int64_t>(delta_bytes); - ReportBufferedAllocatedSizeIfPossible(); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/impl/unified_heap_controller.h b/third_party/blink/renderer/platform/heap/impl/unified_heap_controller.h deleted file mode 100644 index 574ab570..0000000 --- a/third_party/blink/renderer/platform/heap/impl/unified_heap_controller.h +++ /dev/null
@@ -1,72 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_UNIFIED_HEAP_CONTROLLER_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_UNIFIED_HEAP_CONTROLLER_H_ - -#include "third_party/blink/renderer/platform/heap/heap_stats_collector.h" -#include "third_party/blink/renderer/platform/platform_export.h" -#include "v8/include/v8.h" - -namespace blink { - -class ThreadState; - -// UnifiedHeapController ties V8's garbage collector to Oilpan for performing a -// garbage collection across both managed heaps. -// -// Unified heap garbage collections are triggered by V8 and mark the full -// transitive closure of V8 and Blink (Oilpan) objects. The garbage collection -// is initially triggered by V8. Both collecters report live references using -// the EmbedderHeapTracer APIs. V8 and Blink both run separate incremental -// marking steps to compute their live closures, respectively. The final atomic -// pause is then initiated by V8 and triggers a fixed-point computation between -// V8 and Blink where both GCs report live references to each other and drain -// their marking work lists until they are empty and no new references are -// found. -// -// Oilpan does not consider references from DOM wrappers (JavaScript objects on -// V8's heap) as roots for such garbage collections. -class PLATFORM_EXPORT UnifiedHeapController final - : public v8::EmbedderHeapTracer, - public ThreadHeapStatsObserver { - public: - UnifiedHeapController() = delete; - explicit UnifiedHeapController(ThreadState*); - UnifiedHeapController(const UnifiedHeapController&) = delete; - UnifiedHeapController& operator=(const UnifiedHeapController&) = delete; - ~UnifiedHeapController() override; - - // v8::EmbedderHeapTracer implementation. - void TracePrologue(v8::EmbedderHeapTracer::TraceFlags) final; - void TraceEpilogue(v8::EmbedderHeapTracer::TraceSummary*) final; - void EnterFinalPause(EmbedderStackState) final; - void RegisterV8References(const std::vector<std::pair<void*, void*>>&) final; - bool AdvanceTracing(double) final; - bool IsTracingDone() final; - - ThreadState* thread_state() const { return thread_state_; } - - // ThreadHeapStatsObserver implementation. - void IncreaseAllocatedObjectSize(size_t) final; - void DecreaseAllocatedObjectSize(size_t) final; - // Not needed. - void ResetAllocatedObjectSize(size_t) final {} - void IncreaseAllocatedSpace(size_t) final {} - void DecreaseAllocatedSpace(size_t) final {} - - private: - void ReportBufferedAllocatedSizeIfPossible(); - - ThreadState* const thread_state_; - // Returns whether the Blink heap has been fully processed. - bool is_tracing_done_ = false; - - // Buffered allocated size. Only positive values are forwarded to V8. - int64_t buffered_allocated_size_ = 0; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_UNIFIED_HEAP_CONTROLLER_H_
diff --git a/third_party/blink/renderer/platform/heap/impl/unified_heap_marking_visitor.cc b/third_party/blink/renderer/platform/heap/impl/unified_heap_marking_visitor.cc deleted file mode 100644 index 57c2e11d..0000000 --- a/third_party/blink/renderer/platform/heap/impl/unified_heap_marking_visitor.cc +++ /dev/null
@@ -1,109 +0,0 @@ -// 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/heap/unified_heap_marking_visitor.h" - -#include "third_party/blink/public/common/features.h" -#include "third_party/blink/renderer/platform/bindings/script_wrappable.h" -#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h" -#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h" -#include "third_party/blink/renderer/platform/heap/blink_gc.h" -#include "third_party/blink/renderer/platform/heap/thread_state.h" -#include "third_party/blink/renderer/platform/heap/unified_heap_controller.h" - -namespace blink { - -UnifiedHeapMarkingVisitorBase::UnifiedHeapMarkingVisitorBase( - ThreadState* thread_state, - v8::Isolate* isolate, - int task_id) - : isolate_(isolate), - controller_(thread_state->unified_heap_controller()), - v8_references_worklist_(thread_state->Heap().GetV8ReferencesWorklist(), - task_id), - task_id_(task_id) { - DCHECK(controller_); -} - -void UnifiedHeapMarkingVisitorBase::VisitImpl( - const TraceWrapperV8Reference<v8::Value>& v8_reference) { - DCHECK(isolate_); - if (v8_reference.IsEmptySafe()) - return; - if (task_id_ != WorklistTaskId::MutatorThread) { - // This is a temporary solution. Pushing directly from concurrent threads - // to V8 marking worklist will currently result in data races. This - // solution guarantees correctness until we implement a long-term solution - // (i.e. allowing Oilpan concurrent threads concurrent-safe access to V8 - // marking worklist without data-races) - v8_references_worklist_.Push(&v8_reference); - return; - } - controller_->RegisterEmbedderReference( - v8_reference.template Cast<v8::Data>().Get()); -} - -UnifiedHeapMarkingVisitor::UnifiedHeapMarkingVisitor(ThreadState* thread_state, - MarkingMode mode, - v8::Isolate* isolate) - : MarkingVisitor(thread_state, mode), - UnifiedHeapMarkingVisitorBase(thread_state, - isolate, - WorklistTaskId::MutatorThread) {} - -// static -void UnifiedHeapMarkingVisitor::WriteBarrier( - const TraceWrapperV8Reference<v8::Value>& object) { - if (object.IsEmpty() || !ThreadState::IsAnyIncrementalMarking()) - return; - - ThreadState* thread_state = ThreadState::Current(); - if (!thread_state->IsIncrementalMarking()) - return; - - thread_state->CurrentVisitor()->Trace(object); -} - -// static -void UnifiedHeapMarkingVisitor::WriteBarrier( - v8::Isolate* isolate, - v8::Local<v8::Object>&, - const WrapperTypeInfo* wrapper_type_info, - const void* object) { - // |object| here is either ScriptWrappable or CustomWrappable. - - if (!ThreadState::IsAnyIncrementalMarking()) - return; - - ThreadState* thread_state = ThreadState::Current(); - if (!thread_state->IsIncrementalMarking()) - return; - - wrapper_type_info->Trace(thread_state->CurrentVisitor(), object); -} - -void UnifiedHeapMarkingVisitor::Visit( - const TraceWrapperV8Reference<v8::Value>& v) { - VisitImpl(v); -} - -ConcurrentUnifiedHeapMarkingVisitor::ConcurrentUnifiedHeapMarkingVisitor( - ThreadState* thread_state, - MarkingMode mode, - v8::Isolate* isolate, - int task_id) - : ConcurrentMarkingVisitor(thread_state, mode, task_id), - UnifiedHeapMarkingVisitorBase(thread_state, isolate, task_id) {} - -void ConcurrentUnifiedHeapMarkingVisitor::FlushWorklists() { - ConcurrentMarkingVisitor::FlushWorklists(); - v8_references_worklist_.FlushToGlobal(); -} - -void ConcurrentUnifiedHeapMarkingVisitor::Visit( - const TraceWrapperV8Reference<v8::Value>& v) { - VisitImpl(v); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/impl/unified_heap_marking_visitor.h b/third_party/blink/renderer/platform/heap/impl/unified_heap_marking_visitor.h deleted file mode 100644 index 6d0f475..0000000 --- a/third_party/blink/renderer/platform/heap/impl/unified_heap_marking_visitor.h +++ /dev/null
@@ -1,94 +0,0 @@ -// 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. - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_UNIFIED_HEAP_MARKING_VISITOR_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_UNIFIED_HEAP_MARKING_VISITOR_H_ - -#include "third_party/blink/renderer/platform/heap/impl/marking_visitor.h" -#include "v8/include/v8.h" - -namespace v8 { -class EmbedderHeapTracer; -} - -namespace blink { - -struct WrapperTypeInfo; - -// Marking visitor for unified heap garbage collections. Extends the regular -// Oilpan marking visitor by also providing write barriers and visitation -// methods that allow for announcing reachable objects to V8. Visitor can be -// used from any thread. -class PLATFORM_EXPORT UnifiedHeapMarkingVisitorBase { - public: - UnifiedHeapMarkingVisitorBase(const UnifiedHeapMarkingVisitorBase&) = delete; - UnifiedHeapMarkingVisitorBase& operator=( - const UnifiedHeapMarkingVisitorBase&) = delete; - virtual ~UnifiedHeapMarkingVisitorBase() = default; - - protected: - UnifiedHeapMarkingVisitorBase(ThreadState*, v8::Isolate*, int); - - // Visitation methods that announce reachable wrappers to V8. - void VisitImpl(const TraceWrapperV8Reference<v8::Value>&); - - v8::Isolate* const isolate_; - v8::EmbedderHeapTracer* const controller_; - V8ReferencesWorklist::View v8_references_worklist_; - - private: - int task_id_; -}; - -// Same as the base visitor with the difference that it is bound to main thread. -// Also implements various sorts of write barriers that should only be called -// from the main thread. -class PLATFORM_EXPORT UnifiedHeapMarkingVisitor - : public MarkingVisitor, - public UnifiedHeapMarkingVisitorBase { - public: - // Write barriers for annotating a write during incremental marking. - static void WriteBarrier(const TraceWrapperV8Reference<v8::Value>&); - static void WriteBarrier(v8::Isolate*, - v8::Local<v8::Object>&, - const WrapperTypeInfo*, - const void*); - - UnifiedHeapMarkingVisitor(ThreadState*, MarkingMode, v8::Isolate*); - UnifiedHeapMarkingVisitor(const UnifiedHeapMarkingVisitor&) = delete; - UnifiedHeapMarkingVisitor& operator=(const UnifiedHeapMarkingVisitor&) = - delete; - ~UnifiedHeapMarkingVisitor() override = default; - - protected: - using Visitor::Visit; - void Visit(const TraceWrapperV8Reference<v8::Value>&) final; -}; - -// Same as the base visitor with the difference that it is bound to a -// concurrent thread. -class PLATFORM_EXPORT ConcurrentUnifiedHeapMarkingVisitor - : public ConcurrentMarkingVisitor, - public UnifiedHeapMarkingVisitorBase { - public: - ConcurrentUnifiedHeapMarkingVisitor(ThreadState*, - MarkingMode, - v8::Isolate*, - int task_id); - ConcurrentUnifiedHeapMarkingVisitor( - const ConcurrentUnifiedHeapMarkingVisitor&) = delete; - ConcurrentUnifiedHeapMarkingVisitor& operator=( - const ConcurrentUnifiedHeapMarkingVisitor&) = delete; - ~ConcurrentUnifiedHeapMarkingVisitor() override = default; - - void FlushWorklists() override; - - protected: - using Visitor::Visit; - void Visit(const TraceWrapperV8Reference<v8::Value>&) final; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_UNIFIED_HEAP_MARKING_VISITOR_H_
diff --git a/third_party/blink/renderer/platform/heap/impl/unsanitized_atomic.cc b/third_party/blink/renderer/platform/heap/impl/unsanitized_atomic.cc deleted file mode 100644 index 5bd25b9..0000000 --- a/third_party/blink/renderer/platform/heap/impl/unsanitized_atomic.cc +++ /dev/null
@@ -1,87 +0,0 @@ -// Copyright 2020 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/heap/impl/unsanitized_atomic.h" - -#include "cstdint" - -#include "base/compiler_specific.h" - -#if HAS_FEATURE(address_sanitizer) -#error "Must be built without asan." -#endif - -namespace blink { -namespace internal { - -namespace { -constexpr int ToGCCMemoryOrder(std::memory_order order) { - switch (order) { - case std::memory_order_seq_cst: - return __ATOMIC_SEQ_CST; - case std::memory_order_relaxed: - return __ATOMIC_RELAXED; - case std::memory_order_acquire: - return __ATOMIC_ACQUIRE; - case std::memory_order_release: - return __ATOMIC_RELEASE; - case std::memory_order_acq_rel: - return __ATOMIC_ACQ_REL; - case std::memory_order_consume: - return __ATOMIC_CONSUME; - } -} -} // namespace - -template <typename T> -void UnsanitizedAtomic<T>::store(T desired, std::memory_order order) { - __atomic_store(&value_, &desired, ToGCCMemoryOrder(order)); -} - -template <typename T> -T UnsanitizedAtomic<T>::load(std::memory_order order) const { - T result; - __atomic_load(&value_, &result, ToGCCMemoryOrder(order)); - return result; -} - -template <typename T> -bool UnsanitizedAtomic<T>::compare_exchange_strong(T& expected, - T desired, - std::memory_order order) { - return compare_exchange_strong(expected, desired, order, order); -} - -template <typename T> -bool UnsanitizedAtomic<T>::compare_exchange_strong( - T& expected, - T desired, - std::memory_order succ_order, - std::memory_order fail_order) { - return __atomic_compare_exchange(&value_, &expected, &desired, false, - ToGCCMemoryOrder(succ_order), - ToGCCMemoryOrder(fail_order)); -} - -template <typename T> -bool UnsanitizedAtomic<T>::compare_exchange_weak(T& expected, - T desired, - std::memory_order order) { - return compare_exchange_weak(expected, desired, order, order); -} - -template <typename T> -bool UnsanitizedAtomic<T>::compare_exchange_weak(T& expected, - T desired, - std::memory_order succ_order, - std::memory_order fail_order) { - return __atomic_compare_exchange(&value_, &expected, &desired, true, - ToGCCMemoryOrder(succ_order), - ToGCCMemoryOrder(fail_order)); -} - -template class PLATFORM_EXPORT UnsanitizedAtomic<uint16_t>; - -} // namespace internal -} // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/impl/unsanitized_atomic.h b/third_party/blink/renderer/platform/heap/impl/unsanitized_atomic.h deleted file mode 100644 index 7c6828d..0000000 --- a/third_party/blink/renderer/platform/heap/impl/unsanitized_atomic.h +++ /dev/null
@@ -1,65 +0,0 @@ -// Copyright 2020 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. - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_UNSANITIZED_ATOMIC_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_UNSANITIZED_ATOMIC_H_ - -#include <atomic> - -#include "third_party/blink/renderer/platform/platform_export.h" -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" - -namespace blink { -namespace internal { - -// Simple wrapper for std::atomic<> that makes sure that accesses to underlying -// data are not sanitized. This is needed because the no_sanitize_address -// attribute doesn't propagate down to callees. Must be used with care. -// Currently is only used to access poisoned HeapObjectHeader. For derived or -// user types an explicit instantiation must be added to unsanitized_atomic.cc. -template <typename T> -class PLATFORM_EXPORT UnsanitizedAtomic final { - public: - UnsanitizedAtomic() = default; - explicit UnsanitizedAtomic(T value) : value_(value) {} - - void store(T, std::memory_order = std::memory_order_seq_cst); - T load(std::memory_order = std::memory_order_seq_cst) const; - - bool compare_exchange_strong(T&, - T, - std::memory_order = std::memory_order_seq_cst); - bool compare_exchange_strong(T&, T, std::memory_order, std::memory_order); - - bool compare_exchange_weak(T&, - T, - std::memory_order = std::memory_order_seq_cst); - bool compare_exchange_weak(T&, T, std::memory_order, std::memory_order); - - private: - T value_; -}; - -template <typename T> -auto* AsUnsanitizedAtomic(T* ptr) { -#if defined(ADDRESS_SANITIZER) - return reinterpret_cast<UnsanitizedAtomic<T>*>(ptr); -#else - return WTF::AsAtomicPtr(ptr); -#endif -} - -template <typename T> -const auto* AsUnsanitizedAtomic(const T* ptr) { -#if defined(ADDRESS_SANITIZER) - return reinterpret_cast<const UnsanitizedAtomic<T>*>(ptr); -#else - return WTF::AsAtomicPtr(ptr); -#endif -} - -} // namespace internal -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_UNSANITIZED_ATOMIC_H_
diff --git a/third_party/blink/renderer/platform/heap/impl/visitor.h b/third_party/blink/renderer/platform/heap/impl/visitor.h deleted file mode 100644 index 8b16937..0000000 --- a/third_party/blink/renderer/platform/heap/impl/visitor.h +++ /dev/null
@@ -1,329 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_VISITOR_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_VISITOR_H_ - -#include <memory> -#include "third_party/blink/renderer/platform/heap/blink_gc.h" -#include "third_party/blink/renderer/platform/heap/garbage_collected.h" -#include "third_party/blink/renderer/platform/platform_export.h" -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" -#include "third_party/blink/renderer/platform/wtf/forward.h" -#include "third_party/blink/renderer/platform/wtf/hash_traits.h" -#include "third_party/blink/renderer/platform/wtf/type_traits.h" - -namespace base { -class Location; -} - -namespace v8 { -class Value; -} - -namespace blink { - -class LivenessBroker; -template <typename T> -struct TraceTrait; -class ThreadState; -class Visitor; -template <typename T> -class TraceWrapperV8Reference; - -// The TraceMethodDelegate is used to convert a trace method for type T to a -// TraceCallback. This allows us to pass a type's trace method as a parameter -// to the PersistentNode constructor. The PersistentNode constructor needs the -// specific trace method due an issue with the Windows compiler which -// instantiates even unused variables. This causes problems -// in header files where we have only forward declarations of classes. -// -// This interface is safe to use on concurrent threads. All accesses (reads) -// from member are done atomically. -template <typename T, void (T::*method)(Visitor*) const> -struct TraceMethodDelegate { - STATIC_ONLY(TraceMethodDelegate); - static void Trampoline(Visitor* visitor, const void* self) { - (reinterpret_cast<const T*>(self)->*method)(visitor); - } -}; - -template <typename T, void (T::*method)(const LivenessBroker&)> -struct WeakCallbackMethodDelegate { - STATIC_ONLY(WeakCallbackMethodDelegate); - static void Trampoline(const LivenessBroker& info, const void* self) { - (reinterpret_cast<T*>(const_cast<void*>(self))->*method)(info); - } -}; - -// Visitor is used to traverse Oilpan's object graph. -class PLATFORM_EXPORT Visitor { - USING_FAST_MALLOC(Visitor); - - public: - explicit Visitor(ThreadState* state) : state_(state) {} - virtual ~Visitor() = default; - - inline ThreadState* State() const { return state_; } - inline ThreadHeap& Heap() const { return state_->Heap(); } - - // Static visitor implementation forwarding to dynamic interface. - - template <typename T> - void TraceRoot(const T* t, const base::Location& location) { - static_assert(sizeof(T), "T must be fully defined"); - static_assert(IsGarbageCollectedType<T>::value, - "T needs to be a garbage collected object"); - if (!t) - return; - VisitRoot(t, TraceDescriptorFor(t), location); - } - - template <typename T> - void Trace(const Member<T>& t) { - const T* value = t.GetSafe(); - - DCHECK(!Member<T>::IsMemberHashTableDeletedValue(value)); - - Trace(value); - } - - // TraceStrongly strongifies WeakMembers. - template <typename T> - ALWAYS_INLINE void TraceStrongly(const WeakMember<T>& t) { - const T* value = t.GetSafe(); - - DCHECK(!WeakMember<T>::IsMemberHashTableDeletedValue(value)); - - Trace<T>(value); - } - // Fallback methods used only when we need to trace raw pointers of T. This is - // the case when a member is a union where we do not support members. - template <typename T> - void Trace(T* t) { - Trace(const_cast<const T*>(t)); - } - template <typename T> - void Trace(const T* t) { - static_assert(sizeof(T), "T must be fully defined"); - static_assert(IsGarbageCollectedType<T>::value, - "T needs to be a garbage collected object"); - if (!t) - return; - Visit(t, TraceDescriptorFor(t)); - } - - // WeakMember version of the templated trace method. It doesn't keep - // the traced thing alive, but will write null to the WeakMember later - // if the pointed-to object is dead. It's lying for this to be const, - // but the overloading resolver prioritizes constness too high when - // picking the correct overload, so all these trace methods have to have - // the same constness on their argument to allow the type to decide. - template <typename T> - void Trace(const WeakMember<T>& weak_member) { - static_assert(sizeof(T), "T must be fully defined"); - static_assert(IsGarbageCollectedType<T>::value, - "T needs to be a garbage collected object"); - - const T* value = weak_member.GetSafe(); - - if (!value) - return; - - DCHECK(!WeakMember<T>::IsMemberHashTableDeletedValue(value)); - VisitWeak(value, &weak_member, TraceDescriptorFor(value), - &HandleWeakCell<T>); - } - - // Fallback trace method for part objects to allow individual trace methods - // to trace through a part object with visitor->trace(m_partObject). This - // takes a const argument, because otherwise it will match too eagerly: a - // non-const argument would match a non-const Vector<T>& argument better - // than the specialization that takes const Vector<T>&. For a similar reason, - // the other specializations take a const argument even though they are - // usually used with non-const arguments, otherwise this function would match - // too well. - template <typename T> - void Trace(const T& t) { - static_assert(sizeof(T), "T must be fully defined"); - if (std::is_polymorphic<T>::value) { - const intptr_t vtable = *reinterpret_cast<const intptr_t*>(&t); - if (!vtable) - return; - } - TraceTrait<T>::Trace(this, &t); - } - - template <typename T, typename U> - void TraceEphemeron(const WeakMember<T>& key, const U* value) { - const T* t = key.GetSafe(); - if (!t) - return; - VisitEphemeron(TraceDescriptorFor(t).base_object_payload, - TraceDescriptorFor(value)); - } - - template <typename T> - void TraceWeakContainer(const T* object, - const T* const* slot, - TraceDescriptor strong_desc, - TraceDescriptor weak_dec, - WeakCallback weak_callback, - const void* weak_callback_parameter) { - static_assert(sizeof(T), "T must be fully defined"); - static_assert(IsGarbageCollectedType<T>::value, - "T needs to be a garbage collected object"); - VisitWeakContainer(reinterpret_cast<const void*>(object), - reinterpret_cast<const void* const*>(slot), strong_desc, - weak_dec, weak_callback, weak_callback_parameter); - } - - template <typename T> - void TraceMovablePointer(const T* const* slot) { - RegisterMovableSlot(reinterpret_cast<const void* const*>(slot)); - } - - // Cross-component tracing interface. - template <typename V8Type> - void Trace(const TraceWrapperV8Reference<V8Type>& v8reference) { - TraceV8ReferenceImpl(v8reference); - } - - // Dynamic visitor interface. - - // Adds a |callback| that is invoked with |parameter| after liveness has been - // computed on the whole object graph. The |callback| may use the provided - // |LivenessBroker| to determine whether an object is considered alive or - // dead. - // - // - Upon returning from the callback all references to dead objects must have - // been cleared. - // - Any operation that extends the object graph, including allocation - // or reviving objects, is prohibited. - // - Clearing out pointers is allowed. - // - Removing elements from heap collections is allowed as these collections - // are aware of custom weakness and won't resize their backings. - virtual void RegisterWeakCallback(WeakCallback callback, - const void* parameter) {} - - // Registers an instance method using |RegisterWeakCallback|. See description - // below. - template <typename T, void (T::*method)(const LivenessBroker&)> - void RegisterWeakCallbackMethod(const T* obj) { - RegisterWeakCallback(&WeakCallbackMethodDelegate<T, method>::Trampoline, - obj); - } - - // Returns whether the visitor is used in a concurrent setting. - virtual bool IsConcurrent() const { return false; } - - // Defers invoking |desc| to the main thread when running concurrently. - // Returns true if |desc| has been queued for later processing and false if - // running in a non-concurrent setting. - // - // This can be used to defer processing data structures to the main thread - // when support for concurrent processing is missing. - virtual bool DeferredTraceIfConcurrent(TraceDescriptor, size_t) { - return false; - } - - protected: - // Visits an object through a strong reference. - virtual void Visit(const void*, TraceDescriptor) {} - - // Visits an object through a weak reference. - virtual void VisitWeak(const void*, - const void*, - TraceDescriptor, - WeakCallback) {} - - // Visits cross-component references to V8. - virtual void Visit(const TraceWrapperV8Reference<v8::Value>&) {} - - virtual void VisitRoot(const void* t, - TraceDescriptor desc, - const base::Location&) { - Visit(t, desc); - } - - // Visits ephemeron pairs which are a combination of weak and strong keys and - // values. - virtual void VisitEphemeron(const void*, TraceDescriptor) {} - - // Visits a container |object| holding ephemeron pairs held from |slot|. The - // descriptor |strong_desc| can be used to enforce strong treatment of - // |object|. The |weak_desc| descriptor is invoked repeatedly until no - // more new objects are found. It is expected that |weak_desc| processing - // ultimately yields in a call to VisitEphemeron. After marking all reachable - // objects, |weak_callback| is invoked with |weak_callback_parameter|. It is - // expected that this callback is used to reset non-live entries in the - // ephemeron container. - virtual void VisitWeakContainer(const void* object, - const void* const* slot, - TraceDescriptor strong_desc, - TraceDescriptor weak_desc, - WeakCallback weak_callback, - const void* weak_callback_parameter) {} - - virtual void RegisterMovableSlot(const void* const* slot) {} - - template <typename T> - static TraceDescriptor TraceDescriptorFor(const T* traceable) { - return TraceTrait<T>::GetTraceDescriptor(traceable); - } - - private: - template <typename V8Type> - void TraceV8ReferenceImpl( - const TraceWrapperV8Reference<V8Type>& v8reference, - std::enable_if_t<std::is_base_of<v8::Value, V8Type>::value>* = nullptr) { - Visit(v8reference.template Cast<v8::Value>()); - } - - template <typename V8Type> - void TraceV8ReferenceImpl( - const TraceWrapperV8Reference<V8Type>& v8reference, - std::enable_if_t<!std::is_base_of<v8::Value, V8Type>::value && - std::is_base_of<v8::Data, V8Type>::value>* = nullptr) { - // The following cast is technically unsafe but works as the memory layout - // for the references is the same and V8 only needs to know that the value - // is a heap object. - Visit(v8reference.template UnsafeCast<v8::Value>()); - } - - template <typename T> - static void HandleWeakCell(const LivenessBroker&, const void*); - - ThreadState* const state_; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_VISITOR_H_
diff --git a/third_party/blink/renderer/platform/heap/impl/worklist.h b/third_party/blink/renderer/platform/heap/impl/worklist.h deleted file mode 100644 index a26c6189..0000000 --- a/third_party/blink/renderer/platform/heap/impl/worklist.h +++ /dev/null
@@ -1,469 +0,0 @@ -// 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. -// -// Copied and adopted from V8. -// -// Copyright 2017 the V8 project authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_WORKLIST_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_WORKLIST_H_ - -#include <atomic> -#include <cstddef> -#include <utility> - -#include "base/atomicops.h" -#include "base/check_op.h" -#include "base/compiler_specific.h" -#include "base/gtest_prod_util.h" -#include "base/synchronization/lock.h" -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" - -namespace blink { - -// A concurrent worklist based on segments. Each tasks gets private -// push and pop segments. Empty pop segments are swapped with their -// corresponding push segments. Full push segments are published to a global -// pool of segments and replaced with empty segments. -// -// Work stealing is best effort, i.e., there is no way to inform other tasks -// of the need of items. -template <typename _EntryType, int segment_size, int num_tasks = 4> -class Worklist { - USING_FAST_MALLOC(Worklist); - using WorklistType = Worklist<_EntryType, segment_size, num_tasks>; - - public: - using EntryType = _EntryType; - - static constexpr int kNumTasks = num_tasks; - - class View { - DISALLOW_NEW(); - - public: - View(WorklistType* worklist, int task_id) - : worklist_(worklist), task_id_(task_id) {} - - // Pushes an entry onto the worklist. - bool Push(EntryType entry) { return worklist_->Push(task_id_, entry); } - - // Pops an entry from the worklist. - bool Pop(EntryType* entry) { return worklist_->Pop(task_id_, entry); } - - // Returns true if the local portion of the worklist is empty. - bool IsLocalEmpty() const { return worklist_->IsLocalEmpty(task_id_); } - - // Returns true if the worklist is empty. Can only be used from the main - // thread without concurrent access. - bool IsGlobalEmpty() const { return worklist_->IsGlobalEmpty(); } - - bool IsGlobalPoolEmpty() const { return worklist_->IsGlobalPoolEmpty(); } - - // Returns true if the local portion and the global pool are empty (i.e. - // whether the current view cannot pop anymore). - bool IsLocalViewEmpty() const { - return worklist_->IsLocalViewEmpty(task_id_); - } - - void FlushToGlobal() { worklist_->FlushToGlobal(task_id_); } - - size_t LocalPushSegmentSize() const { - return worklist_->LocalPushSegmentSize(task_id_); - } - - private: - WorklistType* const worklist_; - const int task_id_; - }; - - static constexpr size_t kSegmentCapacity = segment_size; - - Worklist() { - for (int i = 0; i < kNumTasks; i++) { - private_push_segment(i) = NewSegment(); - private_pop_segment(i) = NewSegment(); - } - } - - ~Worklist() { - CHECK(IsGlobalEmpty()); - for (int i = 0; i < kNumTasks; i++) { - DCHECK(private_push_segment(i)); - DCHECK(private_pop_segment(i)); - delete private_push_segment(i); - delete private_pop_segment(i); - } - } - - bool Push(int task_id, EntryType entry) { - DCHECK_LT(task_id, kNumTasks); - DCHECK(private_push_segment(task_id)); - if (!private_push_segment(task_id)->Push(entry)) { - PublishPushSegmentToGlobal(task_id); - bool success = private_push_segment(task_id)->Push(entry); - ANALYZER_ALLOW_UNUSED(success); - DCHECK(success); - } - return true; - } - - bool Pop(int task_id, EntryType* entry) { - DCHECK_LT(task_id, kNumTasks); - DCHECK(private_pop_segment(task_id)); - if (!private_pop_segment(task_id)->Pop(entry)) { - if (!private_push_segment(task_id)->IsEmpty()) { - Segment* tmp = private_pop_segment(task_id); - private_pop_segment(task_id) = private_push_segment(task_id); - private_push_segment(task_id) = tmp; - } else if (!StealPopSegmentFromGlobal(task_id)) { - return false; - } - bool success = private_pop_segment(task_id)->Pop(entry); - ANALYZER_ALLOW_UNUSED(success); - DCHECK(success); - } - return true; - } - - bool IsLocalEmpty(int task_id) const { - return private_pop_segment(task_id)->IsEmpty() && - private_push_segment(task_id)->IsEmpty(); - } - - bool IsGlobalPoolEmpty() const { return global_pool_.IsEmpty(); } - - bool IsGlobalEmpty() const { - for (int i = 0; i < kNumTasks; i++) { - if (!IsLocalEmpty(i)) - return false; - } - return global_pool_.IsEmpty(); - } - - bool IsLocalViewEmpty(int task_id) const { - return IsLocalEmpty(task_id) && IsGlobalPoolEmpty(); - } - - size_t LocalSize(int task_id) const { - return private_pop_segment(task_id)->Size() + - private_push_segment(task_id)->Size(); - } - - // Thread-safe but may return an outdated result. - size_t GlobalPoolSize() const { return global_pool_.Size(); } - - size_t LocalPushSegmentSize(int task_id) const { - return private_push_segment(task_id)->Size(); - } - - // Clears all segments. Frees the global segment pool. - // - // Assumes that no other tasks are running. - void Clear() { - for (int i = 0; i < kNumTasks; i++) { - private_pop_segment(i)->Clear(); - private_push_segment(i)->Clear(); - } - global_pool_.Clear(); - } - - // Calls the specified callback on each element of the deques and replaces - // the element with the result of the callback. - // The signature of the callback is - // bool Callback(EntryType old, EntryType* new). - // If the callback returns |false| then the element is removed from the - // worklist. Otherwise the |new| entry is updated. - // - // Assumes that no other tasks are running. - template <typename Callback> - void Update(Callback callback) { - for (int i = 0; i < kNumTasks; i++) { - private_pop_segment(i)->Update(callback); - private_push_segment(i)->Update(callback); - } - global_pool_.Update(callback); - } - - template <typename Callback> - void IterateGlobalPool(Callback callback) { - global_pool_.Iterate(callback); - } - - void FlushToGlobal(int task_id) { - PublishPushSegmentToGlobal(task_id); - PublishPopSegmentToGlobal(task_id); - } - - void MergeGlobalPool(Worklist* other) { - global_pool_.Merge(&other->global_pool_); - } - - size_t SizeForTesting() { - size_t size = global_pool_.SizeForTesting(); - for (int i = 0; i < kNumTasks; i++) { - size += private_pop_segment(i)->Size() + private_push_segment(i)->Size(); - } - return size; - } - - private: - FRIEND_TEST_ALL_PREFIXES(WorklistTest, SegmentCreate); - FRIEND_TEST_ALL_PREFIXES(WorklistTest, SegmentPush); - FRIEND_TEST_ALL_PREFIXES(WorklistTest, SegmentPushPop); - FRIEND_TEST_ALL_PREFIXES(WorklistTest, SegmentIsEmpty); - FRIEND_TEST_ALL_PREFIXES(WorklistTest, SegmentIsFull); - FRIEND_TEST_ALL_PREFIXES(WorklistTest, SegmentClear); - FRIEND_TEST_ALL_PREFIXES(WorklistTest, SegmentFullPushFails); - FRIEND_TEST_ALL_PREFIXES(WorklistTest, SegmentEmptyPopFails); - FRIEND_TEST_ALL_PREFIXES(WorklistTest, SegmentUpdateFalse); - FRIEND_TEST_ALL_PREFIXES(WorklistTest, SegmentUpdate); - - class Segment { - USING_FAST_MALLOC(Segment); - - public: - static const size_t kCapacity = kSegmentCapacity; - - Segment() : index_(0) {} - - bool Push(EntryType entry) { - if (IsFull()) - return false; - entries_[index_++] = entry; - return true; - } - - bool Pop(EntryType* entry) { - if (IsEmpty()) - return false; - *entry = entries_[--index_]; - return true; - } - - size_t Size() const { return index_; } - bool IsEmpty() const { return index_ == 0; } - bool IsFull() const { return index_ == kCapacity; } - void Clear() { index_ = 0; } - - template <typename Callback> - void Update(Callback callback) { - size_t new_index = 0; - for (size_t i = 0; i < index_; i++) { - if (callback(entries_[i], &entries_[new_index])) { - new_index++; - } - } - index_ = new_index; - } - - template <typename Callback> - void Iterate(Callback callback) const { - for (size_t i = 0; i < index_; i++) { - callback(entries_[i]); - } - } - - Segment* next() const { return next_; } - void set_next(Segment* segment) { next_ = segment; } - - private: - Segment* next_; - size_t index_; - EntryType entries_[kCapacity]; - }; - - struct PrivateSegmentHolder { - Segment* private_push_segment; - Segment* private_pop_segment; - char cache_line_padding[64]; - }; - - class GlobalPool { - DISALLOW_NEW(); - - public: - GlobalPool() : top_(nullptr) {} - - inline void Push(Segment* segment) { - base::AutoLock guard(lock_); - segment->set_next(top_); - set_top(segment); - size_.fetch_add(1, std::memory_order_relaxed); - } - - inline bool Pop(Segment** segment) { - base::AutoLock guard(lock_); - if (top_) { - DCHECK_LT(0U, size_); - size_.fetch_sub(1, std::memory_order_relaxed); - *segment = top_; - set_top(top_->next()); - return true; - } - return false; - } - - inline bool IsEmpty() const { - return base::subtle::NoBarrier_Load( - reinterpret_cast<const base::subtle::AtomicWord*>(&top_)) == 0; - } - - inline size_t Size() const { - // It is safe to read |size_| without a lock since this variable is - // atomic, keeping in mind that threads may not immediately see the new - // value when it is updated. - return TS_UNCHECKED_READ(size_).load(std::memory_order_relaxed); - } - - void Clear() { - base::AutoLock guard(lock_); - size_.store(0, std::memory_order_relaxed); - Segment* current = top_; - while (current) { - Segment* tmp = current; - current = current->next(); - delete tmp; - } - set_top(nullptr); - } - - // See Worklist::Update. - template <typename Callback> - void Update(Callback callback) { - base::AutoLock guard(lock_); - Segment* prev = nullptr; - Segment* current = top_; - while (current) { - current->Update(callback); - if (current->IsEmpty()) { - DCHECK_LT(0U, size_); - size_.fetch_sub(1, std::memory_order_relaxed); - if (!prev) { - top_ = current->next(); - } else { - prev->set_next(current->next()); - } - Segment* tmp = current; - current = current->next(); - delete tmp; - } else { - prev = current; - current = current->next(); - } - } - } - - // See Worklist::Iterate. - template <typename Callback> - void Iterate(Callback callback) { - base::AutoLock guard(lock_); - for (Segment* current = top_; current; current = current->next()) { - current->Iterate(callback); - } - } - - void Merge(GlobalPool* other) { - Segment* top = nullptr; - size_t other_size = 0; - { - base::AutoLock guard(other->lock_); - if (!other->top_) - return; - top = other->top_; - other_size = other->size_.load(std::memory_order_relaxed); - other->size_.store(0, std::memory_order_relaxed); - other->set_top(nullptr); - } - - Segment* end = top; - while (end->next()) - end = end->next(); - - { - base::AutoLock guard(lock_); - size_.fetch_add(other_size, std::memory_order_relaxed); - end->set_next(top_); - set_top(top); - } - } - - size_t SizeForTesting() { - size_t size = 0; - base::AutoLock guard(lock_); - for (Segment* current = top_; current; current = current->next()) - size += current->Size(); - return size; - } - - private: - void set_top(Segment* segment) { - return base::subtle::NoBarrier_Store( - reinterpret_cast<base::subtle::AtomicWord*>(&top_), - reinterpret_cast<base::subtle::AtomicWord>(segment)); - } - - mutable base::Lock lock_; - Segment* top_ GUARDED_BY(lock_); - std::atomic<size_t> size_ GUARDED_BY(lock_){0}; - }; - - ALWAYS_INLINE Segment*& private_push_segment(int task_id) { - return private_segments_[task_id].private_push_segment; - } - - ALWAYS_INLINE Segment* const& private_push_segment(int task_id) const { - return const_cast<const PrivateSegmentHolder*>(private_segments_)[task_id] - .private_push_segment; - } - - ALWAYS_INLINE Segment*& private_pop_segment(int task_id) { - return private_segments_[task_id].private_pop_segment; - } - - ALWAYS_INLINE Segment* const& private_pop_segment(int task_id) const { - return const_cast<const PrivateSegmentHolder*>(private_segments_)[task_id] - .private_pop_segment; - } - - ALWAYS_INLINE void PublishPushSegmentToGlobal(int task_id) { - if (!private_push_segment(task_id)->IsEmpty()) { - global_pool_.Push(private_push_segment(task_id)); - private_push_segment(task_id) = NewSegment(); - } - } - - ALWAYS_INLINE void PublishPopSegmentToGlobal(int task_id) { - if (!private_pop_segment(task_id)->IsEmpty()) { - global_pool_.Push(private_pop_segment(task_id)); - private_pop_segment(task_id) = NewSegment(); - } - } - - ALWAYS_INLINE bool StealPopSegmentFromGlobal(int task_id) { - if (global_pool_.IsEmpty()) - return false; - Segment* new_segment = nullptr; - if (global_pool_.Pop(&new_segment)) { - delete private_pop_segment(task_id); - private_pop_segment(task_id) = new_segment; - return true; - } - return false; - } - - ALWAYS_INLINE Segment* NewSegment() { - // Bottleneck for filtering in crash dumps. - return new Segment(); - } - - PrivateSegmentHolder private_segments_[kNumTasks]; - GlobalPool global_pool_; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_IMPL_WORKLIST_H_
diff --git a/third_party/blink/renderer/platform/heap/member.h b/third_party/blink/renderer/platform/heap/member.h index 68ec7c42..b8487f1a 100644 --- a/third_party/blink/renderer/platform/heap/member.h +++ b/third_party/blink/renderer/platform/heap/member.h
@@ -5,16 +5,11 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_MEMBER_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_MEMBER_H_ -#include "third_party/blink/renderer/platform/wtf/buildflags.h" #include "third_party/blink/renderer/platform/wtf/hash_functions.h" #include "third_party/blink/renderer/platform/wtf/hash_traits.h" #include "third_party/blink/renderer/platform/wtf/type_traits.h" -#if BUILDFLAG(USE_V8_OILPAN) #include "third_party/blink/renderer/platform/heap/v8_wrapper/member.h" -#else // !USE_V8_OILPAN -#include "third_party/blink/renderer/platform/heap/impl/member.h" -#endif // !USE_V8_OILPAN namespace blink { @@ -102,19 +97,11 @@ } static void ConstructDeletedValue(MemberType& slot, bool) { -#if BUILDFLAG(USE_V8_OILPAN) slot = cppgc::kSentinelPointer; -#else // !USE_V8_OILPAN - slot = WTF::kHashTableDeletedValue; -#endif // !USE_V8_OILPAN } static bool IsDeletedValue(const MemberType& value) { -#if BUILDFLAG(USE_V8_OILPAN) return value.Get() == cppgc::kSentinelPointer; -#else // !USE_V8_OILPAN - return value.IsHashTableDeletedValue(); -#endif // !USE_V8_OILPAN } };
diff --git a/third_party/blink/renderer/platform/heap/persistent.h b/third_party/blink/renderer/platform/heap/persistent.h index 91e83824..8ad0b11 100644 --- a/third_party/blink/renderer/platform/heap/persistent.h +++ b/third_party/blink/renderer/platform/heap/persistent.h
@@ -6,16 +6,11 @@ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_PERSISTENT_H_ #include "third_party/blink/renderer/platform/heap/member.h" -#include "third_party/blink/renderer/platform/wtf/buildflags.h" #include "third_party/blink/renderer/platform/wtf/cross_thread_copier.h" #include "third_party/blink/renderer/platform/wtf/type_traits.h" #include "third_party/blink/renderer/platform/wtf/vector_traits.h" -#if BUILDFLAG(USE_V8_OILPAN) #include "third_party/blink/renderer/platform/heap/v8_wrapper/persistent.h" -#else // !USE_V8_OILPAN -#include "third_party/blink/renderer/platform/heap/impl/persistent.h" -#endif // !USE_V8_OILPAN namespace blink { @@ -85,19 +80,11 @@ static PeekOutType Peek(const PersistentType& value) { return value; } static void ConstructDeletedValue(PersistentType& slot, bool) { -#if BUILDFLAG(USE_V8_OILPAN) new (&slot) PersistentType(cppgc::kSentinelPointer); -#else // !USE_V8_OILPAN - new (&slot) PersistentType(WTF::kHashTableDeletedValue); -#endif // !USE_V8_OILPAN } static bool IsDeletedValue(const PersistentType& value) { -#if BUILDFLAG(USE_V8_OILPAN) return value.Get() == cppgc::kSentinelPointer; -#else // !USE_V8_OILPAN - return value.IsHashTableDeletedValue(); -#endif // !USE_V8_OILPAN } };
diff --git a/third_party/blink/renderer/platform/heap/process_heap.h b/third_party/blink/renderer/platform/heap/process_heap.h index 4993d40..d94b420 100644 --- a/third_party/blink/renderer/platform/heap/process_heap.h +++ b/third_party/blink/renderer/platform/heap/process_heap.h
@@ -5,12 +5,6 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_PROCESS_HEAP_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_PROCESS_HEAP_H_ -#include "third_party/blink/renderer/platform/wtf/buildflags.h" - -#if BUILDFLAG(USE_V8_OILPAN) #include "third_party/blink/renderer/platform/heap/v8_wrapper/process_heap.h" -#else // !USE_V8_OILPAN -#include "third_party/blink/renderer/platform/heap/impl/process_heap.h" -#endif // !USE_V8_OILPAN #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_PROCESS_HEAP_H_
diff --git a/third_party/blink/renderer/platform/heap/test/allocation_perftest.cc b/third_party/blink/renderer/platform/heap/test/allocation_perftest.cc index 85cfa0f..fe76ac4 100644 --- a/third_party/blink/renderer/platform/heap/test/allocation_perftest.cc +++ b/third_party/blink/renderer/platform/heap/test/allocation_perftest.cc
@@ -25,10 +25,8 @@ }; class LargeObject final : public GarbageCollected<LargeObject> { -#if BUILDFLAG(USE_V8_OILPAN) static constexpr size_t kLargeObjectSizeThreshold = cppgc::internal::api_constants::kLargeObjectSizeThreshold; -#endif // !BUILDFLAG(USE_V8_OILPAN) public: void Trace(Visitor*) const {} char padding[kLargeObjectSizeThreshold + 1];
diff --git a/third_party/blink/renderer/platform/heap/test/blink_gc_memory_dump_provider_test.cc b/third_party/blink/renderer/platform/heap/test/blink_gc_memory_dump_provider_test.cc index 0c68f331..00d3633 100644 --- a/third_party/blink/renderer/platform/heap/test/blink_gc_memory_dump_provider_test.cc +++ b/third_party/blink/renderer/platform/heap/test/blink_gc_memory_dump_provider_test.cc
@@ -10,10 +10,7 @@ #include "third_party/blink/renderer/platform/heap/blink_gc.h" #include "third_party/blink/renderer/platform/heap/heap_test_utilities.h" #include "third_party/blink/renderer/platform/wtf/threading.h" - -#if BUILDFLAG(USE_V8_OILPAN) #include "third_party/blink/renderer/platform/heap/v8_wrapper/custom_spaces.h" -#endif // !USE_V8_OILPAN namespace blink { @@ -52,7 +49,6 @@ void CheckSpacesInDump(base::trace_event::ProcessMemoryDump& dump, const std::string dump_prefix) { -#if BUILDFLAG(USE_V8_OILPAN) size_t custom_space_count = 0; IterateMemoryDumps( dump, dump_prefix + "CustomSpace", @@ -60,14 +56,6 @@ custom_space_count++; }); EXPECT_EQ(CustomSpaces::CreateCustomSpaces().size(), custom_space_count); -#else // !USE_V8_OILPAN -#define CheckArena(name) \ - EXPECT_NE(dump.allocator_dumps().end(), \ - dump.allocator_dumps().find(dump_prefix + #name "Arena")); - - FOR_EACH_ARENA(CheckArena) -#undef CheckArena -#endif // !USE_V8_OILPAN } } // namespace @@ -137,13 +125,8 @@ BlinkGCMemoryDumpProvider::HeapType::kBlinkWorkerThread)); dump_provider->OnMemoryDump(args, dump.get()); -#if BUILDFLAG(USE_V8_OILPAN) const std::string worker_path_prefix = "blink_gc/workers"; const std::string worker_path_suffix = "/heap"; -#else // !USE_V8_OILPAN - const std::string worker_path_prefix = "blink_gc/workers/heap"; - const std::string worker_path_suffix = ""; -#endif // !USE_V8_OILPAN // Find worker suffix. std::string worker_suffix;
diff --git a/third_party/blink/renderer/platform/heap/test/heap_test.cc b/third_party/blink/renderer/platform/heap/test/heap_test.cc index 026a6f1a..f22d1035 100644 --- a/third_party/blink/renderer/platform/heap/test/heap_test.cc +++ b/third_party/blink/renderer/platform/heap/test/heap_test.cc
@@ -46,10 +46,7 @@ #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h" #include "third_party/blink/renderer/platform/wtf/hash_traits.h" #include "third_party/blink/renderer/platform/wtf/threading_primitives.h" - -#if BUILDFLAG(USE_V8_OILPAN) #include "v8/include/cppgc/internal/api-constants.h" -#endif namespace blink { @@ -615,14 +612,10 @@ namespace { size_t GetOverallObjectSize() { -#if BUILDFLAG(USE_V8_OILPAN) return ThreadState::Current() ->cpp_heap() .CollectStatistics(cppgc::HeapStatistics::DetailLevel::kDetailed) .used_size_bytes; -#else // !BUILDFLAG(USE_V8_OILPAN) - return ThreadState::Current()->Heap().ObjectPayloadSizeForTesting(); -#endif // !BUILDFLAG(USE_V8_OILPAN) } } // namespace @@ -901,10 +894,8 @@ } // namespace TEST_F(HeapTest, HeapVectorOnStackLargeObjectPageSized) { -#if BUILDFLAG(USE_V8_OILPAN) static constexpr size_t kLargeObjectSizeThreshold = cppgc::internal::api_constants::kLargeObjectSizeThreshold; -#endif // !BUILDFLAG(USE_V8_OILPAN) ClearOutOldGarbage(); using Container = HeapVector<Member<IntWrapper>>; Container vector; @@ -2815,11 +2806,7 @@ } class AllocatesOnAssignment : public GarbageCollected<AllocatesOnAssignment> { -#if BUILDFLAG(USE_V8_OILPAN) static constexpr auto kHashTableDeletedValue = cppgc::kSentinelPointer; -#else // !USE_V8_OILPAN - static constexpr auto kHashTableDeletedValue = WTF::kHashTableDeletedValue; -#endif // !USE_V8_OILPAN public: AllocatesOnAssignment(std::nullptr_t) : value_(nullptr) {} @@ -2834,9 +2821,6 @@ enum DeletedMarker { kDeletedValue }; AllocatesOnAssignment(const AllocatesOnAssignment& other) { -#if !BUILDFLAG(USE_V8_OILPAN) - DCHECK(!ThreadState::Current()->IsGCForbidden()); -#endif TestSupportingGC::ConservativelyCollectGarbage(); value_ = MakeGarbageCollected<IntWrapper>(other.value_->Value()); } @@ -2845,11 +2829,7 @@ : value_(kHashTableDeletedValue) {} inline bool IsDeleted() const { -#if BUILDFLAG(USE_V8_OILPAN) return value_ == cppgc::kSentinelPointer; -#else // !USE_V8_OILPAN - return value_.IsHashTableDeletedValue(); -#endif // !USE_V8_OILPAN } void Trace(Visitor* visitor) const { visitor->Trace(value_); } @@ -3197,14 +3177,6 @@ namespace { class FakeCSSValue : public GarbageCollected<FakeCSSValue> { public: -#if !BUILDFLAG(USE_V8_OILPAN) - template <typename T> - static void* AllocateObject(size_t size) { - return ThreadState::Current()->Heap().AllocateOnArenaIndex( - ThreadState::Current(), size, BlinkGC::kCSSValueArenaIndex, - GCInfoTrait<GCInfoFoldedType<FakeCSSValue>>::Index(), "FakeCSSValue"); - } -#endif virtual void Trace(Visitor*) const {} char* Data() { return data_; } @@ -3215,14 +3187,6 @@ class FakeNode : public GarbageCollected<FakeNode> { public: -#if !BUILDFLAG(USE_V8_OILPAN) - template <typename T> - static void* AllocateObject(size_t size) { - return ThreadState::Current()->Heap().AllocateOnArenaIndex( - ThreadState::Current(), size, BlinkGC::kNodeArenaIndex, - GCInfoTrait<GCInfoFoldedType<FakeNode>>::Index(), "FakeNode"); - } -#endif virtual void Trace(Visitor*) const {} char* Data() { return data_; } @@ -3232,7 +3196,6 @@ }; } // namespace -#if BUILDFLAG(USE_V8_OILPAN) } // namespace blink namespace cppgc { @@ -3250,7 +3213,6 @@ } // namespace cppgc namespace blink { -#endif TEST_F(HeapTest, CollectNodeAndCssStatistics) { PreciselyCollectGarbage();
diff --git a/third_party/blink/renderer/platform/heap/thread_state.h b/third_party/blink/renderer/platform/heap/thread_state.h index eb763b5..0e077f4 100644 --- a/third_party/blink/renderer/platform/heap/thread_state.h +++ b/third_party/blink/renderer/platform/heap/thread_state.h
@@ -5,12 +5,6 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_THREAD_STATE_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_THREAD_STATE_H_ -#include "third_party/blink/renderer/platform/wtf/buildflags.h" - -#if BUILDFLAG(USE_V8_OILPAN) #include "third_party/blink/renderer/platform/heap/v8_wrapper/thread_state.h" -#else // !USE_V8_OILPAN -#include "third_party/blink/renderer/platform/heap/impl/thread_state.h" -#endif // !USE_V8_OILPAN #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_THREAD_STATE_H_
diff --git a/third_party/blink/renderer/platform/heap/thread_state_scopes.h b/third_party/blink/renderer/platform/heap/thread_state_scopes.h index 85e74893..9a64977 100644 --- a/third_party/blink/renderer/platform/heap/thread_state_scopes.h +++ b/third_party/blink/renderer/platform/heap/thread_state_scopes.h
@@ -6,13 +6,8 @@ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_THREAD_STATE_SCOPES_H_ #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" -#include "third_party/blink/renderer/platform/wtf/buildflags.h" -#if BUILDFLAG(USE_V8_OILPAN) #include "third_party/blink/renderer/platform/heap/v8_wrapper/thread_state_scopes.h" -#else // !USE_V8_OILPAN -#include "third_party/blink/renderer/platform/heap/impl/thread_state_scopes.h" -#endif // !USE_V8_OILPAN namespace blink {
diff --git a/third_party/blink/renderer/platform/heap/trace_traits.h b/third_party/blink/renderer/platform/heap/trace_traits.h index 76b89917..cb66498 100644 --- a/third_party/blink/renderer/platform/heap/trace_traits.h +++ b/third_party/blink/renderer/platform/heap/trace_traits.h
@@ -8,14 +8,9 @@ #include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/heap/member.h" #include "third_party/blink/renderer/platform/heap/visitor.h" -#include "third_party/blink/renderer/platform/wtf/buildflags.h" #include "third_party/blink/renderer/platform/wtf/hash_table.h" -#if BUILDFLAG(USE_V8_OILPAN) #include "third_party/blink/renderer/platform/heap/v8_wrapper/trace_traits.h" -#else // !USE_V8_OILPAN -#include "third_party/blink/renderer/platform/heap/impl/trace_traits.h" -#endif // !USE_V8_OILPAN namespace blink {
diff --git a/third_party/blink/renderer/platform/heap/unified_heap_controller.h b/third_party/blink/renderer/platform/heap/unified_heap_controller.h index c1fd663..01ab304 100644 --- a/third_party/blink/renderer/platform/heap/unified_heap_controller.h +++ b/third_party/blink/renderer/platform/heap/unified_heap_controller.h
@@ -5,10 +5,4 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_UNIFIED_HEAP_CONTROLLER_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_UNIFIED_HEAP_CONTROLLER_H_ -#include "third_party/blink/renderer/platform/wtf/buildflags.h" - -#if !BUILDFLAG(USE_V8_OILPAN) -#include "third_party/blink/renderer/platform/heap/impl/unified_heap_controller.h" -#endif // !BUILDFLAG(USE_V8_OILPAN) - #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_UNIFIED_HEAP_CONTROLLER_H_
diff --git a/third_party/blink/renderer/platform/heap/unified_heap_marking_visitor.h b/third_party/blink/renderer/platform/heap/unified_heap_marking_visitor.h index 267ee32..3c1576e 100644 --- a/third_party/blink/renderer/platform/heap/unified_heap_marking_visitor.h +++ b/third_party/blink/renderer/platform/heap/unified_heap_marking_visitor.h
@@ -5,12 +5,6 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_UNIFIED_HEAP_MARKING_VISITOR_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_UNIFIED_HEAP_MARKING_VISITOR_H_ -#include "third_party/blink/renderer/platform/wtf/buildflags.h" - -#if BUILDFLAG(USE_V8_OILPAN) #include "third_party/blink/renderer/platform/heap/v8_wrapper/unified_heap_marking_visitor.h" -#else // !USE_V8_OILPAN -#include "third_party/blink/renderer/platform/heap/impl/unified_heap_marking_visitor.h" -#endif // !USE_V8_OILPAN #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_UNIFIED_HEAP_MARKING_VISITOR_H_
diff --git a/third_party/blink/renderer/platform/heap/visitor.h b/third_party/blink/renderer/platform/heap/visitor.h index 5ace61d..9fb80dc 100644 --- a/third_party/blink/renderer/platform/heap/visitor.h +++ b/third_party/blink/renderer/platform/heap/visitor.h
@@ -5,12 +5,6 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_VISITOR_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_VISITOR_H_ -#include "third_party/blink/renderer/platform/wtf/buildflags.h" - -#if BUILDFLAG(USE_V8_OILPAN) #include "third_party/blink/renderer/platform/heap/v8_wrapper/visitor.h" -#else // !USE_V8_OILPAN -#include "third_party/blink/renderer/platform/heap/impl/visitor.h" -#endif // !USE_V8_OILPAN #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_VISITOR_H_
diff --git a/third_party/blink/renderer/platform/mojo/heap_mojo_associated_receiver_test.cc b/third_party/blink/renderer/platform/mojo/heap_mojo_associated_receiver_test.cc index 1902d1d..c9bbcf5 100644 --- a/third_party/blink/renderer/platform/mojo/heap_mojo_associated_receiver_test.cc +++ b/third_party/blink/renderer/platform/mojo/heap_mojo_associated_receiver_test.cc
@@ -14,7 +14,6 @@ #include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h" #include "third_party/blink/renderer/platform/mojo/mojo_binding_context.h" #include "third_party/blink/renderer/platform/testing/mock_context_lifecycle_notifier.h" -#include "third_party/blink/renderer/platform/wtf/buildflags.h" namespace blink {
diff --git a/third_party/blink/renderer/platform/mojo/heap_mojo_receiver_test.cc b/third_party/blink/renderer/platform/mojo/heap_mojo_receiver_test.cc index 6bdd9d1..d29810f 100644 --- a/third_party/blink/renderer/platform/mojo/heap_mojo_receiver_test.cc +++ b/third_party/blink/renderer/platform/mojo/heap_mojo_receiver_test.cc
@@ -15,7 +15,6 @@ #include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h" #include "third_party/blink/renderer/platform/mojo/mojo_binding_context.h" #include "third_party/blink/renderer/platform/testing/mock_context_lifecycle_notifier.h" -#include "third_party/blink/renderer/platform/wtf/buildflags.h" namespace blink {
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 3c38e93..2396d6bd 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -432,6 +432,7 @@ }, { name: "ConditionalFocus", + origin_trial_feature_name: "ConditionalFocus", depends_on: ["GetDisplayMedia"], status: {"Android": "", "default": "experimental"}, },
diff --git a/third_party/blink/renderer/platform/timer_test.cc b/third_party/blink/renderer/platform/timer_test.cc index d752a84..924641f4 100644 --- a/third_party/blink/renderer/platform/timer_test.cc +++ b/third_party/blink/renderer/platform/timer_test.cc
@@ -11,12 +11,12 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/platform/platform.h" +#include "third_party/blink/renderer/platform/heap/thread_state.h" #include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h" #include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h" #include "third_party/blink/renderer/platform/scheduler/public/thread.h" #include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h" #include "third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.h" -#include "third_party/blink/renderer/platform/wtf/buildflags.h" #include "third_party/blink/renderer/platform/wtf/ref_counted.h" using base::sequence_manager::TaskQueue; @@ -641,8 +641,7 @@ } // TODO(1056170): Re-enable test. -#if !BUILDFLAG(USE_V8_OILPAN) -TEST_F(TimerTest, MarkOnHeapTimerAsUnreachable) { +TEST_F(TimerTest, DISABLED_MarkOnHeapTimerAsUnreachable) { scoped_refptr<OnHeapTimerOwner::Record> record = OnHeapTimerOwner::Record::Create(); Persistent<OnHeapTimerOwner> owner = @@ -653,10 +652,12 @@ owner = nullptr; // Explicit regular GC call to allow lazy sweeping. - ThreadState::Current()->CollectGarbageForTesting( - BlinkGC::CollectionType::kMajor, BlinkGC::kNoHeapPointersOnStack, - BlinkGC::kAtomicMarking, BlinkGC::kConcurrentAndLazySweeping, - BlinkGC::GCReason::kForcedGCForTesting); + // TODO(1056170): Needs a specific forced GC call to be able to test the + // scenario below. + // ThreadState::Current()->CollectGarbageForTesting( + // BlinkGC::CollectionType::kMajor, BlinkGC::kNoHeapPointersOnStack, + // BlinkGC::kAtomicMarking, BlinkGC::kConcurrentAndLazySweeping, + // BlinkGC::GCReason::kForcedGCForTesting); // Since the heap is laziy swept, owner is not yet destructed. EXPECT_FALSE(record->OwnerIsDestructed()); @@ -666,10 +667,9 @@ platform_->RunUntilIdle(); EXPECT_FALSE(record->TimerHasFired()); EXPECT_FALSE(record->OwnerIsDestructed()); - ThreadState::Current()->CompleteSweep(); + // ThreadState::Current()->CompleteSweep(); } } -#endif // !USE_V8_OILPAN namespace {
diff --git a/third_party/blink/renderer/platform/wtf/BUILD.gn b/third_party/blink/renderer/platform/wtf/BUILD.gn index ea947cc..777c48c 100644 --- a/third_party/blink/renderer/platform/wtf/BUILD.gn +++ b/third_party/blink/renderer/platform/wtf/BUILD.gn
@@ -10,13 +10,6 @@ import("//third_party/blink/public/public_features.gni") import("//third_party/blink/renderer/config.gni") -buildflag_header("buildflags") { - header = "buildflags.h" - header_dir = "third_party/blink/renderer/platform/wtf" - - flags = [ "USE_V8_OILPAN=$enable_blink_heap_use_v8_oilpan" ] -} - visibility = [ ":*", "//:gn_all", @@ -211,7 +204,6 @@ ] deps = [ - ":buildflags", "//base/allocator:buildflags", "//build:chromeos_buildflags", @@ -226,9 +218,7 @@ "//third_party/icu", ] - if (enable_blink_heap_use_v8_oilpan) { - public_deps += [ "//v8:cppgc_headers" ] - } + public_deps += [ "//v8:cppgc_headers" ] # Rules changing the |sources| list are temporarily commented out, until # those files are actually moved to here.
diff --git a/third_party/blink/renderer/platform/wtf/type_traits.h b/third_party/blink/renderer/platform/wtf/type_traits.h index 562628a92..992c79d 100644 --- a/third_party/blink/renderer/platform/wtf/type_traits.h +++ b/third_party/blink/renderer/platform/wtf/type_traits.h
@@ -28,19 +28,7 @@ #include "base/compiler_specific.h" #include "base/template_util.h" #include "build/build_config.h" -#include "third_party/blink/renderer/platform/wtf/buildflags.h" - -#if BUILDFLAG(USE_V8_OILPAN) #include "v8/include/cppgc/type-traits.h" // nogncheck -#else // !BUILDFLAG(USE_V8_OILPAN) -namespace blink { -template <typename T> -class Member; -class Visitor; -template <typename T> -class WeakMember; -} // namespace blink -#endif // !BUILDFLAG(USE_V8_OILPAN) namespace WTF { @@ -117,8 +105,6 @@ static const bool value = sizeof(SubclassCheck(t_)) == sizeof(YesType); }; -#if BUILDFLAG(USE_V8_OILPAN) - template <typename T> struct IsTraceable : cppgc::internal::IsTraceable<T> {}; @@ -142,106 +128,6 @@ cppgc::IsMemberTypeV<T> || cppgc::IsWeakMemberTypeV<T>> {}; -#else // !USE_V8_OILPAN - -namespace internal { -// IsTraceMethodConst is used to verify that all Trace methods are marked as -// const. It is equivalent to IsTraceable but for a non-const object. -template <typename T, typename = void> -struct IsTraceMethodConst : std::false_type {}; - -template <typename T> -struct IsTraceMethodConst<T, - base::void_t<decltype(std::declval<const T>().Trace( - std::declval<blink::Visitor*>()))>> - : std::true_type {}; -} // namespace internal - -template <typename T, typename = void> -struct IsTraceable : std::false_type { - // Fail on incomplete types. - static_assert(sizeof(T), "incomplete type T"); -}; - -// Note: This also checks if a superclass of T has a trace method. -template <typename T> -struct IsTraceable<T, - base::void_t<decltype(std::declval<T>().Trace( - std::declval<blink::Visitor*>()))>> : std::true_type { - // All Trace methods should be marked as const. If an object of type - // 'T' is traceable then any object of type 'const T' should also - // be traceable. - static_assert(internal::IsTraceMethodConst<T>(), - "Trace methods should be marked as const."); -}; - -template <typename T> -class IsGarbageCollectedTypeInternal { - typedef char YesType; - typedef struct NoType { char padding[8]; } NoType; - - using NonConstType = typename std::remove_const<T>::type; - template <typename U> - static YesType CheckGarbageCollectedType( - typename U::IsGarbageCollectedTypeMarker*); - template <typename U> - static NoType CheckGarbageCollectedType(...); - - // Separately check for GarbageCollectedMixin, which declares a different - // marker typedef, to avoid resolution ambiguity for cases like - // IsGarbageCollectedType<B> over: - // - // class A : public GarbageCollected<A>, public GarbageCollectedMixin { - // ... - // }; - // class B : public A, public GarbageCollectedMixin { ... }; - // - template <typename U> - static YesType CheckGarbageCollectedMixinType( - typename U::IsGarbageCollectedMixinMarker*); - template <typename U> - static NoType CheckGarbageCollectedMixinType(...); - - public: - static const bool value = - (sizeof(YesType) == - sizeof(CheckGarbageCollectedType<NonConstType>(nullptr))) || - (sizeof(YesType) == - sizeof(CheckGarbageCollectedMixinType<NonConstType>(nullptr))); -}; - -template <typename T> -class IsGarbageCollectedType : public IsGarbageCollectedTypeInternal<T> { - static_assert(sizeof(T), "T must be fully defined"); -}; - -// Specifies whether a type should be treated weakly by the memory management -// system. Only supported by the garbage collector and not by PartitionAlloc. -// Requires garbage collection support, so it is only safe to override in sync -// with changing garbage collection semantics. -template <typename T> -struct IsWeak : std::false_type {}; - -template <typename T> -struct IsMemberType : std::integral_constant< - bool, - WTF::IsSubclassOfTemplate<T, blink::Member>::value> { -}; - -template <typename T> -struct IsWeakMemberType - : std::integral_constant< - bool, - WTF::IsSubclassOfTemplate<T, blink::WeakMember>::value> {}; - -template <typename T> -struct IsMemberOrWeakMemberType - : std::integral_constant<bool, - IsMemberType<T>::value || - IsWeakMemberType<T>::value> {}; - -#endif // !USE_V8_OILPAN - template <typename T, typename U> struct IsTraceable<std::pair<T, U>> : std::integral_constant<bool,
diff --git a/third_party/blink/tools/blinkpy/web_tests/run_web_tests.py b/third_party/blink/tools/blinkpy/web_tests/run_web_tests.py index 5d80bc24..e64e17ce 100644 --- a/third_party/blink/tools/blinkpy/web_tests/run_web_tests.py +++ b/third_party/blink/tools/blinkpy/web_tests/run_web_tests.py
@@ -155,7 +155,7 @@ help=('Do not log Zircon debug messages.')), optparse.make_option('--device', choices=['aemu', 'qemu', 'device', 'fvdl'], - default='aemu', + default='fvdl', help=('Choose device to launch Fuchsia with. ' 'Defaults to AEMU.')), optparse.make_option('--fuchsia-target-cpu',
diff --git a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng index 28d8030..b9fe83e8 100644 --- a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng +++ b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
@@ -297,7 +297,7 @@ crbug.com/1157740 external/wpt/css/css-sizing/aspect-ratio/flex-aspect-ratio-002.html [ Pass ] crbug.com/1157740 external/wpt/css/css-sizing/aspect-ratio/flex-aspect-ratio-004.html [ Pass ] crbug.com/1157740 external/wpt/css/css-sizing/aspect-ratio/flex-aspect-ratio-024.html [ Failure ] -crbug.com/1157740 external/wpt/css/css-sizing/aspect-ratio/flex-aspect-ratio-025.html [ Pass ] +crbug.com/1157740 external/wpt/css/css-sizing/aspect-ratio/flex-aspect-ratio-026.html [ Failure ] crbug.com/591099 external/wpt/css/css-sizing/clone-nowrap-intrinsic-size-bidi.html [ Failure ] crbug.com/591099 external/wpt/css/css-sizing/intrinsic-percent-non-replaced-004.html [ Failure ] crbug.com/591099 external/wpt/css/css-sizing/intrinsic-percent-non-replaced-005.html [ Failure ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 76b8a4e..78b1230 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -781,8 +781,6 @@ #### external/wpt/css/css-sizing crbug.com/1251788 external/wpt/css/css-sizing/aspect-ratio/flex-aspect-ratio-002.html [ Failure ] -crbug.com/1166834 external/wpt/css/css-sizing/aspect-ratio/flex-aspect-ratio-025.html [ Failure ] -crbug.com/1166834 external/wpt/css/css-sizing/aspect-ratio/flex-aspect-ratio-026.html [ Failure ] crbug.com/970201 external/wpt/css/css-sizing/slice-intrinsic-size.html [ Failure ] crbug.com/970201 external/wpt/css/css-sizing/clone-intrinsic-size.html [ Failure ] @@ -2851,8 +2849,8 @@ crbug.com/626703 virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/worker-interception.https.html [ Pass ] # ====== New tests from wpt-importer added here ====== -crbug.com/626703 [ Linux ] virtual/threaded/external/wpt/animation-worklet/worklet-animation-start-delay.https.html [ Crash ] -crbug.com/626703 [ Mac10.15 ] virtual/threaded/external/wpt/animation-worklet/worklet-animation-start-delay.https.html [ Crash ] +crbug.com/626703 [ Linux ] virtual/threaded/external/wpt/animation-worklet/worklet-animation-start-delay.https.html [ Failure ] +crbug.com/626703 [ Mac10.15 ] virtual/threaded/external/wpt/animation-worklet/worklet-animation-start-delay.https.html [ Failure ] crbug.com/626703 [ Linux ] external/wpt/html/semantics/forms/the-selectmenu-element/selectmenu-parts-structure.tentative.html [ Timeout ] crbug.com/626703 [ Mac ] external/wpt/html/semantics/forms/the-selectmenu-element/selectmenu-parts-structure.tentative.html [ Timeout ] crbug.com/626703 [ Linux ] virtual/synchronous_html_parser/external/wpt/html/semantics/forms/the-selectmenu-element/selectmenu-parts-structure.tentative.html [ Timeout ]
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json index bbc69ad0..4c355a0 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -2600,49 +2600,49 @@ }, "icons-member": { "icons-member-cors-fail-manual.sub.html": [ - "a6acdd4b0147184c1b73d153657a1b6e6090ba45", + "f49dac6057ae12f97f524ba5d3a61ffa94b10be8", [ null, {} ] ], "icons-member-cors-manual.sub.html": [ - "a54f3629caf7ab7f55ecb60e46007f62a3d1b51a", + "aa0fe89db653fe5db1da5ddd5fcb91ff2625eb99", [ null, {} ] ], "icons-member-csp-fail-manual.sub.html": [ - "7f35fc318e8c0c38ad576578537e024b2dc0ce4b", + "e4706011f8437dcad920644dafc313ee7889f659", [ null, {} ] ], "icons-member-csp-manual.sub.html": [ - "15e09129e972b907033968b0b49205d98dfb334b", + "c76364b83feab36ff16d1a54981cb6f85df7eec5", [ null, {} ] ], "icons-member-last-matching-manual.html": [ - "04f18f47e2090987352a707a54c7857c75b446b4", + "a02ddc3a50294b6977e8919aa2aa2ab66935622a", [ null, {} ] ], "icons-member-manual.html": [ - "f42db8d6b273e498be0f0e66daa6087f4063716f", + "6a9b7620ed1c102391ebb4f1987f2fcfa5c219e5", [ null, {} ] ], "icons-member-next-appropriate-manual.html": [ - "1e84ba948f028e67ff31d65dea85400e972e311c", + "8e87fc106207f97f92b710769d637bbd71bd3497", [ null, {} @@ -2674,6 +2674,15 @@ ] ] }, + "protocol_handlers-member": { + "protocol_handlers-member-manual.tentative.html": [ + "fa9c958e0e4ba03a3820f2364314ffc1fff7b93f", + [ + null, + {} + ] + ] + }, "short_name-member": { "short_name-member-manual.html": [ "2ccb68cf0a7007c58b8a6c3e32fddc85690b2b86", @@ -134156,6 +134165,19 @@ {} ] ], + "highlight-cascade-004.html": [ + "eb181096ce1ee035aa10e21e6f35fba58c5c7acb", + [ + null, + [ + [ + "/css/css-pseudo/highlight-cascade-004-ref.html", + "==" + ] + ], + {} + ] + ], "highlight-painting-001.html": [ "ef253e6117c94ef63f9be97eaac0d94667c9fce3", [ @@ -214478,6 +214500,12 @@ ] } }, + "currentchange-event": { + "currentchange-app-history-reload-transitionWhile-expected.txt": [ + "4f115e002d99400418c9fca8f85a490cb10fe9ff", + [] + ] + }, "navigate": { "reload-service-worker-fetch-event-expected.txt": [ "cf4b285328a985e8413570fcc80e16d4501b3d09", @@ -214657,74 +214685,84 @@ } }, "icons-member": { - "fail.png": [ - "1d596c6ba6ab8a6a2636ce524a8cd8cf06538b41", + "icons-member-service-worker.js": [ + "21b07f8515a1cdc225a72884fc40899fe57f5afe", [] ], - "icons-member-cors-fail.sub.webmanifest": [ - "e8b9327ed8fec3b30d7ba2dafc31a73b269c0a19", - [] - ], - "icons-member-cors-fail.webmanifest.headers": [ - "2bab061d43ab9e533b0160ca506231939886cd89", - [] - ], - "icons-member-cors.sub.webmanifest": [ - "5d95262af3e7842eb3e4e79b87c3f98e86ad1fd7", - [] - ], - "icons-member-cors.webmanifest.headers": [ - "2bab061d43ab9e533b0160ca506231939886cd89", - [] - ], - "icons-member-csp-fail.webmanifest": [ - "a17364871ec00da8a5f13ebc434b3873fcef1e4e", - [] - ], - "icons-member-csp-fail.webmanifest.headers": [ - "2bab061d43ab9e533b0160ca506231939886cd89", - [] - ], - "icons-member-csp.sub.webmanifest": [ - "5d95262af3e7842eb3e4e79b87c3f98e86ad1fd7", - [] - ], - "icons-member-csp.webmanifest.headers": [ - "2bab061d43ab9e533b0160ca506231939886cd89", - [] - ], - "icons-member-last-matching.webmanifest": [ - "f4423d28f7e743013c7aa6fafe8aeb9db10dc52a", - [] - ], - "icons-member-last-matching.webmanifest.headers": [ - "2bab061d43ab9e533b0160ca506231939886cd89", - [] - ], - "icons-member-next-appropriate.webmanifest": [ - "5ae381ec65ebff3a43c6921d2386076d8f21f957", - [] - ], - "icons-member-next-appropriate.webmanifest.headers": [ - "2bab061d43ab9e533b0160ca506231939886cd89", - [] - ], - "icons-member.webmanifest": [ - "a744fee8a828f33ce6d4972c80b67c614db5df9b", - [] - ], - "icons-member.webmanifest.headers": [ - "2bab061d43ab9e533b0160ca506231939886cd89", - [] - ], - "pass.png": [ - "be7433a3e2c305ff699e74f9bbd56e87484ba35c", - [] - ], - "pass.png.sub.headers": [ - "adf190aa8ea92e24e74c3c90f21d2155f809abbe", - [] - ] + "resources": { + "fail.png": [ + "1d596c6ba6ab8a6a2636ce524a8cd8cf06538b41", + [] + ], + "icons-member-cors-fail.sub.webmanifest": [ + "24e2214365bd218697e479d7537edbe37d9e7c5d", + [] + ], + "icons-member-cors-fail.webmanifest.headers": [ + "2bab061d43ab9e533b0160ca506231939886cd89", + [] + ], + "icons-member-cors.sub.webmanifest": [ + "33cb12654b662dbcf4334a5607e038fb84850608", + [] + ], + "icons-member-cors.webmanifest.headers": [ + "2bab061d43ab9e533b0160ca506231939886cd89", + [] + ], + "icons-member-csp-fail.webmanifest": [ + "2b614ebb01fef241b434e90d77899a9d6380857b", + [] + ], + "icons-member-csp-fail.webmanifest.headers": [ + "2bab061d43ab9e533b0160ca506231939886cd89", + [] + ], + "icons-member-csp.sub.webmanifest": [ + "f1089bba3c57afd7f1cc8feee5d903154672a6f2", + [] + ], + "icons-member-csp.webmanifest.headers": [ + "2bab061d43ab9e533b0160ca506231939886cd89", + [] + ], + "icons-member-last-matching.webmanifest": [ + "04ac33112d576d6723266ec5a7c99023686f973b", + [] + ], + "icons-member-last-matching.webmanifest.headers": [ + "2bab061d43ab9e533b0160ca506231939886cd89", + [] + ], + "icons-member-manual.js": [ + "cf149792a3ee7c63d72b01d95604b32e526c7373", + [] + ], + "icons-member-next-appropriate.webmanifest": [ + "e65169b06a2f5873f47dee9c6235d5f66229d761", + [] + ], + "icons-member-next-appropriate.webmanifest.headers": [ + "2bab061d43ab9e533b0160ca506231939886cd89", + [] + ], + "icons-member.webmanifest": [ + "8e7a2c34268c8878d99372dfb9948c44d3e8ed7e", + [] + ], + "icons-member.webmanifest.headers": [ + "2bab061d43ab9e533b0160ca506231939886cd89", + [] + ], + "pass.png": [ + "be7433a3e2c305ff699e74f9bbd56e87484ba35c", + [] + ], + "pass.png.sub.headers": [ + "adf190aa8ea92e24e74c3c90f21d2155f809abbe", + [] + ] + } }, "name-member": { "name-member-fail.webmanifest": [ @@ -214762,6 +214800,30 @@ [] ] }, + "protocol_handlers-member": { + "protocol_handlers-member-service-worker.js": [ + "e502e2a9859f6df6f4793fb43e155623c8547a94", + [] + ], + "resources": { + "icon.png": [ + "9255547fae08775cce76b769ad4c6d13cc9b241a", + [] + ], + "protocol_handlers-member.webmanifest": [ + "cce6ae1e22b7813db32b060d86e5c499f6f3d84f", + [] + ], + "protocol_handlers-member.webmanifest.headers": [ + "2bab061d43ab9e533b0160ca506231939886cd89", + [] + ], + "protocol_handlers_entry.html": [ + "c5fa629f22bfdabef4cac02927646f76f66baafc", + [] + ] + } + }, "short_name-member": { "short_name-member.webmanifest": [ "66f357e294cb810a90e6b39f9d87a7a45ab8029d", @@ -233961,7 +234023,7 @@ [] ], "font-palette-values-valid-expected.txt": [ - "d8f9ffbb55ae057e1ee3e637bb19e1bce1a46cfe", + "252eb64ff6414742251f11b772d35d730290d146", [] ], "font-size-adjust-computed-expected.txt": [ @@ -246179,6 +246241,10 @@ "256c28ba0c068630cf675698e019b656a6c56da7", [] ], + "highlight-cascade-004-ref.html": [ + "f9bf83f9c1d63b50b61b96a4edadc1241d3c640b", + [] + ], "highlight-painting-001-ref.html": [ "c5d8814a8252b0a8e4be1b43f635cd7b11f548fc", [] @@ -256225,6 +256291,14 @@ "8b1783d785c1cbd71cbeecb58bd21dcb18edf763", [] ], + "round-mod-rem-serialize-expected.txt": [ + "162be5e295a67ef0c12240a65387e8490f3221a9", + [] + ], + "signs-abs-serialize-expected.txt": [ + "2dc9ef1833ebaf5354f62518f85f6b2c700d0802", + [] + ], "sin-cos-tan-computed-expected.txt": [ "30a56d770fdd6004c52441c671c5f27ee5ad1758", [] @@ -319955,6 +320029,162 @@ ] ] }, + "currentchange-event": { + "currentchange-anchor-href.html": [ + "2a93abf9937942200d4c2d28c8051456de438003", + [ + null, + {} + ] + ], + "currentchange-app-history-back-forward-cross-doc.html": [ + "7782d11b0c31a578637f9b7c17c00f95fe6f3cec", + [ + null, + {} + ] + ], + "currentchange-app-history-back-forward-same-doc.html": [ + "85a93a21bd0f4a708dc99b751c533342743410ce", + [ + null, + {} + ] + ], + "currentchange-app-history-navigate-cross-doc.html": [ + "d6a657a1b1174ce0f3ced3bba8fd617620fefc3d", + [ + null, + {} + ] + ], + "currentchange-app-history-navigate-preventDefault.html": [ + "82f10006832e16522844cdb7fa0bcf2e6a3a8578", + [ + null, + {} + ] + ], + "currentchange-app-history-navigate-replace-cross-doc.html": [ + "3d8ceb746b80da1564a539e080ae965aa30d03b9", + [ + null, + {} + ] + ], + "currentchange-app-history-navigate-replace-same-doc.html": [ + "2967f21d973aa6e6dd8b38ad0b1d0b7e09917d93", + [ + null, + {} + ] + ], + "currentchange-app-history-navigate-replace-transitionWhile.html": [ + "86079e777cb9059b13e6763ea31877475142d368", + [ + null, + {} + ] + ], + "currentchange-app-history-navigate-same-doc.html": [ + "d112e2592806e8fe9830de8fbb2e8b2a8f1a97c7", + [ + null, + {} + ] + ], + "currentchange-app-history-navigate-transitionWhile.html": [ + "d6a39d204ed72c6d578556798e1b9527f58ba219", + [ + null, + {} + ] + ], + "currentchange-app-history-reload-cross-doc.html": [ + "ae142fb5d3bc4d600037077cf5bbbbcece64b6f2", + [ + null, + {} + ] + ], + "currentchange-app-history-reload-transitionWhile.html": [ + "d1f022f584218fec9fb6fb584175adabd7a1a286", + [ + null, + {} + ] + ], + "currentchange-app-history-updateCurrent.html": [ + "9e3a3ec387a2ce682e433dc39c6d2e94bfb3f27e", + [ + null, + {} + ] + ], + "currentchange-dispose-ordering.html": [ + "f9d23f7dd5da79afb95bd998c618685c225c9e6a", + [ + null, + {} + ] + ], + "currentchange-history-back-same-doc.html": [ + "7cfecb15b8ef9e4dc4e2cf678262e889b8d02550", + [ + null, + {} + ] + ], + "currentchange-history-pushState.html": [ + "e5468eafc3938f71c907410ed33fad1a184141ce", + [ + null, + {} + ] + ], + "currentchange-history-replaceState.html": [ + "5a99561ebd2f929e082cfd6b7938898f03243747", + [ + null, + {} + ] + ], + "currentchange-location-api.html": [ + "8cf52ca6d288387036a5d93a007f33c1c79deef3", + [ + null, + {} + ] + ], + "currentchange-navigate-from-initial-about-blank-same-doc.html": [ + "80782613203ae437937cc7de7f440c9446224d50", + [ + null, + {} + ] + ], + "currentchange-navigate-from-initial-about-blank.html": [ + "f97e1e898e94b4790c2d138ebcd48dee2b638626", + [ + null, + {} + ] + ], + "currentchange-properties.html": [ + "a5417fa312c1b43db84b90c7f67fa1ab88be9333", + [ + null, + {} + ] + ], + "event-constructor.html": [ + "6c489363567fd61d210ad92e8336605ea02f1704", + [ + null, + {} + ] + ] + }, "navigate": { "back-forward-multiple-frames.html": [ "80a8fb65a05fb622988e8f64ac78f16c9172869d", @@ -342624,7 +342854,7 @@ ] ], "font-palette-values-valid.html": [ - "c6774efbb14931ebf50808c3cb35fbff8a1379b8", + "665841cc21a5f5aab6ec897a301446003364f5cd", [ null, {} @@ -360232,6 +360462,48 @@ {} ] ], + "round-mod-rem-computed.html": [ + "a98e4a4332250c08b5996a03455a682d26abdc5e", + [ + null, + {} + ] + ], + "round-mod-rem-invalid.html": [ + "99ef2c64b453ac0b56580378a1c4ab59577e90b4", + [ + null, + {} + ] + ], + "round-mod-rem-serialize.html": [ + "490249591947022e09c58b69f1c703483fad2e7d", + [ + null, + {} + ] + ], + "signs-abs-computed.html": [ + "ba672f23cec532befccc2947c4ee14e48d1e2a79", + [ + null, + {} + ] + ], + "signs-abs-invalid.html": [ + "15b058d0c42bade38f083838eaaabadc64410627", + [ + null, + {} + ] + ], + "signs-abs-serialize.html": [ + "b7b5ad2b7529fd81cfc54909c333aed588632549", + [ + null, + {} + ] + ], "sin-cos-tan-computed.html": [ "7f85727bdbad130c9dae323e4e0c9b249c5132aa", [ @@ -432328,15 +432600,6 @@ {} ] ], - "popup-light-dismiss-resize.tentative.html": [ - "cec65f77dcaddfd170581992ddec02c53619898e", - [ - null, - { - "testdriver": true - } - ] - ], "popup-light-dismiss.tentative.html": [ "e0012587fd217a935409b6c70af4db5c94a73332", [
diff --git a/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-anchor-href.html b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-anchor-href.html new file mode 100644 index 0000000..2a93abf --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-anchor-href.html
@@ -0,0 +1,18 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<a id="a" href="#foo"></a> +<script> +test(t => { + let oncurrentchange_called = false; + appHistory.oncurrentchange = t.step_func(e => { + oncurrentchange_called = true; + assert_equals(e.from, appHistory.entries()[0]); + assert_equals(e.from.index, 0); + assert_equals(e.navigationType, "push"); + assert_equals(appHistory.current.index, 1); + }); + a.click(); + assert_true(oncurrentchange_called); +}, "AppHistoryCurrentChangeEvent fires for link click"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-back-forward-cross-doc.html b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-back-forward-cross-doc.html new file mode 100644 index 0000000..7782d11 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-back-forward-cross-doc.html
@@ -0,0 +1,20 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<iframe id="i" src="/common/blank.html"></iframe> +<script> +promise_test(async t => { + await new Promise(resolve => window.onload = resolve); + i.contentWindow.appHistory.navigate("/common/blank.html?1"); + await new Promise(resolve => i.onload = resolve); + assert_equals(i.contentWindow.appHistory.entries().length, 2); + + i.contentWindow.appHistory.oncurrentchange = t.unreached_func("currentchange should not fire for cross-document navigations"); + i.contentWindow.appHistory.back(); + await new Promise(resolve => i.onload = resolve); + + i.contentWindow.appHistory.oncurrentchange = t.unreached_func("currentchange should not fire for cross-document navigations"); + i.contentWindow.appHistory.forward(); + await new Promise(resolve => i.onload = resolve); +}, "AppHistoryCurrentChangeEvent does not fire for cross-document appHistory.back() and appHistory.forward()"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-back-forward-same-doc.html b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-back-forward-same-doc.html new file mode 100644 index 0000000..85a93a21 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-back-forward-same-doc.html
@@ -0,0 +1,40 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +promise_test(async t => { + // Wait for after the load event so that the navigation doesn't get converted + // into a replace navigation. + await new Promise(resolve => window.onload = t.step_timeout(resolve, 0)); + await appHistory.navigate("#foo"); + assert_equals(appHistory.entries().length, 2); + + let oncurrentchange_back_called = false; + let back_committed = false; + appHistory.oncurrentchange = t.step_func(e => { + oncurrentchange_back_called = true; + assert_equals(e.from, appHistory.entries()[1]); + assert_equals(e.navigationType, "traverse"); + assert_equals(appHistory.current.index, 0); + assert_false(back_committed); + }); + let back_result = appHistory.back(); + assert_false(oncurrentchange_back_called); + await back_result.committed.then(() => back_committed = true); + assert_true(oncurrentchange_back_called); + + let oncurrentchange_forward_called = false; + let forward_committed = false; + appHistory.oncurrentchange = t.step_func(e => { + oncurrentchange_forward_called = true; + assert_equals(e.from, appHistory.entries()[0]); + assert_equals(e.navigationType, "traverse"); + assert_equals(appHistory.current.index, 1); + assert_false(forward_committed); + }); + let forward_result = appHistory.forward(); + assert_false(oncurrentchange_forward_called); + await forward_result.committed.then(() => forward_committed = true); + assert_true(oncurrentchange_forward_called); +}, "AppHistoryCurrentChangeEvent fires for appHistory.back() and appHistory.forward()"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-navigate-cross-doc.html b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-navigate-cross-doc.html new file mode 100644 index 0000000..d6a657a1 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-navigate-cross-doc.html
@@ -0,0 +1,12 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<iframe id="i" src="/common/blank.html"></iframe> +<script> +promise_test(async t => { + await new Promise(resolve => window.onload = resolve); + i.contentWindow.appHistory.oncurrentchange = t.unreached_func("currentchange should not fire for cross-document navigations"); + i.contentWindow.appHistory.navigate("/common/blank.html?1"); + await new Promise(resolve => i.onload = resolve); +}, "AppHistoryCurrentChangeEvent does not fire for cross-document appHistory.navigate()"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-navigate-preventDefault.html b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-navigate-preventDefault.html new file mode 100644 index 0000000..82f1000 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-navigate-preventDefault.html
@@ -0,0 +1,10 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +promise_test(async t => { + appHistory.oncurrentchange = t.unreached_func("currentchange should not fire"); + appHistory.onnavigate = e => e.preventDefault(); + await promise_rejects_dom(t, "AbortError", appHistory.navigate("#foo").committed); +}, "AppHistoryCurrentChangeEvent does not fire when onnavigate preventDefault() is called"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-navigate-replace-cross-doc.html b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-navigate-replace-cross-doc.html new file mode 100644 index 0000000..3d8ceb7 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-navigate-replace-cross-doc.html
@@ -0,0 +1,12 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<iframe id="i" src="/common/blank.html"></iframe> +<script> +promise_test(async t => { + await new Promise(resolve => window.onload = resolve); + i.contentWindow.appHistory.oncurrentchange = t.unreached_func("currentchange should not fire for cross-document navigations"); + i.contentWindow.appHistory.navigate("/common/blank.html?1", { replace: true }); + await new Promise(resolve => i.onload = resolve); +}, "AppHistoryCurrentChangeEvent does not fire for cross-document appHistory.navigate() with replace"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-navigate-replace-same-doc.html b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-navigate-replace-same-doc.html new file mode 100644 index 0000000..2967f21d --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-navigate-replace-same-doc.html
@@ -0,0 +1,23 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +promise_test(async t => { + // Wait for after the load event so that the navigation doesn't get converted + // into a replace navigation. + await new Promise(resolve => window.onload = t.step_timeout(resolve, 0)); + + let oncurrentchange_called = false; + let original_entry = appHistory.current; + appHistory.oncurrentchange = t.step_func(e => { + oncurrentchange_called = true; + assert_equals(e.from, original_entry); + assert_equals(e.from.index, -1); + assert_equals(e.navigationType, "replace"); + assert_equals(appHistory.current.index, 0); + }); + let result = appHistory.navigate("#foo", { replace: true }); + assert_true(oncurrentchange_called); + await result.committed; +}, "AppHistoryCurrentChangeEvent fires for appHistory.navigate() with replace"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-navigate-replace-transitionWhile.html b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-navigate-replace-transitionWhile.html new file mode 100644 index 0000000..86079e7 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-navigate-replace-transitionWhile.html
@@ -0,0 +1,23 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<iframe id="i" src="/common/blank.html"></iframe> +<script> +promise_test(async t => { + await new Promise(resolve => window.onload = resolve); + + let oncurrentchange_called = false; + let original_entry = i.contentWindow.appHistory.current; + i.contentWindow.appHistory.oncurrentchange = t.step_func(e => { + oncurrentchange_called = true; + assert_equals(e.from, original_entry); + assert_equals(e.from.index, -1); + assert_equals(e.navigationType, "replace"); + assert_equals(i.contentWindow.appHistory.current.index, 0); + }); + i.contentWindow.appHistory.onnavigate = e => e.transitionWhile(Promise.resolve()); + let result = i.contentWindow.appHistory.navigate("/common/blank.html?1", { replace: true }); + assert_true(oncurrentchange_called); + await result.committed; +}, "AppHistoryCurrentChangeEvent fires for appHistory.navigate() with replace intercepted by transitionWhile"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-navigate-same-doc.html b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-navigate-same-doc.html new file mode 100644 index 0000000..d112e25 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-navigate-same-doc.html
@@ -0,0 +1,21 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +promise_test(async t => { + // Wait for after the load event so that the navigation doesn't get converted + // into a replace navigation. + await new Promise(resolve => window.onload = t.step_timeout(resolve, 0)); + + let oncurrentchange_called = false; + appHistory.oncurrentchange = t.step_func(e => { + oncurrentchange_called = true; + assert_equals(e.from, appHistory.entries()[0]); + assert_equals(e.navigationType, "push"); + assert_equals(appHistory.current.index, 1); + }); + let result = appHistory.navigate("#foo"); + assert_true(oncurrentchange_called); + await result.committed; +}, "AppHistoryCurrentChangeEvent fires for appHistory.navigate()"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-navigate-transitionWhile.html b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-navigate-transitionWhile.html new file mode 100644 index 0000000..d6a39d2 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-navigate-transitionWhile.html
@@ -0,0 +1,21 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<iframe id="i" src="/common/blank.html"></iframe> +<script> +promise_test(async t => { + await new Promise(resolve => window.onload = resolve); + + let oncurrentchange_called = false; + i.contentWindow.appHistory.oncurrentchange = t.step_func(e => { + oncurrentchange_called = true; + assert_equals(e.from, i.contentWindow.appHistory.entries()[0]); + assert_equals(e.navigationType, "push"); + assert_equals(i.contentWindow.appHistory.current.index, 1); + }); + i.contentWindow.appHistory.onnavigate = e => e.transitionWhile(Promise.resolve()); + let result = i.contentWindow.appHistory.navigate("/common/blank.html?1"); + assert_true(oncurrentchange_called); + await result.committed; +}, "AppHistoryCurrentChangeEvent fires for appHistory.navigate() intercepted by transitionWhile"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-reload-cross-doc.html b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-reload-cross-doc.html new file mode 100644 index 0000000..ae142fb --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-reload-cross-doc.html
@@ -0,0 +1,12 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<iframe id="i" src="/common/blank.html"></iframe> +<script> +promise_test(async t => { + await new Promise(resolve => window.onload = resolve); + i.contentWindow.appHistory.oncurrentchange = t.unreached_func("currentchange should not fire for cross-document navigations"); + i.contentWindow.appHistory.reload(); + await new Promise(resolve => i.onload = resolve); +}, "AppHistoryCurrentChangeEvent does not fire for cross-document appHistory.reload()"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-reload-transitionWhile-expected.txt b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-reload-transitionWhile-expected.txt new file mode 100644 index 0000000..4f115e00 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-reload-transitionWhile-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL AppHistoryCurrentChangeEvent fires for appHistory.reload() intercepted by transitionWhile assert_equals: expected object "[object AppHistoryEntry]" but got object "[object AppHistoryEntry]" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-reload-transitionWhile.html b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-reload-transitionWhile.html new file mode 100644 index 0000000..d1f022f5 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-reload-transitionWhile.html
@@ -0,0 +1,21 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<iframe id="i" src="/common/blank.html"></iframe> +<script> +promise_test(async t => { + await new Promise(resolve => window.onload = resolve); + + let oncurrentchange_called = false; + i.contentWindow.appHistory.oncurrentchange = t.step_func(e => { + oncurrentchange_called = true; + assert_equals(e.from, i.contentWindow.appHistory.current); + assert_equals(e.navigationType, "reload"); + assert_equals(i.contentWindow.appHistory.current.index, 0); + }); + i.contentWindow.appHistory.onnavigate = e => e.transitionWhile(Promise.resolve()); + let result = i.contentWindow.appHistory.reload(); + assert_true(oncurrentchange_called); + await result.committed; +}, "AppHistoryCurrentChangeEvent fires for appHistory.reload() intercepted by transitionWhile"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-updateCurrent.html b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-updateCurrent.html new file mode 100644 index 0000000..9e3a3ec --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-app-history-updateCurrent.html
@@ -0,0 +1,20 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +test(t => { + let oncurrentchange_count = 0; + appHistory.oncurrentchange = t.step_func(e => { + oncurrentchange_count++; + assert_equals(e.from, appHistory.current); + assert_equals(e.navigationType, null); + assert_equals(appHistory.current.getState(), "newState"); + }); + appHistory.updateCurrent({ state: "newState" }); + assert_equals(oncurrentchange_count, 1); + + // "Updating" the state to the current state should still fire currentchange. + appHistory.updateCurrent({ state: appHistory.current.getState() }); + assert_equals(oncurrentchange_count, 2); +}, "AppHistoryCurrentChangeEvent fires for appHistory.updateCurrent()"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-dispose-ordering.html b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-dispose-ordering.html new file mode 100644 index 0000000..f9d23f7 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-dispose-ordering.html
@@ -0,0 +1,26 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +test(t => { + let oncurrentchange_called = false; + let ondispose_called = false; + + let original_entry = appHistory.current; + original_entry.ondispose = t.step_func(() => { + assert_true(oncurrentchange_called); + ondispose_called = true; + }); + + appHistory.oncurrentchange = t.step_func(e => { + oncurrentchange_called = true; + assert_equals(e.from, original_entry); + assert_equals(e.from.index, -1); + assert_equals(e.navigationType, "replace"); + assert_equals(appHistory.current.index, 0); + }); + appHistory.navigate("#foo", { replace: true }); + assert_true(oncurrentchange_called); + assert_true(ondispose_called); +}, "Ordering between AppHistoryCurrentChangeEvent and AppHistoryEntry dispose events"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-history-back-same-doc.html b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-history-back-same-doc.html new file mode 100644 index 0000000..7cfecb1 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-history-back-same-doc.html
@@ -0,0 +1,24 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +promise_test(async t => { + // Wait for after the load event so that the navigation doesn't get converted + // into a replace navigation. + await new Promise(resolve => window.onload = t.step_timeout(resolve, 0)); + await appHistory.navigate("#foo"); + assert_equals(appHistory.entries().length, 2); + + let oncurrentchange_called = false; + appHistory.oncurrentchange = t.step_func(e => { + oncurrentchange_called = true; + assert_equals(e.from, appHistory.entries()[1]); + assert_equals(e.navigationType, "traverse"); + assert_equals(appHistory.current.index, 0); + }); + history.back(); + assert_false(oncurrentchange_called); + await new Promise(resolve => window.onpopstate = resolve); + assert_true(oncurrentchange_called); +}, "AppHistoryCurrentChangeEvent fires for history.back()"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-history-pushState.html b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-history-pushState.html new file mode 100644 index 0000000..e5468ea --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-history-pushState.html
@@ -0,0 +1,16 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +test(t => { + let oncurrentchange_called = false; + appHistory.oncurrentchange = t.step_func(e => { + oncurrentchange_called = true; + assert_equals(e.from, appHistory.entries()[0]); + assert_equals(e.navigationType, "push"); + assert_equals(appHistory.current.index, 1); + }); + history.pushState(1, "", "#1"); + assert_true(oncurrentchange_called); +}, "AppHistoryCurrentChangeEvent fires for history.pushState()"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-history-replaceState.html b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-history-replaceState.html new file mode 100644 index 0000000..5a99561e --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-history-replaceState.html
@@ -0,0 +1,18 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +test(t => { + let oncurrentchange_called = false; + let original_current = appHistory.current; + appHistory.oncurrentchange = t.step_func(e => { + oncurrentchange_called = true; + assert_equals(e.from, original_current); + assert_equals(e.from.index, -1); + assert_equals(e.navigationType, "replace"); + assert_equals(appHistory.current.index, 0); + }); + history.replaceState(1, "", "#1"); + assert_true(oncurrentchange_called); +}, "AppHistoryCurrentChangeEvent fires for history.replaceState()"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-location-api.html b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-location-api.html new file mode 100644 index 0000000..8cf52ca --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-location-api.html
@@ -0,0 +1,18 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +test(t => { + let oncurrentchange_called = false; + let original_entry = appHistory.current; + appHistory.oncurrentchange = t.step_func(e => { + oncurrentchange_called = true; + assert_equals(e.from, original_entry); + assert_equals(e.from.index, -1); + assert_equals(e.navigationType, "replace"); + assert_equals(appHistory.current.index, 0); + }); + location.hash = "#foo"; + assert_true(oncurrentchange_called); +}, "AppHistoryCurrentChangeEvent fires for location API navigations"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-navigate-from-initial-about-blank-same-doc.html b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-navigate-from-initial-about-blank-same-doc.html new file mode 100644 index 0000000..8078261 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-navigate-from-initial-about-blank-same-doc.html
@@ -0,0 +1,11 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<iframe id="i" src="/common/blank.html"></iframe> +<script> +promise_test(async t => { + i.contentWindow.appHistory.oncurrentchange = t.unreached_func("currentchange should not fire"); + history.pushState(1, "", "#1"); + await new Promise(resolve => i.onload = resolve); +}, "AppHistoryCurrentChangeEvent does not fire when navigating away from the initial about:blank"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-navigate-from-initial-about-blank.html b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-navigate-from-initial-about-blank.html new file mode 100644 index 0000000..f97e1e8 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-navigate-from-initial-about-blank.html
@@ -0,0 +1,11 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<iframe id="i" src="/common/blank.html"></iframe> +<script> +promise_test(async t => { + i.contentWindow.appHistory.oncurrentchange = t.unreached_func("currentchange should not fire"); + i.contentWindow.appHistory.navigate("/common/blank.html#1"); + await new Promise(resolve => i.onload = resolve); +}, "AppHistoryCurrentChangeEvent does not fire when navigating away from the initial about:blank"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-properties.html b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-properties.html new file mode 100644 index 0000000..a5417fa3 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/currentchange-properties.html
@@ -0,0 +1,14 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +async_test(t => { + appHistory.oncurrentchange = t.step_func_done(e => { + assert_equals(e.constructor, AppHistoryCurrentChangeEvent); + assert_false(e.bubbles); + assert_false(e.cancelable); + assert_true(e.isTrusted); + }); + location.href = "#1"; +}, "AppHistoryCurrentChangeEvent's properties"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/event-constructor.html b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/event-constructor.html new file mode 100644 index 0000000..6c48936 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/app-history/currentchange-event/event-constructor.html
@@ -0,0 +1,32 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +test(() => { + assert_throws_js(TypeError, () => { + new AppHistoryCurrentChangeEvent("currentchange"); + }); +}, "can't bypass required members by omitting the dictionary entirely"); + +test(() => { + assert_throws_js(TypeError, () => { + new AppHistoryCurrentChangeEvent("currentchange", { + navigationType: "push" + }); + }); +}, "from is required"); + +test(() => { + const event = new AppHistoryCurrentChangeEvent("currentchange", { + navigationType: "replace", + from: appHistory.current + }); + assert_equals(event.navigationType, "replace"); + assert_equals(event.from, appHistory.current); +}, "all properties are reflected back"); + +test(t => { + const event = new AppHistoryCurrentChangeEvent("currentchange", { from: appHistory.current }); + assert_equals(event.navigationType, null); +}, "defaults are as expected"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-cors-fail-manual.sub.html b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-cors-fail-manual.sub.html index a6acdd4..f49dac60 100644 --- a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-cors-fail-manual.sub.html +++ b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-cors-fail-manual.sub.html
@@ -1,7 +1,8 @@ <!DOCTYPE html> <title>Test that icons member is supported (CORS violation)</title> <link rel="help" href="https://w3c.github.io/manifest#icons-member" /> -<link rel="manifest" href="icons-member-cors-fail.sub.webmanifest" /> +<link rel="manifest" href="resources/icons-member-cors-fail.sub.webmanifest" /> +<script src="resources/icons-member-manual.js"></script> <h1>Testing support for icons member (CORS violation)</h1> <script> // Force the port of the origin to be ports[https][0] (likely :8443)
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-cors-fail.sub.webmanifest b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-cors-fail.sub.webmanifest deleted file mode 100644 index e8b9327..0000000 --- a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-cors-fail.sub.webmanifest +++ /dev/null
@@ -1,7 +0,0 @@ -{ - "icons": [{ - "src": "https://{{host}}:{{ports[https][1]}}/appmanifest/icons-member/fail.png", - "sizes": "256x256", - "type": "image/png" - }] -}
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-cors-manual.sub.html b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-cors-manual.sub.html index a54f3629..aa0fe89 100644 --- a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-cors-manual.sub.html +++ b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-cors-manual.sub.html
@@ -1,7 +1,8 @@ <!DOCTYPE html> <title>Test that icons member is supported (via CORS)</title> <link rel="help" href="https://w3c.github.io/manifest#icons-member" /> -<link rel="manifest" href="icons-member-cors.sub.webmanifest" /> +<link rel="manifest" href="resources/icons-member-cors.sub.webmanifest" /> +<script src="resources/icons-member-manual.js"></script> <h1>Testing support for icons member (via CORS)</h1> <script> // Force the port of the origin to be ports[https][0] (likely :8443)
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-cors.sub.webmanifest b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-cors.sub.webmanifest deleted file mode 100644 index 5d95262..0000000 --- a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-cors.sub.webmanifest +++ /dev/null
@@ -1,7 +0,0 @@ -{ - "icons": [{ - "src": "https://{{host}}:{{ports[https][1]}}/appmanifest/icons-member/pass.png", - "sizes": "256x256", - "type": "image/png" - }] -}
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-csp-fail-manual.sub.html b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-csp-fail-manual.sub.html index 7f35fc31..e4706011 100644 --- a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-csp-fail-manual.sub.html +++ b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-csp-fail-manual.sub.html
@@ -2,7 +2,8 @@ <meta http-equiv="Content-Security-Policy" content="img-src {{host}}:{{ports[https][1]}}"> <title>Test that icons member is supported (CSP violation)</title> <link rel="help" href="https://w3c.github.io/manifest#icons-member" /> -<link rel="manifest" href="icons-member-csp-fail.webmanifest" /> +<link rel="manifest" href="resources/icons-member-csp-fail.webmanifest" /> +<script src="resources/icons-member-manual.js"></script> <h1>Testing support for icons member (CSP violation)</h1> <script> // Force the port of the origin to be ports[https][0] (likely :8443)
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-csp-fail.webmanifest b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-csp-fail.webmanifest deleted file mode 100644 index a1736487..0000000 --- a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-csp-fail.webmanifest +++ /dev/null
@@ -1,7 +0,0 @@ -{ - "icons": [{ - "src": "fail.png", - "sizes": "256x256", - "type": "image/png" - }] -}
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-csp-manual.sub.html b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-csp-manual.sub.html index 15e0912..c76364b 100644 --- a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-csp-manual.sub.html +++ b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-csp-manual.sub.html
@@ -2,7 +2,8 @@ <meta http-equiv="Content-Security-Policy" content="img-src {{host}}:{{ports[https][1]}}"> <title>Test that icons member is supported (CSP check)</title> <link rel="help" href="https://w3c.github.io/manifest#icons-member" /> -<link rel="manifest" href="icons-member-csp.sub.webmanifest" /> +<link rel="manifest" href="resources/icons-member-csp.sub.webmanifest" /> +<script src="resources/icons-member-manual.js"></script> <h1>Testing support for icons member (CSP check)</h1> <script> // Force the port of the origin to be ports[https][0] (likely :8443)
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-csp.sub.webmanifest b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-csp.sub.webmanifest deleted file mode 100644 index 5d95262..0000000 --- a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-csp.sub.webmanifest +++ /dev/null
@@ -1,7 +0,0 @@ -{ - "icons": [{ - "src": "https://{{host}}:{{ports[https][1]}}/appmanifest/icons-member/pass.png", - "sizes": "256x256", - "type": "image/png" - }] -}
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-last-matching-manual.html b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-last-matching-manual.html index 04f18f4..a02ddc3a 100644 --- a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-last-matching-manual.html +++ b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-last-matching-manual.html
@@ -1,7 +1,8 @@ <!DOCTYPE html> <title>Test that icons member is supported</title> <link rel="help" href="https://w3c.github.io/manifest#icons-member" /> -<link rel="manifest" href="icons-member-last-matching.webmanifest" /> +<link rel="manifest" href="resources/icons-member-last-matching.webmanifest" /> +<script src="resources/icons-member-manual.js"></script> <h1>Testing support for icons member</h1> <p> To pass, the icon must show a white check mark on a green background.
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-manual.html b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-manual.html index f42db8d..6a9b762 100644 --- a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-manual.html +++ b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-manual.html
@@ -1,7 +1,8 @@ <!DOCTYPE html> <title>Test that icons member is supported</title> <link rel="help" href="https://w3c.github.io/manifest#icons-member" /> -<link rel="manifest" href="icons-member.webmanifest" /> +<link rel="manifest" href="resources/icons-member.webmanifest" /> +<script src="resources/icons-member-manual.js"></script> <h1>Testing support for icons member</h1> <p> To pass, the icon should must a white check mark on a green background.
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-next-appropriate-manual.html b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-next-appropriate-manual.html index 1e84ba9..8e87fc1 100644 --- a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-next-appropriate-manual.html +++ b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-next-appropriate-manual.html
@@ -1,7 +1,8 @@ <!DOCTYPE html> <title>Test that icons member is supported</title> <link rel="help" href="https://w3c.github.io/manifest#icons-member" /> -<link rel="manifest" href="icons-member-next-appropriate.webmanifest" /> +<link rel="manifest" href="resources/icons-member-next-appropriate.webmanifest" /> +<script src="resources/icons-member-manual.js"></script> <h1>Testing support for icons member</h1> <p> To pass, the icon must show a white check mark on a green background.
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-next-appropriate.webmanifest b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-next-appropriate.webmanifest deleted file mode 100644 index 5ae381e..0000000 --- a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-next-appropriate.webmanifest +++ /dev/null
@@ -1,10 +0,0 @@ -{ - "icons": [{ - "src": "pass.png", - "sizes": "256x256", - "type": "image/png" - }, { - "src": "icons-member-manual.html", - "sizes": "256x256" - }] -}
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-service-worker.js b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-service-worker.js new file mode 100644 index 0000000..21b07f8 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-service-worker.js
@@ -0,0 +1,59 @@ +// Some user agents only offer app installation if there is a SW and it handles +// offline requests. + +const cacheVersion = "1.2"; +const CACHE_NAME = `cache-v${cacheVersion}`; + +// The resources cached by this service worker. +const resources = [ + "icons-member-cors-fail-manual.sub.html", + "icons-member-cors-manual.sub.html", + "icons-member-csp-fail-manual.sub.html", + "icons-member-csp-manual.sub.html", + "icons-member-last-matching-manual.html", + "icons-member-manual.html", + "icons-member-next-appropriate-manual.html", + "icons-member-service-worker.js", + "resources/icons-member-manual.js", + "resources/fail.png", + "resources/pass.png" +]; + +// Load all resources for this service worker. +const precache = async () => { + const cache = await caches.open(CACHE_NAME); + await cache.addAll(resources); +}; + +// Get a resource from the cache. +const fromCache = async request => { + const cache = await caches.open(CACHE_NAME); + return await cache.match(request.url); +}; + +// Attempt to get resources from the network first, fallback to the cache if we're +// offline. +const networkFallbackToCache = async request => { + try { + const response = await fetch(request); + if (response.ok) return response; + } catch (err) {} + return await fromCache(request); +}; + +// When we have a new service worker, update the caches and swap immediately. +self.addEventListener("install", e => { + e.waitUntil(precache().then(() => self.skipWaiting())); +}); + +// Claim existing clients. +self.addEventListener("activate", e => { + e.waitUntil(self.clients.claim()); +}); + +// When a resource need to be fetched, check whether it is +// contained in the cache and return the cached version, otherwise +// get it from the network. +self.addEventListener("fetch", e => { + e.respondWith(networkFallbackToCache(e.request)); +});
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member.webmanifest b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member.webmanifest deleted file mode 100644 index a744fee..0000000 --- a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member.webmanifest +++ /dev/null
@@ -1,7 +0,0 @@ -{ - "icons": [{ - "src": "pass.png", - "sizes": "256x256", - "type": "image/png" - }] -}
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/fail.png b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/fail.png similarity index 100% rename from third_party/blink/web_tests/external/wpt/appmanifest/icons-member/fail.png rename to third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/fail.png Binary files differ
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/icons-member-cors-fail.sub.webmanifest b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/icons-member-cors-fail.sub.webmanifest new file mode 100644 index 0000000..24e2214 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/icons-member-cors-fail.sub.webmanifest
@@ -0,0 +1,10 @@ +{ + "name": "Icons member (CORS violation) WPT", + "icons": [{ + "src": "https://{{host}}:{{ports[https][1]}}/appmanifest/icons-member/resources/fail.png", + "sizes": "256x256", + "type": "image/png" + }], + "start_url": "../icons-member-cors-fail-manual.sub.html", + "display": "fullscreen" +}
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-cors-fail.webmanifest.headers b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/icons-member-cors-fail.webmanifest.headers similarity index 100% rename from third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-cors-fail.webmanifest.headers rename to third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/icons-member-cors-fail.webmanifest.headers
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/icons-member-cors.sub.webmanifest b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/icons-member-cors.sub.webmanifest new file mode 100644 index 0000000..33cb126 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/icons-member-cors.sub.webmanifest
@@ -0,0 +1,10 @@ +{ + "name": "Icons member (via CORS) WPT", + "icons": [{ + "src": "https://{{host}}:{{ports[https][1]}}/appmanifest/icons-member/resources/pass.png", + "sizes": "256x256", + "type": "image/png" + }], + "start_url": "../icons-member-cors-manual.sub.html", + "display": "fullscreen" +}
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-cors.webmanifest.headers b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/icons-member-cors.webmanifest.headers similarity index 100% rename from third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-cors.webmanifest.headers rename to third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/icons-member-cors.webmanifest.headers
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/icons-member-csp-fail.webmanifest b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/icons-member-csp-fail.webmanifest new file mode 100644 index 0000000..2b614eb --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/icons-member-csp-fail.webmanifest
@@ -0,0 +1,10 @@ +{ + "name": "Icons member (CSP violation) WPT", + "icons": [{ + "src": "fail.png", + "sizes": "256x256", + "type": "image/png" + }], + "start_url": "../icons-member-csp-fail-manual.sub.html", + "display": "fullscreen" +}
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-csp-fail.webmanifest.headers b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/icons-member-csp-fail.webmanifest.headers similarity index 100% rename from third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-csp-fail.webmanifest.headers rename to third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/icons-member-csp-fail.webmanifest.headers
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/icons-member-csp.sub.webmanifest b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/icons-member-csp.sub.webmanifest new file mode 100644 index 0000000..f1089bba --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/icons-member-csp.sub.webmanifest
@@ -0,0 +1,10 @@ +{ + "name": "Icons member (CSP check) WPT", + "icons": [{ + "src": "https://{{host}}:{{ports[https][1]}}/appmanifest/icons-member/resources/pass.png", + "sizes": "256x256", + "type": "image/png" + }], + "start_url": "../icons-member-csp-manual.sub.html", + "display": "fullscreen" +}
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-csp.webmanifest.headers b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/icons-member-csp.webmanifest.headers similarity index 100% rename from third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-csp.webmanifest.headers rename to third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/icons-member-csp.webmanifest.headers
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-last-matching.webmanifest b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/icons-member-last-matching.webmanifest similarity index 60% rename from third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-last-matching.webmanifest rename to third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/icons-member-last-matching.webmanifest index f4423d2..04ac331 100644 --- a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-last-matching.webmanifest +++ b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/icons-member-last-matching.webmanifest
@@ -1,4 +1,5 @@ { + "name": "Icons member WPT", "icons": [{ "src": "fail.png", "sizes": "256x256", @@ -7,5 +8,7 @@ "src": "pass.png", "sizes": "256x256", "type": "image/png" - }] + }], + "start_url": "../icons-member-last-matching-manual.html", + "display": "fullscreen" }
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-last-matching.webmanifest.headers b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/icons-member-last-matching.webmanifest.headers similarity index 100% rename from third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-last-matching.webmanifest.headers rename to third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/icons-member-last-matching.webmanifest.headers
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/icons-member-manual.js b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/icons-member-manual.js new file mode 100644 index 0000000..cf149792 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/icons-member-manual.js
@@ -0,0 +1,4 @@ +if ('serviceWorker' in navigator) { + navigator.serviceWorker.register( + 'icons-member-service-worker.js'); +}
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/icons-member-next-appropriate.webmanifest b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/icons-member-next-appropriate.webmanifest new file mode 100644 index 0000000..e65169b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/icons-member-next-appropriate.webmanifest
@@ -0,0 +1,13 @@ +{ + "name": "Icons member WPT", + "icons": [{ + "src": "pass.png", + "sizes": "256x256", + "type": "image/png" + }, { + "src": "../icons-member-manual.html", + "sizes": "256x256" + }], + "start_url": "../icons-member-next-appropriate-manual.html", + "display": "fullscreen" +}
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-next-appropriate.webmanifest.headers b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/icons-member-next-appropriate.webmanifest.headers similarity index 100% rename from third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member-next-appropriate.webmanifest.headers rename to third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/icons-member-next-appropriate.webmanifest.headers
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/icons-member.webmanifest b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/icons-member.webmanifest new file mode 100644 index 0000000..8e7a2c3 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/icons-member.webmanifest
@@ -0,0 +1,10 @@ +{ + "name": "Icons member WPT", + "icons": [{ + "src": "pass.png", + "sizes": "256x256", + "type": "image/png" + }], + "start_url": "../icons-member-manual.html", + "display": "fullscreen" +}
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member.webmanifest.headers b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/icons-member.webmanifest.headers similarity index 100% rename from third_party/blink/web_tests/external/wpt/appmanifest/icons-member/icons-member.webmanifest.headers rename to third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/icons-member.webmanifest.headers
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/pass.png b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/pass.png similarity index 100% rename from third_party/blink/web_tests/external/wpt/appmanifest/icons-member/pass.png rename to third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/pass.png Binary files differ
diff --git a/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/pass.png.sub.headers b/third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/pass.png.sub.headers similarity index 100% rename from third_party/blink/web_tests/external/wpt/appmanifest/icons-member/pass.png.sub.headers rename to third_party/blink/web_tests/external/wpt/appmanifest/icons-member/resources/pass.png.sub.headers
diff --git a/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-palette-values-valid-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-palette-values-valid-expected.txt index d8f9ffb..252eb64 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-palette-values-valid-expected.txt +++ b/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-palette-values-valid-expected.txt
@@ -19,5 +19,17 @@ FAIL CSS Fonts Module Level 4: parsing @font-palette-values 17 Cannot read properties of undefined (reading 'fontFamily') FAIL CSS Fonts Module Level 4: parsing @font-palette-values 18 Cannot read properties of undefined (reading 'cssText') FAIL CSS Fonts Module Level 4: parsing @font-palette-values 19 Cannot read properties of undefined (reading 'fontFamily') +FAIL CSS Fonts Module Level 4: parsing @font-palette-values 20 Cannot read properties of undefined (reading 'cssText') +FAIL CSS Fonts Module Level 4: parsing @font-palette-values 21 Cannot read properties of undefined (reading 'fontFamily') +FAIL CSS Fonts Module Level 4: parsing @font-palette-values 22 Cannot read properties of undefined (reading 'cssText') +FAIL CSS Fonts Module Level 4: parsing @font-palette-values 23 Cannot read properties of undefined (reading 'fontFamily') +FAIL CSS Fonts Module Level 4: parsing @font-palette-values 24 Cannot read properties of undefined (reading 'cssText') +FAIL CSS Fonts Module Level 4: parsing @font-palette-values 25 Cannot read properties of undefined (reading 'fontFamily') +FAIL CSS Fonts Module Level 4: parsing @font-palette-values 26 Cannot read properties of undefined (reading 'cssText') +FAIL CSS Fonts Module Level 4: parsing @font-palette-values 27 Cannot read properties of undefined (reading 'fontFamily') +FAIL CSS Fonts Module Level 4: parsing @font-palette-values 28 Cannot read properties of undefined (reading 'cssText') +FAIL CSS Fonts Module Level 4: parsing @font-palette-values 29 Cannot read properties of undefined (reading 'fontFamily') +FAIL CSS Fonts Module Level 4: parsing @font-palette-values 30 Cannot read properties of undefined (reading 'cssText') +FAIL CSS Fonts Module Level 4: parsing @font-palette-values 31 Cannot read properties of undefined (reading 'fontFamily') Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-palette-values-valid.html b/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-palette-values-valid.html index c6774ef..665841c 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-palette-values-valid.html +++ b/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-palette-values-valid.html
@@ -69,6 +69,36 @@ @font-palette-values J { override-color: -3 rgb(17, 34, 51); } + +/* 10 */ +@font-palette-values K { + override-color: 0 #0000FF; +} + +/* 11 */ +@font-palette-values L { + override-color: 0 green; +} + +/* 12 */ +@font-palette-values M { + override-color: 0 transparent; +} + +/* 13 */ +@font-palette-values N { + override-color: 0 rgba(1 2 3 / 4); +} + +/* 14 */ +@font-palette-values O { + override-color: 0 lab(29.2345% 39.3825 20.0664); +} + +/* 15 */ +@font-palette-values P { + override-color: 0 color(display-p3 100% 100% 100%); +} </style> </head> <body> @@ -228,6 +258,90 @@ assert_equals(rule.get(7), undefined); assert_equals(rule.get(-3), undefined); }); + +test(function() { + let text = rules[10].cssText; + assert_not_equals(text.indexOf("override-color"), -1); + assert_not_equals(text.indexOf("rgb(0, 0, 255)"), -1); +}); + +test(function() { + let rule = rules[10]; + assert_equals(rule.fontFamily, ""); + assert_equals(rule.basePalette, ""); + assert_equals(rule.size, 1); + assert_equals(rule.get(0), "rgb(0, 0, 255)"); +}); + +test(function() { + let text = rules[11].cssText; + assert_not_equals(text.indexOf("override-color"), -1); + assert_not_equals(text.indexOf("rgb(0, 128, 0)"), -1); +}); + +test(function() { + let rule = rules[11]; + assert_equals(rule.fontFamily, ""); + assert_equals(rule.basePalette, ""); + assert_equals(rule.size, 1); + assert_equals(rule.get(0), "rgb(0, 128, 0)"); +}); + +test(function() { + let text = rules[12].cssText; + assert_not_equals(text.indexOf("override-color"), -1); + assert_not_equals(text.indexOf("rgba(0, 0, 0, 0)"), -1); +}); + +test(function() { + let rule = rules[12]; + assert_equals(rule.fontFamily, ""); + assert_equals(rule.basePalette, ""); + assert_equals(rule.size, 1); + assert_equals(rule.get(0), "rgba(0, 0, 0, 0)"); +}); + +test(function() { + let text = rules[13].cssText; + assert_not_equals(text.indexOf("override-color"), -1); + assert_not_equals(text.indexOf("2"), -1); +}); + +test(function() { + let rule = rules[13]; + assert_equals(rule.fontFamily, ""); + assert_equals(rule.basePalette, ""); + assert_equals(rule.size, 1); + assert_not_equals(rule.get(0).indexOf("2"), -1); +}); + +test(function() { + let text = rules[14].cssText; + assert_not_equals(text.indexOf("override-color"), -1); + assert_not_equals(text.indexOf("29"), -1); +}); + +test(function() { + let rule = rules[14]; + assert_equals(rule.fontFamily, ""); + assert_equals(rule.basePalette, ""); + assert_equals(rule.size, 1); + assert_not_equals(rule.get(0).indexOf("lab"), -1); +}); + +test(function() { + let text = rules[15].cssText; + assert_not_equals(text.indexOf("override-color"), -1); + assert_not_equals(text.indexOf("display-p3"), -1); +}); + +test(function() { + let rule = rules[15]; + assert_equals(rule.fontFamily, ""); + assert_equals(rule.basePalette, ""); + assert_equals(rule.size, 1); + assert_not_equals(rule.get(0).indexOf("display-p3"), -1); +}); </script> </body> </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/round-mod-rem-computed.html b/third_party/blink/web_tests/external/wpt/css/css-values/round-mod-rem-computed.html new file mode 100644 index 0000000..a98e4a4 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-values/round-mod-rem-computed.html
@@ -0,0 +1,111 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.csswg.org/css-values-4/#comp-func"> +<link rel="help" href="https://drafts.csswg.org/css-values-4/#numbers"> +<link rel="help" href="https://drafts.csswg.org/css-values-4/#calc-type-checking"> +<link rel="author" title="Apple Inc"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/numeric-testcommon.js"></script> +<div id="target"></div> +<script> +// Simple tests +test_math_used('round(10,10)', '10', {type:'number'}); +test_math_used('mod(1,1)', '0', {type:'number'}); +test_math_used('rem(1,1)', '0', {type:'number'}); + +//Test basic round +test_math_used('calc(round(100,10))', '100', {type:'number'}); +test_math_used('calc(round(up, 101,10))', '110', {type:'number'}); +test_math_used('calc(round(down, 106,10))', '100', {type:'number'}); +test_math_used('calc(round(to-zero,105, 10))', '100', {type:'number'}); +test_math_used('calc(round(to-zero,-105, 10))', '100', {type:'number'}); +test_math_used('calc(round(-100,10))', '-100', {type:'number'}); +test_math_used('calc(round(up, -103,10))', '-100', {type:'number'}); + +//Test basic mod/rem +test_math_used('mod(18,5)', '3', {type:'number'}); +test_math_used('rem(18,5)', '3', {type:'number'}); +test_math_used('mod(-140,-90)', '-50', {type:'number'}); +test_math_used('mod(-18,5)', '2', {type:'number'}); +test_math_used('rem(-18,5)', '-3', {type:'number'}); +test_math_used('mod(140,-90)', '-40', {type:'number'}); +test_math_used('rem(140,-90)', '50', {type:'number'}); + +//Test basic calculations +test_math_used('calc(round(round(100,10), 10))', '100', {type:'number'}); +test_math_used('calc(round(up, round(100,10) + 1,10))', '110', {type:'number'}); +test_math_used('calc(round(down, round(100,10) + 2 * 3,10))', '100', {type:'number'}); +test_math_used('calc(round(to-zero,round(100,10) * 2 - 95, 10))', '100', {type:'number'}); +test_math_used('calc(round(round(100,10)* -1,10))', '-100', {type:'number'}); +test_math_used('calc(round(up, -103 + -103 / -103 - 1,10))', '-100', {type:'number'}); +test_math_used('calc(mod(18,5) * 2 + mod(17,5))', '8', {type:'number'}); +test_math_used('calc(rem(mod(18,5),5))', '3', {type:'number'}); +test_math_used('calc(rem(mod(18,5),mod(17,5)))', '1', {type:'number'}); +test_math_used('calc(mod(-140,-90))', '-50', {type:'number'}); +test_math_used('calc(mod(rem(1,18)* -1,5))', '-1', {type:'number'}); + +// Type check +test_math_used('round(10px,6px)', '12px'); +test_math_used('round(10cm,6cm)', '12cm'); +test_math_used('round(10mm,6mm)', '12mm'); +test_math_used('round(10Q, 6Q)', '12Q'); +test_math_used('round(10in,6in)', '12in'); +test_math_used('round(10pc,6pc)', '12pc'); +test_math_used('round(10pt,6pt)', '12pt'); +test_math_used('round(10em,6em)', '12em'); +test_math_used('round(10ex,6ex)', '12ex'); +test_math_used('round(10ch,6ch)', '12ch'); +test_math_used('round(10rem,6rem)', '12rem'); +test_math_used('round(10vh,6vh)', '12vh'); +test_math_used('round(10vw,6vw)', '12vw'); +test_math_used('round(10vmin,6vmin)', '12vmin'); +test_math_used('round(10vmax,6vmax)', '12vmax'); +test_math_used('round(10s,6s)', '12s'); +test_math_used('round(10ms,6ms)', '12ms'); +test_math_used('round(10deg,6deg)', '12deg', {type:'angle', approx:0.1}); +test_math_used('round(10grad,6grad)', '12grad', {type:'angle', approx:0.1}); +test_math_used('round(10rad,6rad)', '12rad',{type:'angle', approx:0.1}); +test_math_used('round(10turn,6turn)', '12turn',{type:'angle', approx:0.1}); + +test_math_used('mod(10px,6px)', '4px'); +test_math_used('mod(10cm,6cm)', '4cm'); +test_math_used('mod(10mm,6mm)', '4mm'); +test_math_used('mod(10Q, 6Q)', '4Q'); +test_math_used('mod(10in,6in)', '4in'); +test_math_used('mod(10pc,6pc)', '4pc'); +test_math_used('mod(10em,6em)', '4em'); +test_math_used('mod(10ex,6ex)', '4ex'); +test_math_used('mod(10ch,6ch)', '4ch'); +test_math_used('mod(10rem,6rem)', '4rem'); +test_math_used('mod(10vh,6vh)', '4vh'); +test_math_used('mod(10vw,6vw)', '4vw'); +test_math_used('mod(10vmin,6vmin)', '4vmin'); +test_math_used('mod(10vmax,6vmax)', '4vmax'); +test_math_used('mod(10s,6s)', '4s'); +test_math_used('mod(10ms,6ms)', '4ms'); +test_math_used('mod(10deg,6deg)', '4deg', {type:'angle', approx:0.1}); +test_math_used('mod(10grad,6grad)', '4grad', {type:'angle', approx:0.1}); +test_math_used('mod(10rad,6rad)', '4rad',{type:'angle', approx:0.1}); +test_math_used('mod(10turn,6turn)', '4turn',{type:'angle', approx:0.1}); + +test_math_used('rem(10px,6px)', '4px'); +test_math_used('rem(10cm,6cm)', '4cm'); +test_math_used('rem(10mm,6mm)', '4mm'); +test_math_used('rem(10Q, 6Q)', '4Q'); +test_math_used('rem(10in,6in)', '4in'); +test_math_used('rem(10pc,6pc)', '4pc'); +test_math_used('rem(10em,6em)', '4em'); +test_math_used('rem(10ex,6ex)', '4ex'); +test_math_used('rem(10ch,6ch)', '4ch'); +test_math_used('rem(10rem,6rem)', '4rem'); +test_math_used('rem(10vh,6vh)', '4vh'); +test_math_used('rem(10vw,6vw)', '4vw'); +test_math_used('rem(10vmin,6vmin)', '4vmin'); +test_math_used('rem(10vmax,6vmax)', '4vmax'); +test_math_used('rem(10s,6s)', '4s'); +test_math_used('rem(10ms,6ms)', '4ms'); +test_math_used('rem(10deg,6deg)', '4deg', {type:'angle', approx:0.1}); +test_math_used('rem(10grad,6grad)', '4grad', {type:'angle', approx:0.1}); +test_math_used('rem(10rad,6rad)', '4rad',{type:'angle', approx:0.1}); +test_math_used('rem(10turn,6turn)', '4turn',{type:'angle', approx:0.1}); +</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/round-mod-rem-invalid.html b/third_party/blink/web_tests/external/wpt/css/css-values/round-mod-rem-invalid.html new file mode 100644 index 0000000..99ef2c64 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-values/round-mod-rem-invalid.html
@@ -0,0 +1,94 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.csswg.org/css-values-4/#comp-func"> +<link rel="help" href="https://drafts.csswg.org/css-values-4/#numbers"> +<link rel="help" href="https://drafts.csswg.org/css-values-4/#calc-type-checking"> +<link rel="author" title="Apple Inc"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/parsing-testcommon.js"></script> +<script> +function test_invalid_number(value) { + test_invalid_value('opacity', value); +} + +// Syntax checking +test_invalid_number('round()'); +test_invalid_number('round( )'); +test_invalid_number('round(,)'); +test_invalid_number('round(1, )'); +test_invalid_number('round(, 1)'); +test_invalid_number('round(1 + )'); +test_invalid_number('round(1 - )'); +test_invalid_number('round(1 * )'); +test_invalid_number('round(1 / )'); +test_invalid_number('round(1 2)'); +test_invalid_number('round(nearest, 1 2)'); +test_invalid_number('round(1, nearest, 12)'); +test_invalid_number('round(1, nearest)'); +test_invalid_number('round(nearest, 1, nearest)'); +test_invalid_number('round(nearest, 1)'); +test_invalid_number('round(1, , 2)'); +test_invalid_number('mod()'); +test_invalid_number('mod( )'); +test_invalid_number('mod(,)'); +test_invalid_number('mod(1, )'); +test_invalid_number('mod(, 1)'); +test_invalid_number('mod(1 + )'); +test_invalid_number('mod(1 - )'); +test_invalid_number('mod(1 * )'); +test_invalid_number('mod(1 / )'); +test_invalid_number('mod(1 2)'); +test_invalid_number('mod(1, , 2)'); +test_invalid_number('rem()'); +test_invalid_number('rem( )'); +test_invalid_number('rem(,)'); +test_invalid_number('rem(1, )'); +test_invalid_number('rem(, 1)'); +test_invalid_number('rem(1 + )'); +test_invalid_number('rem(1 - )'); +test_invalid_number('rem(1 * )'); +test_invalid_number('rem(1 / )'); +test_invalid_number('rem(1 2)'); +test_invalid_number('rem(1, , 2)'); + +// Type checking +test_invalid_number('round(0px)'); +test_invalid_number('round(0s)'); +test_invalid_number('round(0deg)'); +test_invalid_number('round(0Hz)'); +test_invalid_number('round(0dpi)'); +test_invalid_number('round(0fr)'); +test_invalid_number('round(1, 1%)'); +test_invalid_number('round(1, 0px)'); +test_invalid_number('round(1, 0s)'); +test_invalid_number('round(1, 0deg)'); +test_invalid_number('round(1, 0Hz)'); +test_invalid_number('round(1, 0dpi)'); +test_invalid_number('round(1, 0fr)'); +test_invalid_number('mod(0px)'); +test_invalid_number('mod(0s)'); +test_invalid_number('mod(0deg)'); +test_invalid_number('mod(0Hz)'); +test_invalid_number('mod(0dpi)'); +test_invalid_number('mod(0fr)'); +test_invalid_number('mod(1, 1%)'); +test_invalid_number('mod(1, 0px)'); +test_invalid_number('mod(1, 0s)'); +test_invalid_number('mod(1, 0deg)'); +test_invalid_number('mod(1, 0Hz)'); +test_invalid_number('mod(1, 0dpi)'); +test_invalid_number('mod(1, 0fr)'); +test_invalid_number('rem(0px)'); +test_invalid_number('rem(0s)'); +test_invalid_number('rem(0deg)'); +test_invalid_number('rem(0Hz)'); +test_invalid_number('rem(0dpi)'); +test_invalid_number('rem(0fr)'); +test_invalid_number('rem(1, 1%)'); +test_invalid_number('rem(1, 0px)'); +test_invalid_number('rem(1, 0s)'); +test_invalid_number('rem(1, 0deg)'); +test_invalid_number('rem(1, 0Hz)'); +test_invalid_number('rem(1, 0dpi)'); +test_invalid_number('rem(1, 0fr)'); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/round-mod-rem-serialize-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-values/round-mod-rem-serialize-expected.txt new file mode 100644 index 0000000..162be5e2 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-values/round-mod-rem-serialize-expected.txt
@@ -0,0 +1,15 @@ +This is a testharness.js-based test. +FAIL 'round(1.1,1)' as a specified value should serialize as 'calc(1)'. assert_not_equals: 'round(1.1,1)' should be valid in opacity. got disallowed value "" +FAIL 'scale(round(1.1,1))' as a specified value should serialize as 'scale(calc(1))'. assert_not_equals: 'scale(round(1.1,1))' should be valid in transform. got disallowed value "" +PASS 'round(1.1,1)' as a computed value should serialize as '1'. +FAIL 'scale(round(1.1,1))' as a computed value should serialize as 'matrix(1, 0, 0, 1, 0, 0)'. assert_equals: 'scale(round(1.1,1))' and 'matrix(1, 0, 0, 1, 0, 0)' should serialize the same in computed values. expected "matrix(1, 0, 0, 1, 0, 0)" but got "none" +FAIL 'mod(1,1)' as a specified value should serialize as 'calc(0)'. assert_not_equals: 'mod(1,1)' should be valid in opacity. got disallowed value "" +FAIL 'scale(mod(1,1))' as a specified value should serialize as 'scale(calc(0))'. assert_not_equals: 'scale(mod(1,1))' should be valid in transform. got disallowed value "" +FAIL 'mod(1,1)' as a computed value should serialize as '0'. assert_equals: 'mod(1,1)' and '0' should serialize the same in computed values. expected "0" but got "1" +FAIL 'scale(mod(1,1))' as a computed value should serialize as 'matrix(0, 0, 0, 0, 0, 0)'. assert_equals: 'scale(mod(1,1))' and 'matrix(0, 0, 0, 0, 0, 0)' should serialize the same in computed values. expected "matrix(0, 0, 0, 0, 0, 0)" but got "none" +FAIL 'rem(1,1)' as a specified value should serialize as 'calc(0)'. assert_not_equals: 'rem(1,1)' should be valid in opacity. got disallowed value "" +FAIL 'scale(rem(1,1))' as a specified value should serialize as 'scale(calc(0))'. assert_not_equals: 'scale(rem(1,1))' should be valid in transform. got disallowed value "" +FAIL 'rem(1,1)' as a computed value should serialize as '0'. assert_equals: 'rem(1,1)' and '0' should serialize the same in computed values. expected "0" but got "1" +FAIL 'scale(rem(1,1))' as a computed value should serialize as 'matrix(0, 0, 0, 0, 0, 0)'. assert_equals: 'scale(rem(1,1))' and 'matrix(0, 0, 0, 0, 0, 0)' should serialize the same in computed values. expected "matrix(0, 0, 0, 0, 0, 0)" but got "none" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/round-mod-rem-serialize.html b/third_party/blink/web_tests/external/wpt/css/css-values/round-mod-rem-serialize.html new file mode 100644 index 0000000..4902495 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-values/round-mod-rem-serialize.html
@@ -0,0 +1,31 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.csswg.org/css-values-4/#comp-func"> +<link rel="help" href="https://drafts.csswg.org/css-values-4/#numbers"> +<link rel="help" href="https://drafts.csswg.org/css-values-4/#calc-serialize"> +<link rel="author" title="Xiaocheng Hu" href="mailto:xiaochengh@chromium.org"> +<link rel="author" title="Apple Inc"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/serialize-testcommon.js"></script> +<div id=target></div> +<script> +function test_serialization(t,s,c) { + test_specified_serialization('opacity', t, s); + test_specified_serialization('transform', `scale(${t})`, `scale(calc(${c}))`); + test_computed_serialization('opacity', t, c); + test_computed_serialization('transform', `scale(${t})`, `matrix(${c}, 0, 0, ${c}, 0, 0)`); +} + +test_serialization( + 'round(1.1,1)', + 'calc(1)', + '1'); +test_serialization( + 'mod(1,1)', + 'calc(0)', + '0'); +test_serialization( + 'rem(1,1)', + 'calc(0)', + '0'); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/signs-abs-computed.html b/third_party/blink/web_tests/external/wpt/css/css-values/signs-abs-computed.html new file mode 100644 index 0000000..ba672f2 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-values/signs-abs-computed.html
@@ -0,0 +1,164 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.csswg.org/css-values-4/#comp-func"> +<link rel="help" href="https://drafts.csswg.org/css-values-4/#numbers"> +<link rel="help" href="https://drafts.csswg.org/css-values-4/#calc-type-checking"> +<link rel="author" title="Apple Inc"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/numeric-testcommon.js"></script> +<div id="target"></div> +<script> +// Identity tests +test_math_used('abs(1)', '1', {type:'number'}); +test_math_used('sign(1)', '1', {type:'number'}); +test_math_used('abs(-1)', '1', {type:'number'}); +test_math_used('sign(-1)', '-1', {type:'number'}); + +// Nestings +test_math_used('abs(sign(1))', '1'); +test_math_used('abs(sign(sign(1)))', '1'); +test_math_used('sign(sign(sign(1) + sign(1)))', '1'); + +// General calculations +test_math_used('calc(abs(0.1 + 0.2) + 0.05)', '0.35', {type:'number', approx:0.1}); +test_math_used('calc(sign(0.1 + 0.2) - 0.05)', '0.95', {type:'number', approx:0.1}); +test_math_used('calc(abs(0.1 + 0.2) * 2)', '0.6', {type:'number', approx:0.1}); +test_math_used('calc(abs(sign(0.1) + 0.2) / 2)', '0.6', {type:'number', approx:0.1}); +test_math_used('calc(abs(0.1 + 0.2) * -2)', '-0.6', {type:'number', approx:0.1}); +test_math_used('calc(sign(0.1 - 0.2) - 0.05)', '-1.05', {type:'number', approx:0.1}); +test_math_used('calc(sign(1) + sign(1) - 0.05)', '1.95', {type:'number', approx:0.1}); + +// Test sign for zero +test_math_used('calc(sign(-0))', '-0', {type:'number'}); +test_math_used('calc(sign(0))', '0', {type:'number'}); + +//Type checking sign +test_math_used('sign(1px)', '1'); +test_math_used('sign(1cm)', '1'); +test_math_used('sign(1mm)', '1'); +test_math_used('sign(1Q)', '1'); +test_math_used('sign(1in)', '1'); +test_math_used('sign(1pc)', '1'); +test_math_used('sign(1pt)', '1'); +test_math_used('sign(1em)', '1'); +test_math_used('sign(1ex)', '1'); +test_math_used('sign(1ch)', '1'); +test_math_used('sign(1rem)', '1'); +test_math_used('sign(1vh)', '1'); +test_math_used('sign(1vw)', '1'); +test_math_used('sign(1vmin)', '1'); +test_math_used('sign(1vmax)', '1'); +test_math_used('sign(-1px)', '-1'); +test_math_used('sign(-1cm)', '-1'); +test_math_used('sign(-1mm)', '-1'); +test_math_used('sign(-1Q)', '-1'); +test_math_used('sign(-1in)', '-1'); +test_math_used('sign(-1pc)', '-1'); +test_math_used('sign(-1pt)', '-1'); +test_math_used('sign(-1em)', '-1'); +test_math_used('sign(-1ex)', '-1'); +test_math_used('sign(-1ch)', '-1'); +test_math_used('sign(-1rem)', '-1'); +test_math_used('sign(-1vh)', '-1'); +test_math_used('sign(-1vw)', '-1'); +test_math_used('sign(-1vmin)', '-1'); +test_math_used('sign(-1vmax)', '-1'); +test_math_used('sign(1s)', '1'); +test_math_used('sign(1ms)', '1'); +test_math_used('sign(-1s)', '-1'); +test_math_used('sign(-1ms)', '-1'); +test_math_used('sign(1deg)', '1'); +test_math_used('sign(1grad)', '1'); +test_math_used('sign(1rad)', '1'); +test_math_used('sign(1turn)', '1'); +test_math_used('sign(-1deg)', '-1'); +test_math_used('sign(-1grad)', '-1'); +test_math_used('sign(-1rad)', '-1'); +test_math_used('sign(-1turn)', '-1'); +test_math_used('sign(0px)', '0'); +test_math_used('sign(0cm)', '0'); +test_math_used('sign(0mm)', '0'); +test_math_used('sign(0Q)', '0'); +test_math_used('sign(0in)', '0'); +test_math_used('sign(0pc)', '0'); +test_math_used('sign(0pt)', '0'); +test_math_used('sign(0em)', '0'); +test_math_used('sign(0ex)', '0'); +test_math_used('sign(0ch)', '0'); +test_math_used('sign(0rem)', '0'); +test_math_used('sign(0vh)', '0'); +test_math_used('sign(0vw)', '0'); +test_math_used('sign(0vmin)', '0'); +test_math_used('sign(0vmax)', '0'); +test_math_used('sign(-0px)', '-0'); +test_math_used('sign(-0cm)', '-0'); +test_math_used('sign(-0mm)', '-0'); +test_math_used('sign(-0Q)', '-0'); +test_math_used('sign(-0in)', '-0'); +test_math_used('sign(-0pc)', '-0'); +test_math_used('sign(-0pt)', '-0'); +test_math_used('sign(-0em)', '-0'); +test_math_used('sign(-0ex)', '-0'); +test_math_used('sign(-0ch)', '-0'); +test_math_used('sign(-0rem)', '-0'); +test_math_used('sign(-0vh)', '-0'); +test_math_used('sign(-0vw)', '-0'); +test_math_used('sign(-0vmin)', '-0'); +test_math_used('sign(-0vmax)', '-0'); +test_math_used('sign(0s)', '0'); +test_math_used('sign(0ms)', '0'); +test_math_used('sign(-0s)', '0'); +test_math_used('sign(-0ms)', '0'); +test_math_used('sign(0deg)', '0'); +test_math_used('sign(0grad)', '0'); +test_math_used('sign(0rad)', '0'); +test_math_used('sign(0turn)', '0'); +test_math_used('sign(-0deg)', '-0'); +test_math_used('sign(-0grad)', '-0'); +test_math_used('sign(-0rad)', '-0'); +test_math_used('sign(-0turn)', '-0'); + +//Type checking abs +test_math_used('abs(1px)', '1px'); +test_math_used('abs(1cm)', '1cm'); +test_math_used('abs(1mm)', '1mm'); +test_math_used('abs(1Q)', '1Q'); +test_math_used('abs(1in)', '1in'); +test_math_used('abs(1pc)', '1pc'); +test_math_used('abs(1pt)', '1pt'); +test_math_used('abs(1em)', '1em'); +test_math_used('abs(1ex)', '1ex'); +test_math_used('abs(1ch)', '1ch'); +test_math_used('abs(1rem)', '1rem'); +test_math_used('abs(1vh)', '1vh'); +test_math_used('abs(1vw)', '1vw'); +test_math_used('abs(1vmin)', '1vmin'); +test_math_used('abs(1vmax)', '1vmax'); +test_math_used('abs(-1px)', '1px'); +test_math_used('abs(-1cm)', '1cm'); +test_math_used('abs(-1mm)', '1mm'); +test_math_used('abs(-1Q)', '1Q'); +test_math_used('abs(-1in)', '1in'); +test_math_used('abs(-1pc)', '1pc'); +test_math_used('abs(-1pt)', '1pt'); +test_math_used('abs(-1em)', '1em'); +test_math_used('abs(-1ex)', '1ex'); +test_math_used('abs(-1ch)', '1ch'); +test_math_used('abs(-1rem)', '1rem'); +test_math_used('abs(-1vh)', '1vh'); +test_math_used('abs(-1vw)', '1vw'); +test_math_used('abs(-1vmin)', '1vmin'); +test_math_used('abs(-1vmax)', '1vmax'); +test_math_used('abs(1s)', '1s', {type:'time'}); +test_math_used('abs(1ms)', '1ms', {type:'time'}); +test_math_used('abs(-1s)', '1s', {type:'time'}); +test_math_used('abs(-1ms)', '1ms', {type:'time'}); +test_math_used('abs(1deg)', '1deg', {type:'angle', approx:0.001}); +test_math_used('abs(1grad)', '1grad', {type:'angle', approx:0.001}); +test_math_used('abs(1rad)', '1rad', {type:'angle', approx:0.001}); +test_math_used('abs(1turn)', '1turn', {type:'angle', approx:0.001}); +test_math_used('abs(-1deg)', '1deg', {type:'angle', approx:0.001}); +test_math_used('abs(-1grad)', '1grad', {type:'angle', approx:0.001}); +test_math_used('abs(-1rad)', '1rad', {type:'angle', approx:0.001}); +test_math_used('abs(-1turn)', '1turn', {type:'angle', approx:0.001}); +</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/signs-abs-invalid.html b/third_party/blink/web_tests/external/wpt/css/css-values/signs-abs-invalid.html new file mode 100644 index 0000000..15b058d --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-values/signs-abs-invalid.html
@@ -0,0 +1,61 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.csswg.org/css-values-4/#comp-func"> +<link rel="help" href="https://drafts.csswg.org/css-values-4/#numbers"> +<link rel="help" href="https://drafts.csswg.org/css-values-4/#calc-type-checking"> +<link rel="author" title="Apple Inc"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/parsing-testcommon.js"></script> +<script> +function test_invalid_number(value) { + test_invalid_value('opacity', value); +} + +// Syntax checking +test_invalid_number('abs()'); +test_invalid_number('abs( )'); +test_invalid_number('abs(,)'); +test_invalid_number('abs(1, )'); +test_invalid_number('abs(, 1)'); +test_invalid_number('abs(1 + )'); +test_invalid_number('abs(1 - )'); +test_invalid_number('abs(1 * )'); +test_invalid_number('abs(1 / )'); +test_invalid_number('abs(1 2)'); +test_invalid_number('abs(1, , 2)'); +test_invalid_number('abs(1, 2)'); +test_invalid_number('sign()'); +test_invalid_number('sign( )'); +test_invalid_number('sign(,)'); +test_invalid_number('sign(1, )'); +test_invalid_number('sign(, 1)'); +test_invalid_number('sign(1 + )'); +test_invalid_number('sign(1 - )'); +test_invalid_number('sign(1 * )'); +test_invalid_number('sign(1 / )'); +test_invalid_number('sign(1 2)'); +test_invalid_number('sign(1, , 2)'); +test_invalid_number('sign(1, 2)'); + +// Type checking +test_invalid_number('abs(0px)'); +test_invalid_number('abs(0s)'); +test_invalid_number('abs(0deg)'); +test_invalid_number('abs(0Hz)'); +test_invalid_number('abs(0dpi)'); +test_invalid_number('abs(0fr)'); +test_invalid_number('abs(1, 1%)'); +test_invalid_number('abs(1, 0px)'); +test_invalid_number('abs(1, 0s)'); +test_invalid_number('abs(1, 0deg)'); +test_invalid_number('abs(1, 0Hz)'); +test_invalid_number('abs(1, 0dpi)'); +test_invalid_number('abs(1, 0fr)'); +test_invalid_number('sign(1, 1%)'); +test_invalid_number('sign(1, 0px)'); +test_invalid_number('sign(1, 0s)'); +test_invalid_number('sign(1, 0deg)'); +test_invalid_number('sign(1, 0Hz)'); +test_invalid_number('sign(1, 0dpi)'); +test_invalid_number('sign(1, 0fr)'); +</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/signs-abs-serialize-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-values/signs-abs-serialize-expected.txt new file mode 100644 index 0000000..2dc9ef1 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-values/signs-abs-serialize-expected.txt
@@ -0,0 +1,35 @@ +This is a testharness.js-based test. +FAIL 'abs(1)' as a specified value should serialize as 'calc(1)'. assert_not_equals: 'abs(1)' should be valid in opacity. got disallowed value "" +FAIL 'scale(abs(1))' as a specified value should serialize as 'scale(calc(1))'. assert_not_equals: 'scale(abs(1))' should be valid in transform. got disallowed value "" +PASS 'abs(1)' as a computed value should serialize as '1'. +FAIL 'scale(abs(1))' as a computed value should serialize as 'matrix(1, 0, 0, 1, 0, 0)'. assert_equals: 'scale(abs(1))' and 'matrix(1, 0, 0, 1, 0, 0)' should serialize the same in computed values. expected "matrix(1, 0, 0, 1, 0, 0)" but got "none" +FAIL 'sign(.1)' as a specified value should serialize as 'calc(1)'. assert_not_equals: 'sign(.1)' should be valid in opacity. got disallowed value "" +FAIL 'scale(sign(.1))' as a specified value should serialize as 'scale(calc(1))'. assert_not_equals: 'scale(sign(.1))' should be valid in transform. got disallowed value "" +PASS 'sign(.1)' as a computed value should serialize as '1'. +FAIL 'scale(sign(.1))' as a computed value should serialize as 'matrix(1, 0, 0, 1, 0, 0)'. assert_equals: 'scale(sign(.1))' and 'matrix(1, 0, 0, 1, 0, 0)' should serialize the same in computed values. expected "matrix(1, 0, 0, 1, 0, 0)" but got "none" +FAIL 'abs(1 + 2 + 3)' as a specified value should serialize as 'calc(6)'. assert_not_equals: 'abs(1 + 2 + 3)' should be valid in opacity. got disallowed value "" +FAIL 'scale(abs(1 + 2 + 3))' as a specified value should serialize as 'scale(calc(6))'. assert_not_equals: 'scale(abs(1 + 2 + 3))' should be valid in transform. got disallowed value "" +FAIL 'abs(1 + 2 + 3)' as a computed value should serialize as '6'. assert_equals: '6' should round-trip exactly in computed values. expected "6" but got "1" +FAIL 'scale(abs(1 + 2 + 3))' as a computed value should serialize as 'matrix(6, 0, 0, 6, 0, 0)'. assert_equals: 'scale(abs(1 + 2 + 3))' and 'matrix(6, 0, 0, 6, 0, 0)' should serialize the same in computed values. expected "matrix(6, 0, 0, 6, 0, 0)" but got "none" +FAIL 'sign(1 + 2 + 3)' as a specified value should serialize as 'calc(1)'. assert_not_equals: 'sign(1 + 2 + 3)' should be valid in opacity. got disallowed value "" +FAIL 'scale(sign(1 + 2 + 3))' as a specified value should serialize as 'scale(calc(1))'. assert_not_equals: 'scale(sign(1 + 2 + 3))' should be valid in transform. got disallowed value "" +PASS 'sign(1 + 2 + 3)' as a computed value should serialize as '1'. +FAIL 'scale(sign(1 + 2 + 3))' as a computed value should serialize as 'matrix(1, 0, 0, 1, 0, 0)'. assert_equals: 'scale(sign(1 + 2 + 3))' and 'matrix(1, 0, 0, 1, 0, 0)' should serialize the same in computed values. expected "matrix(1, 0, 0, 1, 0, 0)" but got "none" +FAIL 'calc(abs(1) + abs(2))' as a specified value should serialize as 'calc(3)'. assert_not_equals: 'calc(abs(1) + abs(2))' should be valid in opacity. got disallowed value "" +FAIL 'scale(calc(abs(1) + abs(2)))' as a specified value should serialize as 'scale(calc(3))'. assert_not_equals: 'scale(calc(abs(1) + abs(2)))' should be valid in transform. got disallowed value "" +FAIL 'calc(abs(1) + abs(2))' as a computed value should serialize as '3'. assert_equals: '3' should round-trip exactly in computed values. expected "3" but got "1" +FAIL 'scale(calc(abs(1) + abs(2)))' as a computed value should serialize as 'matrix(3, 0, 0, 3, 0, 0)'. assert_equals: 'scale(calc(abs(1) + abs(2)))' and 'matrix(3, 0, 0, 3, 0, 0)' should serialize the same in computed values. expected "matrix(3, 0, 0, 3, 0, 0)" but got "none" +FAIL 'calc(sign(.1) + sign(.2))' as a specified value should serialize as 'calc(2)'. assert_not_equals: 'calc(sign(.1) + sign(.2))' should be valid in opacity. got disallowed value "" +FAIL 'scale(calc(sign(.1) + sign(.2)))' as a specified value should serialize as 'scale(calc(2))'. assert_not_equals: 'scale(calc(sign(.1) + sign(.2)))' should be valid in transform. got disallowed value "" +FAIL 'calc(sign(.1) + sign(.2))' as a computed value should serialize as '2'. assert_equals: '2' should round-trip exactly in computed values. expected "2" but got "1" +FAIL 'scale(calc(sign(.1) + sign(.2)))' as a computed value should serialize as 'matrix(2, 0, 0, 2, 0, 0)'. assert_equals: 'scale(calc(sign(.1) + sign(.2)))' and 'matrix(2, 0, 0, 2, 0, 0)' should serialize the same in computed values. expected "matrix(2, 0, 0, 2, 0, 0)" but got "none" +FAIL 'calc(1 + abs(1))' as a specified value should serialize as 'calc(2)'. assert_not_equals: 'calc(1 + abs(1))' should be valid in opacity. got disallowed value "" +FAIL 'scale(calc(1 + abs(1)))' as a specified value should serialize as 'scale(calc(2))'. assert_not_equals: 'scale(calc(1 + abs(1)))' should be valid in transform. got disallowed value "" +FAIL 'calc(1 + abs(1))' as a computed value should serialize as '2'. assert_equals: '2' should round-trip exactly in computed values. expected "2" but got "1" +FAIL 'scale(calc(1 + abs(1)))' as a computed value should serialize as 'matrix(2, 0, 0, 2, 0, 0)'. assert_equals: 'scale(calc(1 + abs(1)))' and 'matrix(2, 0, 0, 2, 0, 0)' should serialize the same in computed values. expected "matrix(2, 0, 0, 2, 0, 0)" but got "none" +FAIL 'calc(sign(.1) + 1)' as a specified value should serialize as 'calc(2)'. assert_not_equals: 'calc(sign(.1) + 1)' should be valid in opacity. got disallowed value "" +FAIL 'scale(calc(sign(.1) + 1))' as a specified value should serialize as 'scale(calc(2))'. assert_not_equals: 'scale(calc(sign(.1) + 1))' should be valid in transform. got disallowed value "" +FAIL 'calc(sign(.1) + 1)' as a computed value should serialize as '2'. assert_equals: '2' should round-trip exactly in computed values. expected "2" but got "1" +FAIL 'scale(calc(sign(.1) + 1))' as a computed value should serialize as 'matrix(2, 0, 0, 2, 0, 0)'. assert_equals: 'scale(calc(sign(.1) + 1))' and 'matrix(2, 0, 0, 2, 0, 0)' should serialize the same in computed values. expected "matrix(2, 0, 0, 2, 0, 0)" but got "none" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/signs-abs-serialize.html b/third_party/blink/web_tests/external/wpt/css/css-values/signs-abs-serialize.html new file mode 100644 index 0000000..b7b5ad2 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-values/signs-abs-serialize.html
@@ -0,0 +1,53 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.csswg.org/css-values-4/#comp-func"> +<link rel="help" href="https://drafts.csswg.org/css-values-4/#numbers"> +<link rel="help" href="https://drafts.csswg.org/css-values-4/#calc-serialize"> +<link rel="author" title="Apple Inc"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/serialize-testcommon.js"></script> +<div id=target></div> +<script> +function test_serialization(t,s,c) { + test_specified_serialization('opacity', t, s); + test_specified_serialization('transform', `scale(${t})`, `scale(calc(${c}))`); + test_computed_serialization('opacity', t, c); + test_computed_serialization('transform', `scale(${t})`, `matrix(${c}, 0, 0, ${c}, 0, 0)`); +} + +test_serialization( + 'abs(1)', + 'calc(1)', + '1'); +test_serialization( + 'sign(.1)', + 'calc(1)', + '1'); + +test_serialization( + 'abs(1 + 2 + 3)', + 'calc(6)', + '6'); +test_serialization( + 'sign(1 + 2 + 3)', + 'calc(1)', + '1'); + +test_serialization( + 'calc(abs(1) + abs(2))', + 'calc(3)', + '3'); +test_serialization( + 'calc(sign(.1) + sign(.2))', + 'calc(2)', + '2'); + +test_serialization( + 'calc(1 + abs(1))', + 'calc(2)', + '2'); +test_serialization( + 'calc(sign(.1) + 1)', + 'calc(2)', + '2'); +</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-navigated-expected.txt b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-navigated-expected.txt index 91f89ee..3127c03 100644 --- a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-navigated-expected.txt +++ b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-navigated-expected.txt
@@ -6,6 +6,7 @@ PASS window.cached_appHistory.canGoBack is false PASS window.cached_appHistory.canGoForward is false PASS window.cached_appHistory.current is null +PASS window.cached_appHistory.oncurrentchange is null PASS window.cached_appHistory.onnavigate is null PASS window.cached_appHistory.onnavigateerror is null PASS window.cached_appHistory.onnavigatesuccess is null
diff --git a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-and-gced-expected.txt b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-and-gced-expected.txt index 9e8dd78..01b6895 100644 --- a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-and-gced-expected.txt +++ b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-and-gced-expected.txt
@@ -6,6 +6,7 @@ PASS window.cached_appHistory.canGoBack is false PASS window.cached_appHistory.canGoForward is false PASS window.cached_appHistory.current is null +PASS window.cached_appHistory.oncurrentchange is null PASS window.cached_appHistory.onnavigate is null PASS window.cached_appHistory.onnavigateerror is null PASS window.cached_appHistory.onnavigatesuccess is null
diff --git a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-expected.txt b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-expected.txt index 5970667..f41566e 100644 --- a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-expected.txt +++ b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-expected.txt
@@ -6,6 +6,7 @@ PASS window.cached_appHistory.canGoBack is false PASS window.cached_appHistory.canGoForward is false PASS window.cached_appHistory.current is null +PASS window.cached_appHistory.oncurrentchange is null PASS window.cached_appHistory.onnavigate is null PASS window.cached_appHistory.onnavigateerror is null PASS window.cached_appHistory.onnavigatesuccess is null
diff --git a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt index 5c865af..610a926 100644 --- a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt +++ b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt
@@ -6,6 +6,7 @@ PASS oldChildWindow.appHistory.canGoBack is newChildWindow.appHistory.canGoBack PASS oldChildWindow.appHistory.canGoForward is newChildWindow.appHistory.canGoForward PASS oldChildWindow.appHistory.current is newChildWindow.appHistory.current +PASS oldChildWindow.appHistory.oncurrentchange is newChildWindow.appHistory.oncurrentchange PASS oldChildWindow.appHistory.onnavigate is newChildWindow.appHistory.onnavigate PASS oldChildWindow.appHistory.onnavigateerror is newChildWindow.appHistory.onnavigateerror PASS oldChildWindow.appHistory.onnavigatesuccess is newChildWindow.appHistory.onnavigatesuccess
diff --git a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt index 86c57a2..e9468e57 100644 --- a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt +++ b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt
@@ -6,6 +6,7 @@ PASS childWindow.appHistory.canGoBack is false PASS childWindow.appHistory.canGoForward is false PASS childWindow.appHistory.current is null +PASS childWindow.appHistory.oncurrentchange is null PASS childWindow.appHistory.onnavigate is null PASS childWindow.appHistory.onnavigateerror is null PASS childWindow.appHistory.onnavigatesuccess is null
diff --git a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt index 655a0b1..79e12524 100644 --- a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt +++ b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt
@@ -6,6 +6,7 @@ PASS childWindow.appHistory.canGoBack is false PASS childWindow.appHistory.canGoForward is false PASS childWindow.appHistory.current is null +PASS childWindow.appHistory.oncurrentchange is null PASS childWindow.appHistory.onnavigate is null PASS childWindow.appHistory.onnavigateerror is null PASS childWindow.appHistory.onnavigatesuccess is null
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/css/css-values/round-mod-rem-computed-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/css/css-values/round-mod-rem-computed-expected.txt new file mode 100644 index 0000000..af52fc8 --- /dev/null +++ b/third_party/blink/web_tests/platform/linux/external/wpt/css/css-values/round-mod-rem-computed-expected.txt
@@ -0,0 +1,93 @@ +This is a testharness.js-based test. +Found 89 tests; 6 PASS, 83 FAIL, 0 TIMEOUT, 0 NOTRUN. +FAIL round(10,10) should be used-value-equivalent to 10 assert_equals: round(10,10) and 10 serialize to the same thing in used values. expected "matrix(10, 0, 0, 10, 0, 0)" but got "none" +FAIL mod(1,1) should be used-value-equivalent to 0 assert_equals: mod(1,1) and 0 serialize to the same thing in used values. expected "matrix(0, 0, 0, 0, 0, 0)" but got "none" +FAIL rem(1,1) should be used-value-equivalent to 0 assert_equals: rem(1,1) and 0 serialize to the same thing in used values. expected "matrix(0, 0, 0, 0, 0, 0)" but got "none" +FAIL calc(round(100,10)) should be used-value-equivalent to 100 assert_equals: calc(round(100,10)) and 100 serialize to the same thing in used values. expected "matrix(100, 0, 0, 100, 0, 0)" but got "none" +FAIL calc(round(up, 101,10)) should be used-value-equivalent to 110 assert_equals: calc(round(up, 101,10)) and 110 serialize to the same thing in used values. expected "matrix(110, 0, 0, 110, 0, 0)" but got "none" +FAIL calc(round(down, 106,10)) should be used-value-equivalent to 100 assert_equals: calc(round(down, 106,10)) and 100 serialize to the same thing in used values. expected "matrix(100, 0, 0, 100, 0, 0)" but got "none" +FAIL calc(round(to-zero,105, 10)) should be used-value-equivalent to 100 assert_equals: calc(round(to-zero,105, 10)) and 100 serialize to the same thing in used values. expected "matrix(100, 0, 0, 100, 0, 0)" but got "none" +FAIL calc(round(to-zero,-105, 10)) should be used-value-equivalent to 100 assert_equals: calc(round(to-zero,-105, 10)) and 100 serialize to the same thing in used values. expected "matrix(100, 0, 0, 100, 0, 0)" but got "none" +FAIL calc(round(-100,10)) should be used-value-equivalent to -100 assert_equals: calc(round(-100,10)) and -100 serialize to the same thing in used values. expected "matrix(-100, 0, 0, -100, 0, 0)" but got "none" +FAIL calc(round(up, -103,10)) should be used-value-equivalent to -100 assert_equals: calc(round(up, -103,10)) and -100 serialize to the same thing in used values. expected "matrix(-100, 0, 0, -100, 0, 0)" but got "none" +FAIL mod(18,5) should be used-value-equivalent to 3 assert_equals: mod(18,5) and 3 serialize to the same thing in used values. expected "matrix(3, 0, 0, 3, 0, 0)" but got "none" +FAIL rem(18,5) should be used-value-equivalent to 3 assert_equals: rem(18,5) and 3 serialize to the same thing in used values. expected "matrix(3, 0, 0, 3, 0, 0)" but got "none" +FAIL mod(-140,-90) should be used-value-equivalent to -50 assert_equals: mod(-140,-90) and -50 serialize to the same thing in used values. expected "matrix(-50, 0, 0, -50, 0, 0)" but got "none" +FAIL mod(-18,5) should be used-value-equivalent to 2 assert_equals: mod(-18,5) and 2 serialize to the same thing in used values. expected "matrix(2, 0, 0, 2, 0, 0)" but got "none" +FAIL rem(-18,5) should be used-value-equivalent to -3 assert_equals: rem(-18,5) and -3 serialize to the same thing in used values. expected "matrix(-3, 0, 0, -3, 0, 0)" but got "none" +FAIL mod(140,-90) should be used-value-equivalent to -40 assert_equals: mod(140,-90) and -40 serialize to the same thing in used values. expected "matrix(-40, 0, 0, -40, 0, 0)" but got "none" +FAIL rem(140,-90) should be used-value-equivalent to 50 assert_equals: rem(140,-90) and 50 serialize to the same thing in used values. expected "matrix(50, 0, 0, 50, 0, 0)" but got "none" +FAIL calc(round(round(100,10), 10)) should be used-value-equivalent to 100 assert_equals: calc(round(round(100,10), 10)) and 100 serialize to the same thing in used values. expected "matrix(100, 0, 0, 100, 0, 0)" but got "none" +FAIL calc(round(up, round(100,10) + 1,10)) should be used-value-equivalent to 110 assert_equals: calc(round(up, round(100,10) + 1,10)) and 110 serialize to the same thing in used values. expected "matrix(110, 0, 0, 110, 0, 0)" but got "none" +FAIL calc(round(down, round(100,10) + 2 * 3,10)) should be used-value-equivalent to 100 assert_equals: calc(round(down, round(100,10) + 2 * 3,10)) and 100 serialize to the same thing in used values. expected "matrix(100, 0, 0, 100, 0, 0)" but got "none" +FAIL calc(round(to-zero,round(100,10) * 2 - 95, 10)) should be used-value-equivalent to 100 assert_equals: calc(round(to-zero,round(100,10) * 2 - 95, 10)) and 100 serialize to the same thing in used values. expected "matrix(100, 0, 0, 100, 0, 0)" but got "none" +FAIL calc(round(round(100,10)* -1,10)) should be used-value-equivalent to -100 assert_equals: calc(round(round(100,10)* -1,10)) and -100 serialize to the same thing in used values. expected "matrix(-100, 0, 0, -100, 0, 0)" but got "none" +FAIL calc(round(up, -103 + -103 / -103 - 1,10)) should be used-value-equivalent to -100 assert_equals: calc(round(up, -103 + -103 / -103 - 1,10)) and -100 serialize to the same thing in used values. expected "matrix(-100, 0, 0, -100, 0, 0)" but got "none" +FAIL calc(mod(18,5) * 2 + mod(17,5)) should be used-value-equivalent to 8 assert_equals: calc(mod(18,5) * 2 + mod(17,5)) and 8 serialize to the same thing in used values. expected "matrix(8, 0, 0, 8, 0, 0)" but got "none" +FAIL calc(rem(mod(18,5),5)) should be used-value-equivalent to 3 assert_equals: calc(rem(mod(18,5),5)) and 3 serialize to the same thing in used values. expected "matrix(3, 0, 0, 3, 0, 0)" but got "none" +FAIL calc(rem(mod(18,5),mod(17,5))) should be used-value-equivalent to 1 assert_equals: calc(rem(mod(18,5),mod(17,5))) and 1 serialize to the same thing in used values. expected "matrix(1, 0, 0, 1, 0, 0)" but got "none" +FAIL calc(mod(-140,-90)) should be used-value-equivalent to -50 assert_equals: calc(mod(-140,-90)) and -50 serialize to the same thing in used values. expected "matrix(-50, 0, 0, -50, 0, 0)" but got "none" +FAIL calc(mod(rem(1,18)* -1,5)) should be used-value-equivalent to -1 assert_equals: calc(mod(rem(1,18)* -1,5)) and -1 serialize to the same thing in used values. expected "matrix(-1, 0, 0, -1, 0, 0)" but got "none" +FAIL round(10px,6px) should be used-value-equivalent to 12px assert_equals: round(10px,6px) and 12px serialize to the same thing in used values. expected "12px" but got "0px" +FAIL round(10cm,6cm) should be used-value-equivalent to 12cm assert_equals: round(10cm,6cm) and 12cm serialize to the same thing in used values. expected "453.543px" but got "0px" +FAIL round(10mm,6mm) should be used-value-equivalent to 12mm assert_equals: round(10mm,6mm) and 12mm serialize to the same thing in used values. expected "45.3543px" but got "0px" +FAIL round(10Q, 6Q) should be used-value-equivalent to 12Q assert_equals: round(10Q, 6Q) and 12Q serialize to the same thing in used values. expected "11.3386px" but got "0px" +FAIL round(10in,6in) should be used-value-equivalent to 12in assert_equals: round(10in,6in) and 12in serialize to the same thing in used values. expected "1152px" but got "0px" +FAIL round(10pc,6pc) should be used-value-equivalent to 12pc assert_equals: round(10pc,6pc) and 12pc serialize to the same thing in used values. expected "192px" but got "0px" +FAIL round(10pt,6pt) should be used-value-equivalent to 12pt assert_equals: round(10pt,6pt) and 12pt serialize to the same thing in used values. expected "16px" but got "0px" +FAIL round(10em,6em) should be used-value-equivalent to 12em assert_equals: round(10em,6em) and 12em serialize to the same thing in used values. expected "192px" but got "0px" +FAIL round(10ex,6ex) should be used-value-equivalent to 12ex assert_equals: round(10ex,6ex) and 12ex serialize to the same thing in used values. expected "88.125px" but got "0px" +FAIL round(10ch,6ch) should be used-value-equivalent to 12ch assert_equals: round(10ch,6ch) and 12ch serialize to the same thing in used values. expected "96px" but got "0px" +FAIL round(10rem,6rem) should be used-value-equivalent to 12rem assert_equals: round(10rem,6rem) and 12rem serialize to the same thing in used values. expected "192px" but got "0px" +FAIL round(10vh,6vh) should be used-value-equivalent to 12vh assert_equals: round(10vh,6vh) and 12vh serialize to the same thing in used values. expected "72px" but got "0px" +FAIL round(10vw,6vw) should be used-value-equivalent to 12vw assert_equals: round(10vw,6vw) and 12vw serialize to the same thing in used values. expected "96px" but got "0px" +FAIL round(10vmin,6vmin) should be used-value-equivalent to 12vmin assert_equals: round(10vmin,6vmin) and 12vmin serialize to the same thing in used values. expected "72px" but got "0px" +FAIL round(10vmax,6vmax) should be used-value-equivalent to 12vmax assert_equals: round(10vmax,6vmax) and 12vmax serialize to the same thing in used values. expected "96px" but got "0px" +PASS round(10s,6s) should be used-value-equivalent to 12s +PASS round(10ms,6ms) should be used-value-equivalent to 12ms +FAIL round(10deg,6deg) should be used-value-equivalent to 12deg Cannot read properties of undefined (reading 'split') +FAIL round(10grad,6grad) should be used-value-equivalent to 12grad Cannot read properties of undefined (reading 'split') +FAIL round(10rad,6rad) should be used-value-equivalent to 12rad Cannot read properties of undefined (reading 'split') +FAIL round(10turn,6turn) should be used-value-equivalent to 12turn Cannot read properties of undefined (reading 'split') +FAIL mod(10px,6px) should be used-value-equivalent to 4px assert_equals: mod(10px,6px) and 4px serialize to the same thing in used values. expected "4px" but got "0px" +FAIL mod(10cm,6cm) should be used-value-equivalent to 4cm assert_equals: mod(10cm,6cm) and 4cm serialize to the same thing in used values. expected "151.181px" but got "0px" +FAIL mod(10mm,6mm) should be used-value-equivalent to 4mm assert_equals: mod(10mm,6mm) and 4mm serialize to the same thing in used values. expected "15.1181px" but got "0px" +FAIL mod(10Q, 6Q) should be used-value-equivalent to 4Q assert_equals: mod(10Q, 6Q) and 4Q serialize to the same thing in used values. expected "3.77953px" but got "0px" +FAIL mod(10in,6in) should be used-value-equivalent to 4in assert_equals: mod(10in,6in) and 4in serialize to the same thing in used values. expected "384px" but got "0px" +FAIL mod(10pc,6pc) should be used-value-equivalent to 4pc assert_equals: mod(10pc,6pc) and 4pc serialize to the same thing in used values. expected "64px" but got "0px" +FAIL mod(10em,6em) should be used-value-equivalent to 4em assert_equals: mod(10em,6em) and 4em serialize to the same thing in used values. expected "64px" but got "0px" +FAIL mod(10ex,6ex) should be used-value-equivalent to 4ex assert_equals: mod(10ex,6ex) and 4ex serialize to the same thing in used values. expected "29.375px" but got "0px" +FAIL mod(10ch,6ch) should be used-value-equivalent to 4ch assert_equals: mod(10ch,6ch) and 4ch serialize to the same thing in used values. expected "32px" but got "0px" +FAIL mod(10rem,6rem) should be used-value-equivalent to 4rem assert_equals: mod(10rem,6rem) and 4rem serialize to the same thing in used values. expected "64px" but got "0px" +FAIL mod(10vh,6vh) should be used-value-equivalent to 4vh assert_equals: mod(10vh,6vh) and 4vh serialize to the same thing in used values. expected "24px" but got "0px" +FAIL mod(10vw,6vw) should be used-value-equivalent to 4vw assert_equals: mod(10vw,6vw) and 4vw serialize to the same thing in used values. expected "32px" but got "0px" +FAIL mod(10vmin,6vmin) should be used-value-equivalent to 4vmin assert_equals: mod(10vmin,6vmin) and 4vmin serialize to the same thing in used values. expected "24px" but got "0px" +FAIL mod(10vmax,6vmax) should be used-value-equivalent to 4vmax assert_equals: mod(10vmax,6vmax) and 4vmax serialize to the same thing in used values. expected "32px" but got "0px" +PASS mod(10s,6s) should be used-value-equivalent to 4s +PASS mod(10ms,6ms) should be used-value-equivalent to 4ms +FAIL mod(10deg,6deg) should be used-value-equivalent to 4deg Cannot read properties of undefined (reading 'split') +FAIL mod(10grad,6grad) should be used-value-equivalent to 4grad Cannot read properties of undefined (reading 'split') +FAIL mod(10rad,6rad) should be used-value-equivalent to 4rad Cannot read properties of undefined (reading 'split') +FAIL mod(10turn,6turn) should be used-value-equivalent to 4turn Cannot read properties of undefined (reading 'split') +FAIL rem(10px,6px) should be used-value-equivalent to 4px assert_equals: rem(10px,6px) and 4px serialize to the same thing in used values. expected "4px" but got "0px" +FAIL rem(10cm,6cm) should be used-value-equivalent to 4cm assert_equals: rem(10cm,6cm) and 4cm serialize to the same thing in used values. expected "151.181px" but got "0px" +FAIL rem(10mm,6mm) should be used-value-equivalent to 4mm assert_equals: rem(10mm,6mm) and 4mm serialize to the same thing in used values. expected "15.1181px" but got "0px" +FAIL rem(10Q, 6Q) should be used-value-equivalent to 4Q assert_equals: rem(10Q, 6Q) and 4Q serialize to the same thing in used values. expected "3.77953px" but got "0px" +FAIL rem(10in,6in) should be used-value-equivalent to 4in assert_equals: rem(10in,6in) and 4in serialize to the same thing in used values. expected "384px" but got "0px" +FAIL rem(10pc,6pc) should be used-value-equivalent to 4pc assert_equals: rem(10pc,6pc) and 4pc serialize to the same thing in used values. expected "64px" but got "0px" +FAIL rem(10em,6em) should be used-value-equivalent to 4em assert_equals: rem(10em,6em) and 4em serialize to the same thing in used values. expected "64px" but got "0px" +FAIL rem(10ex,6ex) should be used-value-equivalent to 4ex assert_equals: rem(10ex,6ex) and 4ex serialize to the same thing in used values. expected "29.375px" but got "0px" +FAIL rem(10ch,6ch) should be used-value-equivalent to 4ch assert_equals: rem(10ch,6ch) and 4ch serialize to the same thing in used values. expected "32px" but got "0px" +FAIL rem(10rem,6rem) should be used-value-equivalent to 4rem assert_equals: rem(10rem,6rem) and 4rem serialize to the same thing in used values. expected "64px" but got "0px" +FAIL rem(10vh,6vh) should be used-value-equivalent to 4vh assert_equals: rem(10vh,6vh) and 4vh serialize to the same thing in used values. expected "24px" but got "0px" +FAIL rem(10vw,6vw) should be used-value-equivalent to 4vw assert_equals: rem(10vw,6vw) and 4vw serialize to the same thing in used values. expected "32px" but got "0px" +FAIL rem(10vmin,6vmin) should be used-value-equivalent to 4vmin assert_equals: rem(10vmin,6vmin) and 4vmin serialize to the same thing in used values. expected "24px" but got "0px" +FAIL rem(10vmax,6vmax) should be used-value-equivalent to 4vmax assert_equals: rem(10vmax,6vmax) and 4vmax serialize to the same thing in used values. expected "32px" but got "0px" +PASS rem(10s,6s) should be used-value-equivalent to 4s +PASS rem(10ms,6ms) should be used-value-equivalent to 4ms +FAIL rem(10deg,6deg) should be used-value-equivalent to 4deg Cannot read properties of undefined (reading 'split') +FAIL rem(10grad,6grad) should be used-value-equivalent to 4grad Cannot read properties of undefined (reading 'split') +FAIL rem(10rad,6rad) should be used-value-equivalent to 4rad Cannot read properties of undefined (reading 'split') +FAIL rem(10turn,6turn) should be used-value-equivalent to 4turn Cannot read properties of undefined (reading 'split') +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/css/css-values/signs-abs-computed-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/css/css-values/signs-abs-computed-expected.txt new file mode 100644 index 0000000..dcc3832 --- /dev/null +++ b/third_party/blink/web_tests/platform/linux/external/wpt/css/css-values/signs-abs-computed-expected.txt
@@ -0,0 +1,146 @@ +This is a testharness.js-based test. +Found 142 tests; 87 PASS, 55 FAIL, 0 TIMEOUT, 0 NOTRUN. +FAIL abs(1) should be used-value-equivalent to 1 assert_equals: abs(1) and 1 serialize to the same thing in used values. expected "matrix(1, 0, 0, 1, 0, 0)" but got "none" +FAIL sign(1) should be used-value-equivalent to 1 assert_equals: sign(1) and 1 serialize to the same thing in used values. expected "matrix(1, 0, 0, 1, 0, 0)" but got "none" +FAIL abs(-1) should be used-value-equivalent to 1 assert_equals: abs(-1) and 1 serialize to the same thing in used values. expected "matrix(1, 0, 0, 1, 0, 0)" but got "none" +FAIL sign(-1) should be used-value-equivalent to -1 assert_equals: sign(-1) and -1 serialize to the same thing in used values. expected "matrix(-1, 0, 0, -1, 0, 0)" but got "none" +PASS abs(sign(1)) should be used-value-equivalent to 1 +PASS abs(sign(sign(1))) should be used-value-equivalent to 1 +PASS sign(sign(sign(1) + sign(1))) should be used-value-equivalent to 1 +FAIL calc(abs(0.1 + 0.2) + 0.05) should be used-value-equivalent to 0.35 Cannot read properties of undefined (reading 'split') +FAIL calc(sign(0.1 + 0.2) - 0.05) should be used-value-equivalent to 0.95 Cannot read properties of undefined (reading 'split') +FAIL calc(abs(0.1 + 0.2) * 2) should be used-value-equivalent to 0.6 Cannot read properties of undefined (reading 'split') +FAIL calc(abs(sign(0.1) + 0.2) / 2) should be used-value-equivalent to 0.6 Cannot read properties of undefined (reading 'split') +FAIL calc(abs(0.1 + 0.2) * -2) should be used-value-equivalent to -0.6 Cannot read properties of undefined (reading 'split') +FAIL calc(sign(0.1 - 0.2) - 0.05) should be used-value-equivalent to -1.05 Cannot read properties of undefined (reading 'split') +FAIL calc(sign(1) + sign(1) - 0.05) should be used-value-equivalent to 1.95 Cannot read properties of undefined (reading 'split') +FAIL calc(sign(-0)) should be used-value-equivalent to -0 assert_equals: calc(sign(-0)) and -0 serialize to the same thing in used values. expected "matrix(0, 0, 0, 0, 0, 0)" but got "none" +FAIL calc(sign(0)) should be used-value-equivalent to 0 assert_equals: calc(sign(0)) and 0 serialize to the same thing in used values. expected "matrix(0, 0, 0, 0, 0, 0)" but got "none" +PASS sign(1px) should be used-value-equivalent to 1 +PASS sign(1cm) should be used-value-equivalent to 1 +PASS sign(1mm) should be used-value-equivalent to 1 +PASS sign(1Q) should be used-value-equivalent to 1 +PASS sign(1in) should be used-value-equivalent to 1 +PASS sign(1pc) should be used-value-equivalent to 1 +PASS sign(1pt) should be used-value-equivalent to 1 +PASS sign(1em) should be used-value-equivalent to 1 +PASS sign(1ex) should be used-value-equivalent to 1 +PASS sign(1ch) should be used-value-equivalent to 1 +PASS sign(1rem) should be used-value-equivalent to 1 +PASS sign(1vh) should be used-value-equivalent to 1 +PASS sign(1vw) should be used-value-equivalent to 1 +PASS sign(1vmin) should be used-value-equivalent to 1 +PASS sign(1vmax) should be used-value-equivalent to 1 +PASS sign(-1px) should be used-value-equivalent to -1 +PASS sign(-1cm) should be used-value-equivalent to -1 +PASS sign(-1mm) should be used-value-equivalent to -1 +PASS sign(-1Q) should be used-value-equivalent to -1 +PASS sign(-1in) should be used-value-equivalent to -1 +PASS sign(-1pc) should be used-value-equivalent to -1 +PASS sign(-1pt) should be used-value-equivalent to -1 +PASS sign(-1em) should be used-value-equivalent to -1 +PASS sign(-1ex) should be used-value-equivalent to -1 +PASS sign(-1ch) should be used-value-equivalent to -1 +PASS sign(-1rem) should be used-value-equivalent to -1 +PASS sign(-1vh) should be used-value-equivalent to -1 +PASS sign(-1vw) should be used-value-equivalent to -1 +PASS sign(-1vmin) should be used-value-equivalent to -1 +PASS sign(-1vmax) should be used-value-equivalent to -1 +PASS sign(1s) should be used-value-equivalent to 1 +PASS sign(1ms) should be used-value-equivalent to 1 +PASS sign(-1s) should be used-value-equivalent to -1 +PASS sign(-1ms) should be used-value-equivalent to -1 +PASS sign(1deg) should be used-value-equivalent to 1 +PASS sign(1grad) should be used-value-equivalent to 1 +PASS sign(1rad) should be used-value-equivalent to 1 +PASS sign(1turn) should be used-value-equivalent to 1 +PASS sign(-1deg) should be used-value-equivalent to -1 +PASS sign(-1grad) should be used-value-equivalent to -1 +PASS sign(-1rad) should be used-value-equivalent to -1 +PASS sign(-1turn) should be used-value-equivalent to -1 +PASS sign(0px) should be used-value-equivalent to 0 +PASS sign(0cm) should be used-value-equivalent to 0 +PASS sign(0mm) should be used-value-equivalent to 0 +PASS sign(0Q) should be used-value-equivalent to 0 +PASS sign(0in) should be used-value-equivalent to 0 +PASS sign(0pc) should be used-value-equivalent to 0 +PASS sign(0pt) should be used-value-equivalent to 0 +PASS sign(0em) should be used-value-equivalent to 0 +PASS sign(0ex) should be used-value-equivalent to 0 +PASS sign(0ch) should be used-value-equivalent to 0 +PASS sign(0rem) should be used-value-equivalent to 0 +PASS sign(0vh) should be used-value-equivalent to 0 +PASS sign(0vw) should be used-value-equivalent to 0 +PASS sign(0vmin) should be used-value-equivalent to 0 +PASS sign(0vmax) should be used-value-equivalent to 0 +PASS sign(-0px) should be used-value-equivalent to -0 +PASS sign(-0cm) should be used-value-equivalent to -0 +PASS sign(-0mm) should be used-value-equivalent to -0 +PASS sign(-0Q) should be used-value-equivalent to -0 +PASS sign(-0in) should be used-value-equivalent to -0 +PASS sign(-0pc) should be used-value-equivalent to -0 +PASS sign(-0pt) should be used-value-equivalent to -0 +PASS sign(-0em) should be used-value-equivalent to -0 +PASS sign(-0ex) should be used-value-equivalent to -0 +PASS sign(-0ch) should be used-value-equivalent to -0 +PASS sign(-0rem) should be used-value-equivalent to -0 +PASS sign(-0vh) should be used-value-equivalent to -0 +PASS sign(-0vw) should be used-value-equivalent to -0 +PASS sign(-0vmin) should be used-value-equivalent to -0 +PASS sign(-0vmax) should be used-value-equivalent to -0 +PASS sign(0s) should be used-value-equivalent to 0 +PASS sign(0ms) should be used-value-equivalent to 0 +PASS sign(-0s) should be used-value-equivalent to 0 +PASS sign(-0ms) should be used-value-equivalent to 0 +PASS sign(0deg) should be used-value-equivalent to 0 +PASS sign(0grad) should be used-value-equivalent to 0 +PASS sign(0rad) should be used-value-equivalent to 0 +PASS sign(0turn) should be used-value-equivalent to 0 +PASS sign(-0deg) should be used-value-equivalent to -0 +PASS sign(-0grad) should be used-value-equivalent to -0 +PASS sign(-0rad) should be used-value-equivalent to -0 +PASS sign(-0turn) should be used-value-equivalent to -0 +FAIL abs(1px) should be used-value-equivalent to 1px assert_equals: abs(1px) and 1px serialize to the same thing in used values. expected "1px" but got "0px" +FAIL abs(1cm) should be used-value-equivalent to 1cm assert_equals: abs(1cm) and 1cm serialize to the same thing in used values. expected "37.7953px" but got "0px" +FAIL abs(1mm) should be used-value-equivalent to 1mm assert_equals: abs(1mm) and 1mm serialize to the same thing in used values. expected "3.77953px" but got "0px" +FAIL abs(1Q) should be used-value-equivalent to 1Q assert_equals: abs(1Q) and 1Q serialize to the same thing in used values. expected "0.944882px" but got "0px" +FAIL abs(1in) should be used-value-equivalent to 1in assert_equals: abs(1in) and 1in serialize to the same thing in used values. expected "96px" but got "0px" +FAIL abs(1pc) should be used-value-equivalent to 1pc assert_equals: abs(1pc) and 1pc serialize to the same thing in used values. expected "16px" but got "0px" +FAIL abs(1pt) should be used-value-equivalent to 1pt assert_equals: abs(1pt) and 1pt serialize to the same thing in used values. expected "1.33333px" but got "0px" +FAIL abs(1em) should be used-value-equivalent to 1em assert_equals: abs(1em) and 1em serialize to the same thing in used values. expected "16px" but got "0px" +FAIL abs(1ex) should be used-value-equivalent to 1ex assert_equals: abs(1ex) and 1ex serialize to the same thing in used values. expected "7.34375px" but got "0px" +FAIL abs(1ch) should be used-value-equivalent to 1ch assert_equals: abs(1ch) and 1ch serialize to the same thing in used values. expected "8px" but got "0px" +FAIL abs(1rem) should be used-value-equivalent to 1rem assert_equals: abs(1rem) and 1rem serialize to the same thing in used values. expected "16px" but got "0px" +FAIL abs(1vh) should be used-value-equivalent to 1vh assert_equals: abs(1vh) and 1vh serialize to the same thing in used values. expected "6px" but got "0px" +FAIL abs(1vw) should be used-value-equivalent to 1vw assert_equals: abs(1vw) and 1vw serialize to the same thing in used values. expected "8px" but got "0px" +FAIL abs(1vmin) should be used-value-equivalent to 1vmin assert_equals: abs(1vmin) and 1vmin serialize to the same thing in used values. expected "6px" but got "0px" +FAIL abs(1vmax) should be used-value-equivalent to 1vmax assert_equals: abs(1vmax) and 1vmax serialize to the same thing in used values. expected "8px" but got "0px" +FAIL abs(-1px) should be used-value-equivalent to 1px assert_equals: abs(-1px) and 1px serialize to the same thing in used values. expected "1px" but got "0px" +FAIL abs(-1cm) should be used-value-equivalent to 1cm assert_equals: abs(-1cm) and 1cm serialize to the same thing in used values. expected "37.7953px" but got "0px" +FAIL abs(-1mm) should be used-value-equivalent to 1mm assert_equals: abs(-1mm) and 1mm serialize to the same thing in used values. expected "3.77953px" but got "0px" +FAIL abs(-1Q) should be used-value-equivalent to 1Q assert_equals: abs(-1Q) and 1Q serialize to the same thing in used values. expected "0.944882px" but got "0px" +FAIL abs(-1in) should be used-value-equivalent to 1in assert_equals: abs(-1in) and 1in serialize to the same thing in used values. expected "96px" but got "0px" +FAIL abs(-1pc) should be used-value-equivalent to 1pc assert_equals: abs(-1pc) and 1pc serialize to the same thing in used values. expected "16px" but got "0px" +FAIL abs(-1pt) should be used-value-equivalent to 1pt assert_equals: abs(-1pt) and 1pt serialize to the same thing in used values. expected "1.33333px" but got "0px" +FAIL abs(-1em) should be used-value-equivalent to 1em assert_equals: abs(-1em) and 1em serialize to the same thing in used values. expected "16px" but got "0px" +FAIL abs(-1ex) should be used-value-equivalent to 1ex assert_equals: abs(-1ex) and 1ex serialize to the same thing in used values. expected "7.34375px" but got "0px" +FAIL abs(-1ch) should be used-value-equivalent to 1ch assert_equals: abs(-1ch) and 1ch serialize to the same thing in used values. expected "8px" but got "0px" +FAIL abs(-1rem) should be used-value-equivalent to 1rem assert_equals: abs(-1rem) and 1rem serialize to the same thing in used values. expected "16px" but got "0px" +FAIL abs(-1vh) should be used-value-equivalent to 1vh assert_equals: abs(-1vh) and 1vh serialize to the same thing in used values. expected "6px" but got "0px" +FAIL abs(-1vw) should be used-value-equivalent to 1vw assert_equals: abs(-1vw) and 1vw serialize to the same thing in used values. expected "8px" but got "0px" +FAIL abs(-1vmin) should be used-value-equivalent to 1vmin assert_equals: abs(-1vmin) and 1vmin serialize to the same thing in used values. expected "6px" but got "0px" +FAIL abs(-1vmax) should be used-value-equivalent to 1vmax assert_equals: abs(-1vmax) and 1vmax serialize to the same thing in used values. expected "8px" but got "0px" +FAIL abs(1s) should be used-value-equivalent to 1s assert_equals: abs(1s) and 1s serialize to the same thing in used values. expected "1s" but got "0s" +FAIL abs(1ms) should be used-value-equivalent to 1ms assert_equals: abs(1ms) and 1ms serialize to the same thing in used values. expected "0.001s" but got "0s" +FAIL abs(-1s) should be used-value-equivalent to 1s assert_equals: abs(-1s) and 1s serialize to the same thing in used values. expected "1s" but got "0s" +FAIL abs(-1ms) should be used-value-equivalent to 1ms assert_equals: abs(-1ms) and 1ms serialize to the same thing in used values. expected "0.001s" but got "0s" +FAIL abs(1deg) should be used-value-equivalent to 1deg Cannot read properties of undefined (reading 'split') +FAIL abs(1grad) should be used-value-equivalent to 1grad Cannot read properties of undefined (reading 'split') +FAIL abs(1rad) should be used-value-equivalent to 1rad Cannot read properties of undefined (reading 'split') +FAIL abs(1turn) should be used-value-equivalent to 1turn Cannot read properties of undefined (reading 'split') +FAIL abs(-1deg) should be used-value-equivalent to 1deg Cannot read properties of undefined (reading 'split') +FAIL abs(-1grad) should be used-value-equivalent to 1grad Cannot read properties of undefined (reading 'split') +FAIL abs(-1rad) should be used-value-equivalent to 1rad Cannot read properties of undefined (reading 'split') +FAIL abs(-1turn) should be used-value-equivalent to 1turn Cannot read properties of undefined (reading 'split') +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/linux/virtual/css-calc-infinity-and-nan-disabled/external/wpt/css/css-values/round-mod-rem-computed-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/css-calc-infinity-and-nan-disabled/external/wpt/css/css-values/round-mod-rem-computed-expected.txt new file mode 100644 index 0000000..af52fc8 --- /dev/null +++ b/third_party/blink/web_tests/platform/linux/virtual/css-calc-infinity-and-nan-disabled/external/wpt/css/css-values/round-mod-rem-computed-expected.txt
@@ -0,0 +1,93 @@ +This is a testharness.js-based test. +Found 89 tests; 6 PASS, 83 FAIL, 0 TIMEOUT, 0 NOTRUN. +FAIL round(10,10) should be used-value-equivalent to 10 assert_equals: round(10,10) and 10 serialize to the same thing in used values. expected "matrix(10, 0, 0, 10, 0, 0)" but got "none" +FAIL mod(1,1) should be used-value-equivalent to 0 assert_equals: mod(1,1) and 0 serialize to the same thing in used values. expected "matrix(0, 0, 0, 0, 0, 0)" but got "none" +FAIL rem(1,1) should be used-value-equivalent to 0 assert_equals: rem(1,1) and 0 serialize to the same thing in used values. expected "matrix(0, 0, 0, 0, 0, 0)" but got "none" +FAIL calc(round(100,10)) should be used-value-equivalent to 100 assert_equals: calc(round(100,10)) and 100 serialize to the same thing in used values. expected "matrix(100, 0, 0, 100, 0, 0)" but got "none" +FAIL calc(round(up, 101,10)) should be used-value-equivalent to 110 assert_equals: calc(round(up, 101,10)) and 110 serialize to the same thing in used values. expected "matrix(110, 0, 0, 110, 0, 0)" but got "none" +FAIL calc(round(down, 106,10)) should be used-value-equivalent to 100 assert_equals: calc(round(down, 106,10)) and 100 serialize to the same thing in used values. expected "matrix(100, 0, 0, 100, 0, 0)" but got "none" +FAIL calc(round(to-zero,105, 10)) should be used-value-equivalent to 100 assert_equals: calc(round(to-zero,105, 10)) and 100 serialize to the same thing in used values. expected "matrix(100, 0, 0, 100, 0, 0)" but got "none" +FAIL calc(round(to-zero,-105, 10)) should be used-value-equivalent to 100 assert_equals: calc(round(to-zero,-105, 10)) and 100 serialize to the same thing in used values. expected "matrix(100, 0, 0, 100, 0, 0)" but got "none" +FAIL calc(round(-100,10)) should be used-value-equivalent to -100 assert_equals: calc(round(-100,10)) and -100 serialize to the same thing in used values. expected "matrix(-100, 0, 0, -100, 0, 0)" but got "none" +FAIL calc(round(up, -103,10)) should be used-value-equivalent to -100 assert_equals: calc(round(up, -103,10)) and -100 serialize to the same thing in used values. expected "matrix(-100, 0, 0, -100, 0, 0)" but got "none" +FAIL mod(18,5) should be used-value-equivalent to 3 assert_equals: mod(18,5) and 3 serialize to the same thing in used values. expected "matrix(3, 0, 0, 3, 0, 0)" but got "none" +FAIL rem(18,5) should be used-value-equivalent to 3 assert_equals: rem(18,5) and 3 serialize to the same thing in used values. expected "matrix(3, 0, 0, 3, 0, 0)" but got "none" +FAIL mod(-140,-90) should be used-value-equivalent to -50 assert_equals: mod(-140,-90) and -50 serialize to the same thing in used values. expected "matrix(-50, 0, 0, -50, 0, 0)" but got "none" +FAIL mod(-18,5) should be used-value-equivalent to 2 assert_equals: mod(-18,5) and 2 serialize to the same thing in used values. expected "matrix(2, 0, 0, 2, 0, 0)" but got "none" +FAIL rem(-18,5) should be used-value-equivalent to -3 assert_equals: rem(-18,5) and -3 serialize to the same thing in used values. expected "matrix(-3, 0, 0, -3, 0, 0)" but got "none" +FAIL mod(140,-90) should be used-value-equivalent to -40 assert_equals: mod(140,-90) and -40 serialize to the same thing in used values. expected "matrix(-40, 0, 0, -40, 0, 0)" but got "none" +FAIL rem(140,-90) should be used-value-equivalent to 50 assert_equals: rem(140,-90) and 50 serialize to the same thing in used values. expected "matrix(50, 0, 0, 50, 0, 0)" but got "none" +FAIL calc(round(round(100,10), 10)) should be used-value-equivalent to 100 assert_equals: calc(round(round(100,10), 10)) and 100 serialize to the same thing in used values. expected "matrix(100, 0, 0, 100, 0, 0)" but got "none" +FAIL calc(round(up, round(100,10) + 1,10)) should be used-value-equivalent to 110 assert_equals: calc(round(up, round(100,10) + 1,10)) and 110 serialize to the same thing in used values. expected "matrix(110, 0, 0, 110, 0, 0)" but got "none" +FAIL calc(round(down, round(100,10) + 2 * 3,10)) should be used-value-equivalent to 100 assert_equals: calc(round(down, round(100,10) + 2 * 3,10)) and 100 serialize to the same thing in used values. expected "matrix(100, 0, 0, 100, 0, 0)" but got "none" +FAIL calc(round(to-zero,round(100,10) * 2 - 95, 10)) should be used-value-equivalent to 100 assert_equals: calc(round(to-zero,round(100,10) * 2 - 95, 10)) and 100 serialize to the same thing in used values. expected "matrix(100, 0, 0, 100, 0, 0)" but got "none" +FAIL calc(round(round(100,10)* -1,10)) should be used-value-equivalent to -100 assert_equals: calc(round(round(100,10)* -1,10)) and -100 serialize to the same thing in used values. expected "matrix(-100, 0, 0, -100, 0, 0)" but got "none" +FAIL calc(round(up, -103 + -103 / -103 - 1,10)) should be used-value-equivalent to -100 assert_equals: calc(round(up, -103 + -103 / -103 - 1,10)) and -100 serialize to the same thing in used values. expected "matrix(-100, 0, 0, -100, 0, 0)" but got "none" +FAIL calc(mod(18,5) * 2 + mod(17,5)) should be used-value-equivalent to 8 assert_equals: calc(mod(18,5) * 2 + mod(17,5)) and 8 serialize to the same thing in used values. expected "matrix(8, 0, 0, 8, 0, 0)" but got "none" +FAIL calc(rem(mod(18,5),5)) should be used-value-equivalent to 3 assert_equals: calc(rem(mod(18,5),5)) and 3 serialize to the same thing in used values. expected "matrix(3, 0, 0, 3, 0, 0)" but got "none" +FAIL calc(rem(mod(18,5),mod(17,5))) should be used-value-equivalent to 1 assert_equals: calc(rem(mod(18,5),mod(17,5))) and 1 serialize to the same thing in used values. expected "matrix(1, 0, 0, 1, 0, 0)" but got "none" +FAIL calc(mod(-140,-90)) should be used-value-equivalent to -50 assert_equals: calc(mod(-140,-90)) and -50 serialize to the same thing in used values. expected "matrix(-50, 0, 0, -50, 0, 0)" but got "none" +FAIL calc(mod(rem(1,18)* -1,5)) should be used-value-equivalent to -1 assert_equals: calc(mod(rem(1,18)* -1,5)) and -1 serialize to the same thing in used values. expected "matrix(-1, 0, 0, -1, 0, 0)" but got "none" +FAIL round(10px,6px) should be used-value-equivalent to 12px assert_equals: round(10px,6px) and 12px serialize to the same thing in used values. expected "12px" but got "0px" +FAIL round(10cm,6cm) should be used-value-equivalent to 12cm assert_equals: round(10cm,6cm) and 12cm serialize to the same thing in used values. expected "453.543px" but got "0px" +FAIL round(10mm,6mm) should be used-value-equivalent to 12mm assert_equals: round(10mm,6mm) and 12mm serialize to the same thing in used values. expected "45.3543px" but got "0px" +FAIL round(10Q, 6Q) should be used-value-equivalent to 12Q assert_equals: round(10Q, 6Q) and 12Q serialize to the same thing in used values. expected "11.3386px" but got "0px" +FAIL round(10in,6in) should be used-value-equivalent to 12in assert_equals: round(10in,6in) and 12in serialize to the same thing in used values. expected "1152px" but got "0px" +FAIL round(10pc,6pc) should be used-value-equivalent to 12pc assert_equals: round(10pc,6pc) and 12pc serialize to the same thing in used values. expected "192px" but got "0px" +FAIL round(10pt,6pt) should be used-value-equivalent to 12pt assert_equals: round(10pt,6pt) and 12pt serialize to the same thing in used values. expected "16px" but got "0px" +FAIL round(10em,6em) should be used-value-equivalent to 12em assert_equals: round(10em,6em) and 12em serialize to the same thing in used values. expected "192px" but got "0px" +FAIL round(10ex,6ex) should be used-value-equivalent to 12ex assert_equals: round(10ex,6ex) and 12ex serialize to the same thing in used values. expected "88.125px" but got "0px" +FAIL round(10ch,6ch) should be used-value-equivalent to 12ch assert_equals: round(10ch,6ch) and 12ch serialize to the same thing in used values. expected "96px" but got "0px" +FAIL round(10rem,6rem) should be used-value-equivalent to 12rem assert_equals: round(10rem,6rem) and 12rem serialize to the same thing in used values. expected "192px" but got "0px" +FAIL round(10vh,6vh) should be used-value-equivalent to 12vh assert_equals: round(10vh,6vh) and 12vh serialize to the same thing in used values. expected "72px" but got "0px" +FAIL round(10vw,6vw) should be used-value-equivalent to 12vw assert_equals: round(10vw,6vw) and 12vw serialize to the same thing in used values. expected "96px" but got "0px" +FAIL round(10vmin,6vmin) should be used-value-equivalent to 12vmin assert_equals: round(10vmin,6vmin) and 12vmin serialize to the same thing in used values. expected "72px" but got "0px" +FAIL round(10vmax,6vmax) should be used-value-equivalent to 12vmax assert_equals: round(10vmax,6vmax) and 12vmax serialize to the same thing in used values. expected "96px" but got "0px" +PASS round(10s,6s) should be used-value-equivalent to 12s +PASS round(10ms,6ms) should be used-value-equivalent to 12ms +FAIL round(10deg,6deg) should be used-value-equivalent to 12deg Cannot read properties of undefined (reading 'split') +FAIL round(10grad,6grad) should be used-value-equivalent to 12grad Cannot read properties of undefined (reading 'split') +FAIL round(10rad,6rad) should be used-value-equivalent to 12rad Cannot read properties of undefined (reading 'split') +FAIL round(10turn,6turn) should be used-value-equivalent to 12turn Cannot read properties of undefined (reading 'split') +FAIL mod(10px,6px) should be used-value-equivalent to 4px assert_equals: mod(10px,6px) and 4px serialize to the same thing in used values. expected "4px" but got "0px" +FAIL mod(10cm,6cm) should be used-value-equivalent to 4cm assert_equals: mod(10cm,6cm) and 4cm serialize to the same thing in used values. expected "151.181px" but got "0px" +FAIL mod(10mm,6mm) should be used-value-equivalent to 4mm assert_equals: mod(10mm,6mm) and 4mm serialize to the same thing in used values. expected "15.1181px" but got "0px" +FAIL mod(10Q, 6Q) should be used-value-equivalent to 4Q assert_equals: mod(10Q, 6Q) and 4Q serialize to the same thing in used values. expected "3.77953px" but got "0px" +FAIL mod(10in,6in) should be used-value-equivalent to 4in assert_equals: mod(10in,6in) and 4in serialize to the same thing in used values. expected "384px" but got "0px" +FAIL mod(10pc,6pc) should be used-value-equivalent to 4pc assert_equals: mod(10pc,6pc) and 4pc serialize to the same thing in used values. expected "64px" but got "0px" +FAIL mod(10em,6em) should be used-value-equivalent to 4em assert_equals: mod(10em,6em) and 4em serialize to the same thing in used values. expected "64px" but got "0px" +FAIL mod(10ex,6ex) should be used-value-equivalent to 4ex assert_equals: mod(10ex,6ex) and 4ex serialize to the same thing in used values. expected "29.375px" but got "0px" +FAIL mod(10ch,6ch) should be used-value-equivalent to 4ch assert_equals: mod(10ch,6ch) and 4ch serialize to the same thing in used values. expected "32px" but got "0px" +FAIL mod(10rem,6rem) should be used-value-equivalent to 4rem assert_equals: mod(10rem,6rem) and 4rem serialize to the same thing in used values. expected "64px" but got "0px" +FAIL mod(10vh,6vh) should be used-value-equivalent to 4vh assert_equals: mod(10vh,6vh) and 4vh serialize to the same thing in used values. expected "24px" but got "0px" +FAIL mod(10vw,6vw) should be used-value-equivalent to 4vw assert_equals: mod(10vw,6vw) and 4vw serialize to the same thing in used values. expected "32px" but got "0px" +FAIL mod(10vmin,6vmin) should be used-value-equivalent to 4vmin assert_equals: mod(10vmin,6vmin) and 4vmin serialize to the same thing in used values. expected "24px" but got "0px" +FAIL mod(10vmax,6vmax) should be used-value-equivalent to 4vmax assert_equals: mod(10vmax,6vmax) and 4vmax serialize to the same thing in used values. expected "32px" but got "0px" +PASS mod(10s,6s) should be used-value-equivalent to 4s +PASS mod(10ms,6ms) should be used-value-equivalent to 4ms +FAIL mod(10deg,6deg) should be used-value-equivalent to 4deg Cannot read properties of undefined (reading 'split') +FAIL mod(10grad,6grad) should be used-value-equivalent to 4grad Cannot read properties of undefined (reading 'split') +FAIL mod(10rad,6rad) should be used-value-equivalent to 4rad Cannot read properties of undefined (reading 'split') +FAIL mod(10turn,6turn) should be used-value-equivalent to 4turn Cannot read properties of undefined (reading 'split') +FAIL rem(10px,6px) should be used-value-equivalent to 4px assert_equals: rem(10px,6px) and 4px serialize to the same thing in used values. expected "4px" but got "0px" +FAIL rem(10cm,6cm) should be used-value-equivalent to 4cm assert_equals: rem(10cm,6cm) and 4cm serialize to the same thing in used values. expected "151.181px" but got "0px" +FAIL rem(10mm,6mm) should be used-value-equivalent to 4mm assert_equals: rem(10mm,6mm) and 4mm serialize to the same thing in used values. expected "15.1181px" but got "0px" +FAIL rem(10Q, 6Q) should be used-value-equivalent to 4Q assert_equals: rem(10Q, 6Q) and 4Q serialize to the same thing in used values. expected "3.77953px" but got "0px" +FAIL rem(10in,6in) should be used-value-equivalent to 4in assert_equals: rem(10in,6in) and 4in serialize to the same thing in used values. expected "384px" but got "0px" +FAIL rem(10pc,6pc) should be used-value-equivalent to 4pc assert_equals: rem(10pc,6pc) and 4pc serialize to the same thing in used values. expected "64px" but got "0px" +FAIL rem(10em,6em) should be used-value-equivalent to 4em assert_equals: rem(10em,6em) and 4em serialize to the same thing in used values. expected "64px" but got "0px" +FAIL rem(10ex,6ex) should be used-value-equivalent to 4ex assert_equals: rem(10ex,6ex) and 4ex serialize to the same thing in used values. expected "29.375px" but got "0px" +FAIL rem(10ch,6ch) should be used-value-equivalent to 4ch assert_equals: rem(10ch,6ch) and 4ch serialize to the same thing in used values. expected "32px" but got "0px" +FAIL rem(10rem,6rem) should be used-value-equivalent to 4rem assert_equals: rem(10rem,6rem) and 4rem serialize to the same thing in used values. expected "64px" but got "0px" +FAIL rem(10vh,6vh) should be used-value-equivalent to 4vh assert_equals: rem(10vh,6vh) and 4vh serialize to the same thing in used values. expected "24px" but got "0px" +FAIL rem(10vw,6vw) should be used-value-equivalent to 4vw assert_equals: rem(10vw,6vw) and 4vw serialize to the same thing in used values. expected "32px" but got "0px" +FAIL rem(10vmin,6vmin) should be used-value-equivalent to 4vmin assert_equals: rem(10vmin,6vmin) and 4vmin serialize to the same thing in used values. expected "24px" but got "0px" +FAIL rem(10vmax,6vmax) should be used-value-equivalent to 4vmax assert_equals: rem(10vmax,6vmax) and 4vmax serialize to the same thing in used values. expected "32px" but got "0px" +PASS rem(10s,6s) should be used-value-equivalent to 4s +PASS rem(10ms,6ms) should be used-value-equivalent to 4ms +FAIL rem(10deg,6deg) should be used-value-equivalent to 4deg Cannot read properties of undefined (reading 'split') +FAIL rem(10grad,6grad) should be used-value-equivalent to 4grad Cannot read properties of undefined (reading 'split') +FAIL rem(10rad,6rad) should be used-value-equivalent to 4rad Cannot read properties of undefined (reading 'split') +FAIL rem(10turn,6turn) should be used-value-equivalent to 4turn Cannot read properties of undefined (reading 'split') +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/linux/virtual/css-calc-infinity-and-nan-disabled/external/wpt/css/css-values/signs-abs-computed-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/css-calc-infinity-and-nan-disabled/external/wpt/css/css-values/signs-abs-computed-expected.txt new file mode 100644 index 0000000..dcc3832 --- /dev/null +++ b/third_party/blink/web_tests/platform/linux/virtual/css-calc-infinity-and-nan-disabled/external/wpt/css/css-values/signs-abs-computed-expected.txt
@@ -0,0 +1,146 @@ +This is a testharness.js-based test. +Found 142 tests; 87 PASS, 55 FAIL, 0 TIMEOUT, 0 NOTRUN. +FAIL abs(1) should be used-value-equivalent to 1 assert_equals: abs(1) and 1 serialize to the same thing in used values. expected "matrix(1, 0, 0, 1, 0, 0)" but got "none" +FAIL sign(1) should be used-value-equivalent to 1 assert_equals: sign(1) and 1 serialize to the same thing in used values. expected "matrix(1, 0, 0, 1, 0, 0)" but got "none" +FAIL abs(-1) should be used-value-equivalent to 1 assert_equals: abs(-1) and 1 serialize to the same thing in used values. expected "matrix(1, 0, 0, 1, 0, 0)" but got "none" +FAIL sign(-1) should be used-value-equivalent to -1 assert_equals: sign(-1) and -1 serialize to the same thing in used values. expected "matrix(-1, 0, 0, -1, 0, 0)" but got "none" +PASS abs(sign(1)) should be used-value-equivalent to 1 +PASS abs(sign(sign(1))) should be used-value-equivalent to 1 +PASS sign(sign(sign(1) + sign(1))) should be used-value-equivalent to 1 +FAIL calc(abs(0.1 + 0.2) + 0.05) should be used-value-equivalent to 0.35 Cannot read properties of undefined (reading 'split') +FAIL calc(sign(0.1 + 0.2) - 0.05) should be used-value-equivalent to 0.95 Cannot read properties of undefined (reading 'split') +FAIL calc(abs(0.1 + 0.2) * 2) should be used-value-equivalent to 0.6 Cannot read properties of undefined (reading 'split') +FAIL calc(abs(sign(0.1) + 0.2) / 2) should be used-value-equivalent to 0.6 Cannot read properties of undefined (reading 'split') +FAIL calc(abs(0.1 + 0.2) * -2) should be used-value-equivalent to -0.6 Cannot read properties of undefined (reading 'split') +FAIL calc(sign(0.1 - 0.2) - 0.05) should be used-value-equivalent to -1.05 Cannot read properties of undefined (reading 'split') +FAIL calc(sign(1) + sign(1) - 0.05) should be used-value-equivalent to 1.95 Cannot read properties of undefined (reading 'split') +FAIL calc(sign(-0)) should be used-value-equivalent to -0 assert_equals: calc(sign(-0)) and -0 serialize to the same thing in used values. expected "matrix(0, 0, 0, 0, 0, 0)" but got "none" +FAIL calc(sign(0)) should be used-value-equivalent to 0 assert_equals: calc(sign(0)) and 0 serialize to the same thing in used values. expected "matrix(0, 0, 0, 0, 0, 0)" but got "none" +PASS sign(1px) should be used-value-equivalent to 1 +PASS sign(1cm) should be used-value-equivalent to 1 +PASS sign(1mm) should be used-value-equivalent to 1 +PASS sign(1Q) should be used-value-equivalent to 1 +PASS sign(1in) should be used-value-equivalent to 1 +PASS sign(1pc) should be used-value-equivalent to 1 +PASS sign(1pt) should be used-value-equivalent to 1 +PASS sign(1em) should be used-value-equivalent to 1 +PASS sign(1ex) should be used-value-equivalent to 1 +PASS sign(1ch) should be used-value-equivalent to 1 +PASS sign(1rem) should be used-value-equivalent to 1 +PASS sign(1vh) should be used-value-equivalent to 1 +PASS sign(1vw) should be used-value-equivalent to 1 +PASS sign(1vmin) should be used-value-equivalent to 1 +PASS sign(1vmax) should be used-value-equivalent to 1 +PASS sign(-1px) should be used-value-equivalent to -1 +PASS sign(-1cm) should be used-value-equivalent to -1 +PASS sign(-1mm) should be used-value-equivalent to -1 +PASS sign(-1Q) should be used-value-equivalent to -1 +PASS sign(-1in) should be used-value-equivalent to -1 +PASS sign(-1pc) should be used-value-equivalent to -1 +PASS sign(-1pt) should be used-value-equivalent to -1 +PASS sign(-1em) should be used-value-equivalent to -1 +PASS sign(-1ex) should be used-value-equivalent to -1 +PASS sign(-1ch) should be used-value-equivalent to -1 +PASS sign(-1rem) should be used-value-equivalent to -1 +PASS sign(-1vh) should be used-value-equivalent to -1 +PASS sign(-1vw) should be used-value-equivalent to -1 +PASS sign(-1vmin) should be used-value-equivalent to -1 +PASS sign(-1vmax) should be used-value-equivalent to -1 +PASS sign(1s) should be used-value-equivalent to 1 +PASS sign(1ms) should be used-value-equivalent to 1 +PASS sign(-1s) should be used-value-equivalent to -1 +PASS sign(-1ms) should be used-value-equivalent to -1 +PASS sign(1deg) should be used-value-equivalent to 1 +PASS sign(1grad) should be used-value-equivalent to 1 +PASS sign(1rad) should be used-value-equivalent to 1 +PASS sign(1turn) should be used-value-equivalent to 1 +PASS sign(-1deg) should be used-value-equivalent to -1 +PASS sign(-1grad) should be used-value-equivalent to -1 +PASS sign(-1rad) should be used-value-equivalent to -1 +PASS sign(-1turn) should be used-value-equivalent to -1 +PASS sign(0px) should be used-value-equivalent to 0 +PASS sign(0cm) should be used-value-equivalent to 0 +PASS sign(0mm) should be used-value-equivalent to 0 +PASS sign(0Q) should be used-value-equivalent to 0 +PASS sign(0in) should be used-value-equivalent to 0 +PASS sign(0pc) should be used-value-equivalent to 0 +PASS sign(0pt) should be used-value-equivalent to 0 +PASS sign(0em) should be used-value-equivalent to 0 +PASS sign(0ex) should be used-value-equivalent to 0 +PASS sign(0ch) should be used-value-equivalent to 0 +PASS sign(0rem) should be used-value-equivalent to 0 +PASS sign(0vh) should be used-value-equivalent to 0 +PASS sign(0vw) should be used-value-equivalent to 0 +PASS sign(0vmin) should be used-value-equivalent to 0 +PASS sign(0vmax) should be used-value-equivalent to 0 +PASS sign(-0px) should be used-value-equivalent to -0 +PASS sign(-0cm) should be used-value-equivalent to -0 +PASS sign(-0mm) should be used-value-equivalent to -0 +PASS sign(-0Q) should be used-value-equivalent to -0 +PASS sign(-0in) should be used-value-equivalent to -0 +PASS sign(-0pc) should be used-value-equivalent to -0 +PASS sign(-0pt) should be used-value-equivalent to -0 +PASS sign(-0em) should be used-value-equivalent to -0 +PASS sign(-0ex) should be used-value-equivalent to -0 +PASS sign(-0ch) should be used-value-equivalent to -0 +PASS sign(-0rem) should be used-value-equivalent to -0 +PASS sign(-0vh) should be used-value-equivalent to -0 +PASS sign(-0vw) should be used-value-equivalent to -0 +PASS sign(-0vmin) should be used-value-equivalent to -0 +PASS sign(-0vmax) should be used-value-equivalent to -0 +PASS sign(0s) should be used-value-equivalent to 0 +PASS sign(0ms) should be used-value-equivalent to 0 +PASS sign(-0s) should be used-value-equivalent to 0 +PASS sign(-0ms) should be used-value-equivalent to 0 +PASS sign(0deg) should be used-value-equivalent to 0 +PASS sign(0grad) should be used-value-equivalent to 0 +PASS sign(0rad) should be used-value-equivalent to 0 +PASS sign(0turn) should be used-value-equivalent to 0 +PASS sign(-0deg) should be used-value-equivalent to -0 +PASS sign(-0grad) should be used-value-equivalent to -0 +PASS sign(-0rad) should be used-value-equivalent to -0 +PASS sign(-0turn) should be used-value-equivalent to -0 +FAIL abs(1px) should be used-value-equivalent to 1px assert_equals: abs(1px) and 1px serialize to the same thing in used values. expected "1px" but got "0px" +FAIL abs(1cm) should be used-value-equivalent to 1cm assert_equals: abs(1cm) and 1cm serialize to the same thing in used values. expected "37.7953px" but got "0px" +FAIL abs(1mm) should be used-value-equivalent to 1mm assert_equals: abs(1mm) and 1mm serialize to the same thing in used values. expected "3.77953px" but got "0px" +FAIL abs(1Q) should be used-value-equivalent to 1Q assert_equals: abs(1Q) and 1Q serialize to the same thing in used values. expected "0.944882px" but got "0px" +FAIL abs(1in) should be used-value-equivalent to 1in assert_equals: abs(1in) and 1in serialize to the same thing in used values. expected "96px" but got "0px" +FAIL abs(1pc) should be used-value-equivalent to 1pc assert_equals: abs(1pc) and 1pc serialize to the same thing in used values. expected "16px" but got "0px" +FAIL abs(1pt) should be used-value-equivalent to 1pt assert_equals: abs(1pt) and 1pt serialize to the same thing in used values. expected "1.33333px" but got "0px" +FAIL abs(1em) should be used-value-equivalent to 1em assert_equals: abs(1em) and 1em serialize to the same thing in used values. expected "16px" but got "0px" +FAIL abs(1ex) should be used-value-equivalent to 1ex assert_equals: abs(1ex) and 1ex serialize to the same thing in used values. expected "7.34375px" but got "0px" +FAIL abs(1ch) should be used-value-equivalent to 1ch assert_equals: abs(1ch) and 1ch serialize to the same thing in used values. expected "8px" but got "0px" +FAIL abs(1rem) should be used-value-equivalent to 1rem assert_equals: abs(1rem) and 1rem serialize to the same thing in used values. expected "16px" but got "0px" +FAIL abs(1vh) should be used-value-equivalent to 1vh assert_equals: abs(1vh) and 1vh serialize to the same thing in used values. expected "6px" but got "0px" +FAIL abs(1vw) should be used-value-equivalent to 1vw assert_equals: abs(1vw) and 1vw serialize to the same thing in used values. expected "8px" but got "0px" +FAIL abs(1vmin) should be used-value-equivalent to 1vmin assert_equals: abs(1vmin) and 1vmin serialize to the same thing in used values. expected "6px" but got "0px" +FAIL abs(1vmax) should be used-value-equivalent to 1vmax assert_equals: abs(1vmax) and 1vmax serialize to the same thing in used values. expected "8px" but got "0px" +FAIL abs(-1px) should be used-value-equivalent to 1px assert_equals: abs(-1px) and 1px serialize to the same thing in used values. expected "1px" but got "0px" +FAIL abs(-1cm) should be used-value-equivalent to 1cm assert_equals: abs(-1cm) and 1cm serialize to the same thing in used values. expected "37.7953px" but got "0px" +FAIL abs(-1mm) should be used-value-equivalent to 1mm assert_equals: abs(-1mm) and 1mm serialize to the same thing in used values. expected "3.77953px" but got "0px" +FAIL abs(-1Q) should be used-value-equivalent to 1Q assert_equals: abs(-1Q) and 1Q serialize to the same thing in used values. expected "0.944882px" but got "0px" +FAIL abs(-1in) should be used-value-equivalent to 1in assert_equals: abs(-1in) and 1in serialize to the same thing in used values. expected "96px" but got "0px" +FAIL abs(-1pc) should be used-value-equivalent to 1pc assert_equals: abs(-1pc) and 1pc serialize to the same thing in used values. expected "16px" but got "0px" +FAIL abs(-1pt) should be used-value-equivalent to 1pt assert_equals: abs(-1pt) and 1pt serialize to the same thing in used values. expected "1.33333px" but got "0px" +FAIL abs(-1em) should be used-value-equivalent to 1em assert_equals: abs(-1em) and 1em serialize to the same thing in used values. expected "16px" but got "0px" +FAIL abs(-1ex) should be used-value-equivalent to 1ex assert_equals: abs(-1ex) and 1ex serialize to the same thing in used values. expected "7.34375px" but got "0px" +FAIL abs(-1ch) should be used-value-equivalent to 1ch assert_equals: abs(-1ch) and 1ch serialize to the same thing in used values. expected "8px" but got "0px" +FAIL abs(-1rem) should be used-value-equivalent to 1rem assert_equals: abs(-1rem) and 1rem serialize to the same thing in used values. expected "16px" but got "0px" +FAIL abs(-1vh) should be used-value-equivalent to 1vh assert_equals: abs(-1vh) and 1vh serialize to the same thing in used values. expected "6px" but got "0px" +FAIL abs(-1vw) should be used-value-equivalent to 1vw assert_equals: abs(-1vw) and 1vw serialize to the same thing in used values. expected "8px" but got "0px" +FAIL abs(-1vmin) should be used-value-equivalent to 1vmin assert_equals: abs(-1vmin) and 1vmin serialize to the same thing in used values. expected "6px" but got "0px" +FAIL abs(-1vmax) should be used-value-equivalent to 1vmax assert_equals: abs(-1vmax) and 1vmax serialize to the same thing in used values. expected "8px" but got "0px" +FAIL abs(1s) should be used-value-equivalent to 1s assert_equals: abs(1s) and 1s serialize to the same thing in used values. expected "1s" but got "0s" +FAIL abs(1ms) should be used-value-equivalent to 1ms assert_equals: abs(1ms) and 1ms serialize to the same thing in used values. expected "0.001s" but got "0s" +FAIL abs(-1s) should be used-value-equivalent to 1s assert_equals: abs(-1s) and 1s serialize to the same thing in used values. expected "1s" but got "0s" +FAIL abs(-1ms) should be used-value-equivalent to 1ms assert_equals: abs(-1ms) and 1ms serialize to the same thing in used values. expected "0.001s" but got "0s" +FAIL abs(1deg) should be used-value-equivalent to 1deg Cannot read properties of undefined (reading 'split') +FAIL abs(1grad) should be used-value-equivalent to 1grad Cannot read properties of undefined (reading 'split') +FAIL abs(1rad) should be used-value-equivalent to 1rad Cannot read properties of undefined (reading 'split') +FAIL abs(1turn) should be used-value-equivalent to 1turn Cannot read properties of undefined (reading 'split') +FAIL abs(-1deg) should be used-value-equivalent to 1deg Cannot read properties of undefined (reading 'split') +FAIL abs(-1grad) should be used-value-equivalent to 1grad Cannot read properties of undefined (reading 'split') +FAIL abs(-1rad) should be used-value-equivalent to 1rad Cannot read properties of undefined (reading 'split') +FAIL abs(-1turn) should be used-value-equivalent to 1turn Cannot read properties of undefined (reading 'split') +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/css/css-values/round-mod-rem-computed-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/css/css-values/round-mod-rem-computed-expected.txt new file mode 100644 index 0000000..605af99d --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/external/wpt/css/css-values/round-mod-rem-computed-expected.txt
@@ -0,0 +1,93 @@ +This is a testharness.js-based test. +Found 89 tests; 6 PASS, 83 FAIL, 0 TIMEOUT, 0 NOTRUN. +FAIL round(10,10) should be used-value-equivalent to 10 assert_equals: round(10,10) and 10 serialize to the same thing in used values. expected "matrix(10, 0, 0, 10, 0, 0)" but got "none" +FAIL mod(1,1) should be used-value-equivalent to 0 assert_equals: mod(1,1) and 0 serialize to the same thing in used values. expected "matrix(0, 0, 0, 0, 0, 0)" but got "none" +FAIL rem(1,1) should be used-value-equivalent to 0 assert_equals: rem(1,1) and 0 serialize to the same thing in used values. expected "matrix(0, 0, 0, 0, 0, 0)" but got "none" +FAIL calc(round(100,10)) should be used-value-equivalent to 100 assert_equals: calc(round(100,10)) and 100 serialize to the same thing in used values. expected "matrix(100, 0, 0, 100, 0, 0)" but got "none" +FAIL calc(round(up, 101,10)) should be used-value-equivalent to 110 assert_equals: calc(round(up, 101,10)) and 110 serialize to the same thing in used values. expected "matrix(110, 0, 0, 110, 0, 0)" but got "none" +FAIL calc(round(down, 106,10)) should be used-value-equivalent to 100 assert_equals: calc(round(down, 106,10)) and 100 serialize to the same thing in used values. expected "matrix(100, 0, 0, 100, 0, 0)" but got "none" +FAIL calc(round(to-zero,105, 10)) should be used-value-equivalent to 100 assert_equals: calc(round(to-zero,105, 10)) and 100 serialize to the same thing in used values. expected "matrix(100, 0, 0, 100, 0, 0)" but got "none" +FAIL calc(round(to-zero,-105, 10)) should be used-value-equivalent to 100 assert_equals: calc(round(to-zero,-105, 10)) and 100 serialize to the same thing in used values. expected "matrix(100, 0, 0, 100, 0, 0)" but got "none" +FAIL calc(round(-100,10)) should be used-value-equivalent to -100 assert_equals: calc(round(-100,10)) and -100 serialize to the same thing in used values. expected "matrix(-100, 0, 0, -100, 0, 0)" but got "none" +FAIL calc(round(up, -103,10)) should be used-value-equivalent to -100 assert_equals: calc(round(up, -103,10)) and -100 serialize to the same thing in used values. expected "matrix(-100, 0, 0, -100, 0, 0)" but got "none" +FAIL mod(18,5) should be used-value-equivalent to 3 assert_equals: mod(18,5) and 3 serialize to the same thing in used values. expected "matrix(3, 0, 0, 3, 0, 0)" but got "none" +FAIL rem(18,5) should be used-value-equivalent to 3 assert_equals: rem(18,5) and 3 serialize to the same thing in used values. expected "matrix(3, 0, 0, 3, 0, 0)" but got "none" +FAIL mod(-140,-90) should be used-value-equivalent to -50 assert_equals: mod(-140,-90) and -50 serialize to the same thing in used values. expected "matrix(-50, 0, 0, -50, 0, 0)" but got "none" +FAIL mod(-18,5) should be used-value-equivalent to 2 assert_equals: mod(-18,5) and 2 serialize to the same thing in used values. expected "matrix(2, 0, 0, 2, 0, 0)" but got "none" +FAIL rem(-18,5) should be used-value-equivalent to -3 assert_equals: rem(-18,5) and -3 serialize to the same thing in used values. expected "matrix(-3, 0, 0, -3, 0, 0)" but got "none" +FAIL mod(140,-90) should be used-value-equivalent to -40 assert_equals: mod(140,-90) and -40 serialize to the same thing in used values. expected "matrix(-40, 0, 0, -40, 0, 0)" but got "none" +FAIL rem(140,-90) should be used-value-equivalent to 50 assert_equals: rem(140,-90) and 50 serialize to the same thing in used values. expected "matrix(50, 0, 0, 50, 0, 0)" but got "none" +FAIL calc(round(round(100,10), 10)) should be used-value-equivalent to 100 assert_equals: calc(round(round(100,10), 10)) and 100 serialize to the same thing in used values. expected "matrix(100, 0, 0, 100, 0, 0)" but got "none" +FAIL calc(round(up, round(100,10) + 1,10)) should be used-value-equivalent to 110 assert_equals: calc(round(up, round(100,10) + 1,10)) and 110 serialize to the same thing in used values. expected "matrix(110, 0, 0, 110, 0, 0)" but got "none" +FAIL calc(round(down, round(100,10) + 2 * 3,10)) should be used-value-equivalent to 100 assert_equals: calc(round(down, round(100,10) + 2 * 3,10)) and 100 serialize to the same thing in used values. expected "matrix(100, 0, 0, 100, 0, 0)" but got "none" +FAIL calc(round(to-zero,round(100,10) * 2 - 95, 10)) should be used-value-equivalent to 100 assert_equals: calc(round(to-zero,round(100,10) * 2 - 95, 10)) and 100 serialize to the same thing in used values. expected "matrix(100, 0, 0, 100, 0, 0)" but got "none" +FAIL calc(round(round(100,10)* -1,10)) should be used-value-equivalent to -100 assert_equals: calc(round(round(100,10)* -1,10)) and -100 serialize to the same thing in used values. expected "matrix(-100, 0, 0, -100, 0, 0)" but got "none" +FAIL calc(round(up, -103 + -103 / -103 - 1,10)) should be used-value-equivalent to -100 assert_equals: calc(round(up, -103 + -103 / -103 - 1,10)) and -100 serialize to the same thing in used values. expected "matrix(-100, 0, 0, -100, 0, 0)" but got "none" +FAIL calc(mod(18,5) * 2 + mod(17,5)) should be used-value-equivalent to 8 assert_equals: calc(mod(18,5) * 2 + mod(17,5)) and 8 serialize to the same thing in used values. expected "matrix(8, 0, 0, 8, 0, 0)" but got "none" +FAIL calc(rem(mod(18,5),5)) should be used-value-equivalent to 3 assert_equals: calc(rem(mod(18,5),5)) and 3 serialize to the same thing in used values. expected "matrix(3, 0, 0, 3, 0, 0)" but got "none" +FAIL calc(rem(mod(18,5),mod(17,5))) should be used-value-equivalent to 1 assert_equals: calc(rem(mod(18,5),mod(17,5))) and 1 serialize to the same thing in used values. expected "matrix(1, 0, 0, 1, 0, 0)" but got "none" +FAIL calc(mod(-140,-90)) should be used-value-equivalent to -50 assert_equals: calc(mod(-140,-90)) and -50 serialize to the same thing in used values. expected "matrix(-50, 0, 0, -50, 0, 0)" but got "none" +FAIL calc(mod(rem(1,18)* -1,5)) should be used-value-equivalent to -1 assert_equals: calc(mod(rem(1,18)* -1,5)) and -1 serialize to the same thing in used values. expected "matrix(-1, 0, 0, -1, 0, 0)" but got "none" +FAIL round(10px,6px) should be used-value-equivalent to 12px assert_equals: round(10px,6px) and 12px serialize to the same thing in used values. expected "12px" but got "0px" +FAIL round(10cm,6cm) should be used-value-equivalent to 12cm assert_equals: round(10cm,6cm) and 12cm serialize to the same thing in used values. expected "453.543px" but got "0px" +FAIL round(10mm,6mm) should be used-value-equivalent to 12mm assert_equals: round(10mm,6mm) and 12mm serialize to the same thing in used values. expected "45.3543px" but got "0px" +FAIL round(10Q, 6Q) should be used-value-equivalent to 12Q assert_equals: round(10Q, 6Q) and 12Q serialize to the same thing in used values. expected "11.3386px" but got "0px" +FAIL round(10in,6in) should be used-value-equivalent to 12in assert_equals: round(10in,6in) and 12in serialize to the same thing in used values. expected "1152px" but got "0px" +FAIL round(10pc,6pc) should be used-value-equivalent to 12pc assert_equals: round(10pc,6pc) and 12pc serialize to the same thing in used values. expected "192px" but got "0px" +FAIL round(10pt,6pt) should be used-value-equivalent to 12pt assert_equals: round(10pt,6pt) and 12pt serialize to the same thing in used values. expected "16px" but got "0px" +FAIL round(10em,6em) should be used-value-equivalent to 12em assert_equals: round(10em,6em) and 12em serialize to the same thing in used values. expected "192px" but got "0px" +FAIL round(10ex,6ex) should be used-value-equivalent to 12ex assert_equals: round(10ex,6ex) and 12ex serialize to the same thing in used values. expected "86.1562px" but got "0px" +FAIL round(10ch,6ch) should be used-value-equivalent to 12ch assert_equals: round(10ch,6ch) and 12ch serialize to the same thing in used values. expected "96px" but got "0px" +FAIL round(10rem,6rem) should be used-value-equivalent to 12rem assert_equals: round(10rem,6rem) and 12rem serialize to the same thing in used values. expected "192px" but got "0px" +FAIL round(10vh,6vh) should be used-value-equivalent to 12vh assert_equals: round(10vh,6vh) and 12vh serialize to the same thing in used values. expected "72px" but got "0px" +FAIL round(10vw,6vw) should be used-value-equivalent to 12vw assert_equals: round(10vw,6vw) and 12vw serialize to the same thing in used values. expected "96px" but got "0px" +FAIL round(10vmin,6vmin) should be used-value-equivalent to 12vmin assert_equals: round(10vmin,6vmin) and 12vmin serialize to the same thing in used values. expected "72px" but got "0px" +FAIL round(10vmax,6vmax) should be used-value-equivalent to 12vmax assert_equals: round(10vmax,6vmax) and 12vmax serialize to the same thing in used values. expected "96px" but got "0px" +PASS round(10s,6s) should be used-value-equivalent to 12s +PASS round(10ms,6ms) should be used-value-equivalent to 12ms +FAIL round(10deg,6deg) should be used-value-equivalent to 12deg Cannot read properties of undefined (reading 'split') +FAIL round(10grad,6grad) should be used-value-equivalent to 12grad Cannot read properties of undefined (reading 'split') +FAIL round(10rad,6rad) should be used-value-equivalent to 12rad Cannot read properties of undefined (reading 'split') +FAIL round(10turn,6turn) should be used-value-equivalent to 12turn Cannot read properties of undefined (reading 'split') +FAIL mod(10px,6px) should be used-value-equivalent to 4px assert_equals: mod(10px,6px) and 4px serialize to the same thing in used values. expected "4px" but got "0px" +FAIL mod(10cm,6cm) should be used-value-equivalent to 4cm assert_equals: mod(10cm,6cm) and 4cm serialize to the same thing in used values. expected "151.181px" but got "0px" +FAIL mod(10mm,6mm) should be used-value-equivalent to 4mm assert_equals: mod(10mm,6mm) and 4mm serialize to the same thing in used values. expected "15.1181px" but got "0px" +FAIL mod(10Q, 6Q) should be used-value-equivalent to 4Q assert_equals: mod(10Q, 6Q) and 4Q serialize to the same thing in used values. expected "3.77953px" but got "0px" +FAIL mod(10in,6in) should be used-value-equivalent to 4in assert_equals: mod(10in,6in) and 4in serialize to the same thing in used values. expected "384px" but got "0px" +FAIL mod(10pc,6pc) should be used-value-equivalent to 4pc assert_equals: mod(10pc,6pc) and 4pc serialize to the same thing in used values. expected "64px" but got "0px" +FAIL mod(10em,6em) should be used-value-equivalent to 4em assert_equals: mod(10em,6em) and 4em serialize to the same thing in used values. expected "64px" but got "0px" +FAIL mod(10ex,6ex) should be used-value-equivalent to 4ex assert_equals: mod(10ex,6ex) and 4ex serialize to the same thing in used values. expected "28.7188px" but got "0px" +FAIL mod(10ch,6ch) should be used-value-equivalent to 4ch assert_equals: mod(10ch,6ch) and 4ch serialize to the same thing in used values. expected "32px" but got "0px" +FAIL mod(10rem,6rem) should be used-value-equivalent to 4rem assert_equals: mod(10rem,6rem) and 4rem serialize to the same thing in used values. expected "64px" but got "0px" +FAIL mod(10vh,6vh) should be used-value-equivalent to 4vh assert_equals: mod(10vh,6vh) and 4vh serialize to the same thing in used values. expected "24px" but got "0px" +FAIL mod(10vw,6vw) should be used-value-equivalent to 4vw assert_equals: mod(10vw,6vw) and 4vw serialize to the same thing in used values. expected "32px" but got "0px" +FAIL mod(10vmin,6vmin) should be used-value-equivalent to 4vmin assert_equals: mod(10vmin,6vmin) and 4vmin serialize to the same thing in used values. expected "24px" but got "0px" +FAIL mod(10vmax,6vmax) should be used-value-equivalent to 4vmax assert_equals: mod(10vmax,6vmax) and 4vmax serialize to the same thing in used values. expected "32px" but got "0px" +PASS mod(10s,6s) should be used-value-equivalent to 4s +PASS mod(10ms,6ms) should be used-value-equivalent to 4ms +FAIL mod(10deg,6deg) should be used-value-equivalent to 4deg Cannot read properties of undefined (reading 'split') +FAIL mod(10grad,6grad) should be used-value-equivalent to 4grad Cannot read properties of undefined (reading 'split') +FAIL mod(10rad,6rad) should be used-value-equivalent to 4rad Cannot read properties of undefined (reading 'split') +FAIL mod(10turn,6turn) should be used-value-equivalent to 4turn Cannot read properties of undefined (reading 'split') +FAIL rem(10px,6px) should be used-value-equivalent to 4px assert_equals: rem(10px,6px) and 4px serialize to the same thing in used values. expected "4px" but got "0px" +FAIL rem(10cm,6cm) should be used-value-equivalent to 4cm assert_equals: rem(10cm,6cm) and 4cm serialize to the same thing in used values. expected "151.181px" but got "0px" +FAIL rem(10mm,6mm) should be used-value-equivalent to 4mm assert_equals: rem(10mm,6mm) and 4mm serialize to the same thing in used values. expected "15.1181px" but got "0px" +FAIL rem(10Q, 6Q) should be used-value-equivalent to 4Q assert_equals: rem(10Q, 6Q) and 4Q serialize to the same thing in used values. expected "3.77953px" but got "0px" +FAIL rem(10in,6in) should be used-value-equivalent to 4in assert_equals: rem(10in,6in) and 4in serialize to the same thing in used values. expected "384px" but got "0px" +FAIL rem(10pc,6pc) should be used-value-equivalent to 4pc assert_equals: rem(10pc,6pc) and 4pc serialize to the same thing in used values. expected "64px" but got "0px" +FAIL rem(10em,6em) should be used-value-equivalent to 4em assert_equals: rem(10em,6em) and 4em serialize to the same thing in used values. expected "64px" but got "0px" +FAIL rem(10ex,6ex) should be used-value-equivalent to 4ex assert_equals: rem(10ex,6ex) and 4ex serialize to the same thing in used values. expected "28.7188px" but got "0px" +FAIL rem(10ch,6ch) should be used-value-equivalent to 4ch assert_equals: rem(10ch,6ch) and 4ch serialize to the same thing in used values. expected "32px" but got "0px" +FAIL rem(10rem,6rem) should be used-value-equivalent to 4rem assert_equals: rem(10rem,6rem) and 4rem serialize to the same thing in used values. expected "64px" but got "0px" +FAIL rem(10vh,6vh) should be used-value-equivalent to 4vh assert_equals: rem(10vh,6vh) and 4vh serialize to the same thing in used values. expected "24px" but got "0px" +FAIL rem(10vw,6vw) should be used-value-equivalent to 4vw assert_equals: rem(10vw,6vw) and 4vw serialize to the same thing in used values. expected "32px" but got "0px" +FAIL rem(10vmin,6vmin) should be used-value-equivalent to 4vmin assert_equals: rem(10vmin,6vmin) and 4vmin serialize to the same thing in used values. expected "24px" but got "0px" +FAIL rem(10vmax,6vmax) should be used-value-equivalent to 4vmax assert_equals: rem(10vmax,6vmax) and 4vmax serialize to the same thing in used values. expected "32px" but got "0px" +PASS rem(10s,6s) should be used-value-equivalent to 4s +PASS rem(10ms,6ms) should be used-value-equivalent to 4ms +FAIL rem(10deg,6deg) should be used-value-equivalent to 4deg Cannot read properties of undefined (reading 'split') +FAIL rem(10grad,6grad) should be used-value-equivalent to 4grad Cannot read properties of undefined (reading 'split') +FAIL rem(10rad,6rad) should be used-value-equivalent to 4rad Cannot read properties of undefined (reading 'split') +FAIL rem(10turn,6turn) should be used-value-equivalent to 4turn Cannot read properties of undefined (reading 'split') +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/css/css-values/signs-abs-computed-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/css/css-values/signs-abs-computed-expected.txt new file mode 100644 index 0000000..111e9ed --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/external/wpt/css/css-values/signs-abs-computed-expected.txt
@@ -0,0 +1,146 @@ +This is a testharness.js-based test. +Found 142 tests; 87 PASS, 55 FAIL, 0 TIMEOUT, 0 NOTRUN. +FAIL abs(1) should be used-value-equivalent to 1 assert_equals: abs(1) and 1 serialize to the same thing in used values. expected "matrix(1, 0, 0, 1, 0, 0)" but got "none" +FAIL sign(1) should be used-value-equivalent to 1 assert_equals: sign(1) and 1 serialize to the same thing in used values. expected "matrix(1, 0, 0, 1, 0, 0)" but got "none" +FAIL abs(-1) should be used-value-equivalent to 1 assert_equals: abs(-1) and 1 serialize to the same thing in used values. expected "matrix(1, 0, 0, 1, 0, 0)" but got "none" +FAIL sign(-1) should be used-value-equivalent to -1 assert_equals: sign(-1) and -1 serialize to the same thing in used values. expected "matrix(-1, 0, 0, -1, 0, 0)" but got "none" +PASS abs(sign(1)) should be used-value-equivalent to 1 +PASS abs(sign(sign(1))) should be used-value-equivalent to 1 +PASS sign(sign(sign(1) + sign(1))) should be used-value-equivalent to 1 +FAIL calc(abs(0.1 + 0.2) + 0.05) should be used-value-equivalent to 0.35 Cannot read properties of undefined (reading 'split') +FAIL calc(sign(0.1 + 0.2) - 0.05) should be used-value-equivalent to 0.95 Cannot read properties of undefined (reading 'split') +FAIL calc(abs(0.1 + 0.2) * 2) should be used-value-equivalent to 0.6 Cannot read properties of undefined (reading 'split') +FAIL calc(abs(sign(0.1) + 0.2) / 2) should be used-value-equivalent to 0.6 Cannot read properties of undefined (reading 'split') +FAIL calc(abs(0.1 + 0.2) * -2) should be used-value-equivalent to -0.6 Cannot read properties of undefined (reading 'split') +FAIL calc(sign(0.1 - 0.2) - 0.05) should be used-value-equivalent to -1.05 Cannot read properties of undefined (reading 'split') +FAIL calc(sign(1) + sign(1) - 0.05) should be used-value-equivalent to 1.95 Cannot read properties of undefined (reading 'split') +FAIL calc(sign(-0)) should be used-value-equivalent to -0 assert_equals: calc(sign(-0)) and -0 serialize to the same thing in used values. expected "matrix(0, 0, 0, 0, 0, 0)" but got "none" +FAIL calc(sign(0)) should be used-value-equivalent to 0 assert_equals: calc(sign(0)) and 0 serialize to the same thing in used values. expected "matrix(0, 0, 0, 0, 0, 0)" but got "none" +PASS sign(1px) should be used-value-equivalent to 1 +PASS sign(1cm) should be used-value-equivalent to 1 +PASS sign(1mm) should be used-value-equivalent to 1 +PASS sign(1Q) should be used-value-equivalent to 1 +PASS sign(1in) should be used-value-equivalent to 1 +PASS sign(1pc) should be used-value-equivalent to 1 +PASS sign(1pt) should be used-value-equivalent to 1 +PASS sign(1em) should be used-value-equivalent to 1 +PASS sign(1ex) should be used-value-equivalent to 1 +PASS sign(1ch) should be used-value-equivalent to 1 +PASS sign(1rem) should be used-value-equivalent to 1 +PASS sign(1vh) should be used-value-equivalent to 1 +PASS sign(1vw) should be used-value-equivalent to 1 +PASS sign(1vmin) should be used-value-equivalent to 1 +PASS sign(1vmax) should be used-value-equivalent to 1 +PASS sign(-1px) should be used-value-equivalent to -1 +PASS sign(-1cm) should be used-value-equivalent to -1 +PASS sign(-1mm) should be used-value-equivalent to -1 +PASS sign(-1Q) should be used-value-equivalent to -1 +PASS sign(-1in) should be used-value-equivalent to -1 +PASS sign(-1pc) should be used-value-equivalent to -1 +PASS sign(-1pt) should be used-value-equivalent to -1 +PASS sign(-1em) should be used-value-equivalent to -1 +PASS sign(-1ex) should be used-value-equivalent to -1 +PASS sign(-1ch) should be used-value-equivalent to -1 +PASS sign(-1rem) should be used-value-equivalent to -1 +PASS sign(-1vh) should be used-value-equivalent to -1 +PASS sign(-1vw) should be used-value-equivalent to -1 +PASS sign(-1vmin) should be used-value-equivalent to -1 +PASS sign(-1vmax) should be used-value-equivalent to -1 +PASS sign(1s) should be used-value-equivalent to 1 +PASS sign(1ms) should be used-value-equivalent to 1 +PASS sign(-1s) should be used-value-equivalent to -1 +PASS sign(-1ms) should be used-value-equivalent to -1 +PASS sign(1deg) should be used-value-equivalent to 1 +PASS sign(1grad) should be used-value-equivalent to 1 +PASS sign(1rad) should be used-value-equivalent to 1 +PASS sign(1turn) should be used-value-equivalent to 1 +PASS sign(-1deg) should be used-value-equivalent to -1 +PASS sign(-1grad) should be used-value-equivalent to -1 +PASS sign(-1rad) should be used-value-equivalent to -1 +PASS sign(-1turn) should be used-value-equivalent to -1 +PASS sign(0px) should be used-value-equivalent to 0 +PASS sign(0cm) should be used-value-equivalent to 0 +PASS sign(0mm) should be used-value-equivalent to 0 +PASS sign(0Q) should be used-value-equivalent to 0 +PASS sign(0in) should be used-value-equivalent to 0 +PASS sign(0pc) should be used-value-equivalent to 0 +PASS sign(0pt) should be used-value-equivalent to 0 +PASS sign(0em) should be used-value-equivalent to 0 +PASS sign(0ex) should be used-value-equivalent to 0 +PASS sign(0ch) should be used-value-equivalent to 0 +PASS sign(0rem) should be used-value-equivalent to 0 +PASS sign(0vh) should be used-value-equivalent to 0 +PASS sign(0vw) should be used-value-equivalent to 0 +PASS sign(0vmin) should be used-value-equivalent to 0 +PASS sign(0vmax) should be used-value-equivalent to 0 +PASS sign(-0px) should be used-value-equivalent to -0 +PASS sign(-0cm) should be used-value-equivalent to -0 +PASS sign(-0mm) should be used-value-equivalent to -0 +PASS sign(-0Q) should be used-value-equivalent to -0 +PASS sign(-0in) should be used-value-equivalent to -0 +PASS sign(-0pc) should be used-value-equivalent to -0 +PASS sign(-0pt) should be used-value-equivalent to -0 +PASS sign(-0em) should be used-value-equivalent to -0 +PASS sign(-0ex) should be used-value-equivalent to -0 +PASS sign(-0ch) should be used-value-equivalent to -0 +PASS sign(-0rem) should be used-value-equivalent to -0 +PASS sign(-0vh) should be used-value-equivalent to -0 +PASS sign(-0vw) should be used-value-equivalent to -0 +PASS sign(-0vmin) should be used-value-equivalent to -0 +PASS sign(-0vmax) should be used-value-equivalent to -0 +PASS sign(0s) should be used-value-equivalent to 0 +PASS sign(0ms) should be used-value-equivalent to 0 +PASS sign(-0s) should be used-value-equivalent to 0 +PASS sign(-0ms) should be used-value-equivalent to 0 +PASS sign(0deg) should be used-value-equivalent to 0 +PASS sign(0grad) should be used-value-equivalent to 0 +PASS sign(0rad) should be used-value-equivalent to 0 +PASS sign(0turn) should be used-value-equivalent to 0 +PASS sign(-0deg) should be used-value-equivalent to -0 +PASS sign(-0grad) should be used-value-equivalent to -0 +PASS sign(-0rad) should be used-value-equivalent to -0 +PASS sign(-0turn) should be used-value-equivalent to -0 +FAIL abs(1px) should be used-value-equivalent to 1px assert_equals: abs(1px) and 1px serialize to the same thing in used values. expected "1px" but got "0px" +FAIL abs(1cm) should be used-value-equivalent to 1cm assert_equals: abs(1cm) and 1cm serialize to the same thing in used values. expected "37.7953px" but got "0px" +FAIL abs(1mm) should be used-value-equivalent to 1mm assert_equals: abs(1mm) and 1mm serialize to the same thing in used values. expected "3.77953px" but got "0px" +FAIL abs(1Q) should be used-value-equivalent to 1Q assert_equals: abs(1Q) and 1Q serialize to the same thing in used values. expected "0.944882px" but got "0px" +FAIL abs(1in) should be used-value-equivalent to 1in assert_equals: abs(1in) and 1in serialize to the same thing in used values. expected "96px" but got "0px" +FAIL abs(1pc) should be used-value-equivalent to 1pc assert_equals: abs(1pc) and 1pc serialize to the same thing in used values. expected "16px" but got "0px" +FAIL abs(1pt) should be used-value-equivalent to 1pt assert_equals: abs(1pt) and 1pt serialize to the same thing in used values. expected "1.33333px" but got "0px" +FAIL abs(1em) should be used-value-equivalent to 1em assert_equals: abs(1em) and 1em serialize to the same thing in used values. expected "16px" but got "0px" +FAIL abs(1ex) should be used-value-equivalent to 1ex assert_equals: abs(1ex) and 1ex serialize to the same thing in used values. expected "7.17969px" but got "0px" +FAIL abs(1ch) should be used-value-equivalent to 1ch assert_equals: abs(1ch) and 1ch serialize to the same thing in used values. expected "8px" but got "0px" +FAIL abs(1rem) should be used-value-equivalent to 1rem assert_equals: abs(1rem) and 1rem serialize to the same thing in used values. expected "16px" but got "0px" +FAIL abs(1vh) should be used-value-equivalent to 1vh assert_equals: abs(1vh) and 1vh serialize to the same thing in used values. expected "6px" but got "0px" +FAIL abs(1vw) should be used-value-equivalent to 1vw assert_equals: abs(1vw) and 1vw serialize to the same thing in used values. expected "8px" but got "0px" +FAIL abs(1vmin) should be used-value-equivalent to 1vmin assert_equals: abs(1vmin) and 1vmin serialize to the same thing in used values. expected "6px" but got "0px" +FAIL abs(1vmax) should be used-value-equivalent to 1vmax assert_equals: abs(1vmax) and 1vmax serialize to the same thing in used values. expected "8px" but got "0px" +FAIL abs(-1px) should be used-value-equivalent to 1px assert_equals: abs(-1px) and 1px serialize to the same thing in used values. expected "1px" but got "0px" +FAIL abs(-1cm) should be used-value-equivalent to 1cm assert_equals: abs(-1cm) and 1cm serialize to the same thing in used values. expected "37.7953px" but got "0px" +FAIL abs(-1mm) should be used-value-equivalent to 1mm assert_equals: abs(-1mm) and 1mm serialize to the same thing in used values. expected "3.77953px" but got "0px" +FAIL abs(-1Q) should be used-value-equivalent to 1Q assert_equals: abs(-1Q) and 1Q serialize to the same thing in used values. expected "0.944882px" but got "0px" +FAIL abs(-1in) should be used-value-equivalent to 1in assert_equals: abs(-1in) and 1in serialize to the same thing in used values. expected "96px" but got "0px" +FAIL abs(-1pc) should be used-value-equivalent to 1pc assert_equals: abs(-1pc) and 1pc serialize to the same thing in used values. expected "16px" but got "0px" +FAIL abs(-1pt) should be used-value-equivalent to 1pt assert_equals: abs(-1pt) and 1pt serialize to the same thing in used values. expected "1.33333px" but got "0px" +FAIL abs(-1em) should be used-value-equivalent to 1em assert_equals: abs(-1em) and 1em serialize to the same thing in used values. expected "16px" but got "0px" +FAIL abs(-1ex) should be used-value-equivalent to 1ex assert_equals: abs(-1ex) and 1ex serialize to the same thing in used values. expected "7.17969px" but got "0px" +FAIL abs(-1ch) should be used-value-equivalent to 1ch assert_equals: abs(-1ch) and 1ch serialize to the same thing in used values. expected "8px" but got "0px" +FAIL abs(-1rem) should be used-value-equivalent to 1rem assert_equals: abs(-1rem) and 1rem serialize to the same thing in used values. expected "16px" but got "0px" +FAIL abs(-1vh) should be used-value-equivalent to 1vh assert_equals: abs(-1vh) and 1vh serialize to the same thing in used values. expected "6px" but got "0px" +FAIL abs(-1vw) should be used-value-equivalent to 1vw assert_equals: abs(-1vw) and 1vw serialize to the same thing in used values. expected "8px" but got "0px" +FAIL abs(-1vmin) should be used-value-equivalent to 1vmin assert_equals: abs(-1vmin) and 1vmin serialize to the same thing in used values. expected "6px" but got "0px" +FAIL abs(-1vmax) should be used-value-equivalent to 1vmax assert_equals: abs(-1vmax) and 1vmax serialize to the same thing in used values. expected "8px" but got "0px" +FAIL abs(1s) should be used-value-equivalent to 1s assert_equals: abs(1s) and 1s serialize to the same thing in used values. expected "1s" but got "0s" +FAIL abs(1ms) should be used-value-equivalent to 1ms assert_equals: abs(1ms) and 1ms serialize to the same thing in used values. expected "0.001s" but got "0s" +FAIL abs(-1s) should be used-value-equivalent to 1s assert_equals: abs(-1s) and 1s serialize to the same thing in used values. expected "1s" but got "0s" +FAIL abs(-1ms) should be used-value-equivalent to 1ms assert_equals: abs(-1ms) and 1ms serialize to the same thing in used values. expected "0.001s" but got "0s" +FAIL abs(1deg) should be used-value-equivalent to 1deg Cannot read properties of undefined (reading 'split') +FAIL abs(1grad) should be used-value-equivalent to 1grad Cannot read properties of undefined (reading 'split') +FAIL abs(1rad) should be used-value-equivalent to 1rad Cannot read properties of undefined (reading 'split') +FAIL abs(1turn) should be used-value-equivalent to 1turn Cannot read properties of undefined (reading 'split') +FAIL abs(-1deg) should be used-value-equivalent to 1deg Cannot read properties of undefined (reading 'split') +FAIL abs(-1grad) should be used-value-equivalent to 1grad Cannot read properties of undefined (reading 'split') +FAIL abs(-1rad) should be used-value-equivalent to 1rad Cannot read properties of undefined (reading 'split') +FAIL abs(-1turn) should be used-value-equivalent to 1turn Cannot read properties of undefined (reading 'split') +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/css/css-values/round-mod-rem-computed-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/css/css-values/round-mod-rem-computed-expected.txt new file mode 100644 index 0000000..7de46f0 --- /dev/null +++ b/third_party/blink/web_tests/platform/win/external/wpt/css/css-values/round-mod-rem-computed-expected.txt
@@ -0,0 +1,93 @@ +This is a testharness.js-based test. +Found 89 tests; 6 PASS, 83 FAIL, 0 TIMEOUT, 0 NOTRUN. +FAIL round(10,10) should be used-value-equivalent to 10 assert_equals: round(10,10) and 10 serialize to the same thing in used values. expected "matrix(10, 0, 0, 10, 0, 0)" but got "none" +FAIL mod(1,1) should be used-value-equivalent to 0 assert_equals: mod(1,1) and 0 serialize to the same thing in used values. expected "matrix(0, 0, 0, 0, 0, 0)" but got "none" +FAIL rem(1,1) should be used-value-equivalent to 0 assert_equals: rem(1,1) and 0 serialize to the same thing in used values. expected "matrix(0, 0, 0, 0, 0, 0)" but got "none" +FAIL calc(round(100,10)) should be used-value-equivalent to 100 assert_equals: calc(round(100,10)) and 100 serialize to the same thing in used values. expected "matrix(100, 0, 0, 100, 0, 0)" but got "none" +FAIL calc(round(up, 101,10)) should be used-value-equivalent to 110 assert_equals: calc(round(up, 101,10)) and 110 serialize to the same thing in used values. expected "matrix(110, 0, 0, 110, 0, 0)" but got "none" +FAIL calc(round(down, 106,10)) should be used-value-equivalent to 100 assert_equals: calc(round(down, 106,10)) and 100 serialize to the same thing in used values. expected "matrix(100, 0, 0, 100, 0, 0)" but got "none" +FAIL calc(round(to-zero,105, 10)) should be used-value-equivalent to 100 assert_equals: calc(round(to-zero,105, 10)) and 100 serialize to the same thing in used values. expected "matrix(100, 0, 0, 100, 0, 0)" but got "none" +FAIL calc(round(to-zero,-105, 10)) should be used-value-equivalent to 100 assert_equals: calc(round(to-zero,-105, 10)) and 100 serialize to the same thing in used values. expected "matrix(100, 0, 0, 100, 0, 0)" but got "none" +FAIL calc(round(-100,10)) should be used-value-equivalent to -100 assert_equals: calc(round(-100,10)) and -100 serialize to the same thing in used values. expected "matrix(-100, 0, 0, -100, 0, 0)" but got "none" +FAIL calc(round(up, -103,10)) should be used-value-equivalent to -100 assert_equals: calc(round(up, -103,10)) and -100 serialize to the same thing in used values. expected "matrix(-100, 0, 0, -100, 0, 0)" but got "none" +FAIL mod(18,5) should be used-value-equivalent to 3 assert_equals: mod(18,5) and 3 serialize to the same thing in used values. expected "matrix(3, 0, 0, 3, 0, 0)" but got "none" +FAIL rem(18,5) should be used-value-equivalent to 3 assert_equals: rem(18,5) and 3 serialize to the same thing in used values. expected "matrix(3, 0, 0, 3, 0, 0)" but got "none" +FAIL mod(-140,-90) should be used-value-equivalent to -50 assert_equals: mod(-140,-90) and -50 serialize to the same thing in used values. expected "matrix(-50, 0, 0, -50, 0, 0)" but got "none" +FAIL mod(-18,5) should be used-value-equivalent to 2 assert_equals: mod(-18,5) and 2 serialize to the same thing in used values. expected "matrix(2, 0, 0, 2, 0, 0)" but got "none" +FAIL rem(-18,5) should be used-value-equivalent to -3 assert_equals: rem(-18,5) and -3 serialize to the same thing in used values. expected "matrix(-3, 0, 0, -3, 0, 0)" but got "none" +FAIL mod(140,-90) should be used-value-equivalent to -40 assert_equals: mod(140,-90) and -40 serialize to the same thing in used values. expected "matrix(-40, 0, 0, -40, 0, 0)" but got "none" +FAIL rem(140,-90) should be used-value-equivalent to 50 assert_equals: rem(140,-90) and 50 serialize to the same thing in used values. expected "matrix(50, 0, 0, 50, 0, 0)" but got "none" +FAIL calc(round(round(100,10), 10)) should be used-value-equivalent to 100 assert_equals: calc(round(round(100,10), 10)) and 100 serialize to the same thing in used values. expected "matrix(100, 0, 0, 100, 0, 0)" but got "none" +FAIL calc(round(up, round(100,10) + 1,10)) should be used-value-equivalent to 110 assert_equals: calc(round(up, round(100,10) + 1,10)) and 110 serialize to the same thing in used values. expected "matrix(110, 0, 0, 110, 0, 0)" but got "none" +FAIL calc(round(down, round(100,10) + 2 * 3,10)) should be used-value-equivalent to 100 assert_equals: calc(round(down, round(100,10) + 2 * 3,10)) and 100 serialize to the same thing in used values. expected "matrix(100, 0, 0, 100, 0, 0)" but got "none" +FAIL calc(round(to-zero,round(100,10) * 2 - 95, 10)) should be used-value-equivalent to 100 assert_equals: calc(round(to-zero,round(100,10) * 2 - 95, 10)) and 100 serialize to the same thing in used values. expected "matrix(100, 0, 0, 100, 0, 0)" but got "none" +FAIL calc(round(round(100,10)* -1,10)) should be used-value-equivalent to -100 assert_equals: calc(round(round(100,10)* -1,10)) and -100 serialize to the same thing in used values. expected "matrix(-100, 0, 0, -100, 0, 0)" but got "none" +FAIL calc(round(up, -103 + -103 / -103 - 1,10)) should be used-value-equivalent to -100 assert_equals: calc(round(up, -103 + -103 / -103 - 1,10)) and -100 serialize to the same thing in used values. expected "matrix(-100, 0, 0, -100, 0, 0)" but got "none" +FAIL calc(mod(18,5) * 2 + mod(17,5)) should be used-value-equivalent to 8 assert_equals: calc(mod(18,5) * 2 + mod(17,5)) and 8 serialize to the same thing in used values. expected "matrix(8, 0, 0, 8, 0, 0)" but got "none" +FAIL calc(rem(mod(18,5),5)) should be used-value-equivalent to 3 assert_equals: calc(rem(mod(18,5),5)) and 3 serialize to the same thing in used values. expected "matrix(3, 0, 0, 3, 0, 0)" but got "none" +FAIL calc(rem(mod(18,5),mod(17,5))) should be used-value-equivalent to 1 assert_equals: calc(rem(mod(18,5),mod(17,5))) and 1 serialize to the same thing in used values. expected "matrix(1, 0, 0, 1, 0, 0)" but got "none" +FAIL calc(mod(-140,-90)) should be used-value-equivalent to -50 assert_equals: calc(mod(-140,-90)) and -50 serialize to the same thing in used values. expected "matrix(-50, 0, 0, -50, 0, 0)" but got "none" +FAIL calc(mod(rem(1,18)* -1,5)) should be used-value-equivalent to -1 assert_equals: calc(mod(rem(1,18)* -1,5)) and -1 serialize to the same thing in used values. expected "matrix(-1, 0, 0, -1, 0, 0)" but got "none" +FAIL round(10px,6px) should be used-value-equivalent to 12px assert_equals: round(10px,6px) and 12px serialize to the same thing in used values. expected "12px" but got "0px" +FAIL round(10cm,6cm) should be used-value-equivalent to 12cm assert_equals: round(10cm,6cm) and 12cm serialize to the same thing in used values. expected "453.543px" but got "0px" +FAIL round(10mm,6mm) should be used-value-equivalent to 12mm assert_equals: round(10mm,6mm) and 12mm serialize to the same thing in used values. expected "45.3543px" but got "0px" +FAIL round(10Q, 6Q) should be used-value-equivalent to 12Q assert_equals: round(10Q, 6Q) and 12Q serialize to the same thing in used values. expected "11.3386px" but got "0px" +FAIL round(10in,6in) should be used-value-equivalent to 12in assert_equals: round(10in,6in) and 12in serialize to the same thing in used values. expected "1152px" but got "0px" +FAIL round(10pc,6pc) should be used-value-equivalent to 12pc assert_equals: round(10pc,6pc) and 12pc serialize to the same thing in used values. expected "192px" but got "0px" +FAIL round(10pt,6pt) should be used-value-equivalent to 12pt assert_equals: round(10pt,6pt) and 12pt serialize to the same thing in used values. expected "16px" but got "0px" +FAIL round(10em,6em) should be used-value-equivalent to 12em assert_equals: round(10em,6em) and 12em serialize to the same thing in used values. expected "192px" but got "0px" +FAIL round(10ex,6ex) should be used-value-equivalent to 12ex assert_equals: round(10ex,6ex) and 12ex serialize to the same thing in used values. expected "84px" but got "0px" +FAIL round(10ch,6ch) should be used-value-equivalent to 12ch assert_equals: round(10ch,6ch) and 12ch serialize to the same thing in used values. expected "96px" but got "0px" +FAIL round(10rem,6rem) should be used-value-equivalent to 12rem assert_equals: round(10rem,6rem) and 12rem serialize to the same thing in used values. expected "192px" but got "0px" +FAIL round(10vh,6vh) should be used-value-equivalent to 12vh assert_equals: round(10vh,6vh) and 12vh serialize to the same thing in used values. expected "72px" but got "0px" +FAIL round(10vw,6vw) should be used-value-equivalent to 12vw assert_equals: round(10vw,6vw) and 12vw serialize to the same thing in used values. expected "96px" but got "0px" +FAIL round(10vmin,6vmin) should be used-value-equivalent to 12vmin assert_equals: round(10vmin,6vmin) and 12vmin serialize to the same thing in used values. expected "72px" but got "0px" +FAIL round(10vmax,6vmax) should be used-value-equivalent to 12vmax assert_equals: round(10vmax,6vmax) and 12vmax serialize to the same thing in used values. expected "96px" but got "0px" +PASS round(10s,6s) should be used-value-equivalent to 12s +PASS round(10ms,6ms) should be used-value-equivalent to 12ms +FAIL round(10deg,6deg) should be used-value-equivalent to 12deg Cannot read properties of undefined (reading 'split') +FAIL round(10grad,6grad) should be used-value-equivalent to 12grad Cannot read properties of undefined (reading 'split') +FAIL round(10rad,6rad) should be used-value-equivalent to 12rad Cannot read properties of undefined (reading 'split') +FAIL round(10turn,6turn) should be used-value-equivalent to 12turn Cannot read properties of undefined (reading 'split') +FAIL mod(10px,6px) should be used-value-equivalent to 4px assert_equals: mod(10px,6px) and 4px serialize to the same thing in used values. expected "4px" but got "0px" +FAIL mod(10cm,6cm) should be used-value-equivalent to 4cm assert_equals: mod(10cm,6cm) and 4cm serialize to the same thing in used values. expected "151.181px" but got "0px" +FAIL mod(10mm,6mm) should be used-value-equivalent to 4mm assert_equals: mod(10mm,6mm) and 4mm serialize to the same thing in used values. expected "15.1181px" but got "0px" +FAIL mod(10Q, 6Q) should be used-value-equivalent to 4Q assert_equals: mod(10Q, 6Q) and 4Q serialize to the same thing in used values. expected "3.77953px" but got "0px" +FAIL mod(10in,6in) should be used-value-equivalent to 4in assert_equals: mod(10in,6in) and 4in serialize to the same thing in used values. expected "384px" but got "0px" +FAIL mod(10pc,6pc) should be used-value-equivalent to 4pc assert_equals: mod(10pc,6pc) and 4pc serialize to the same thing in used values. expected "64px" but got "0px" +FAIL mod(10em,6em) should be used-value-equivalent to 4em assert_equals: mod(10em,6em) and 4em serialize to the same thing in used values. expected "64px" but got "0px" +FAIL mod(10ex,6ex) should be used-value-equivalent to 4ex assert_equals: mod(10ex,6ex) and 4ex serialize to the same thing in used values. expected "28px" but got "0px" +FAIL mod(10ch,6ch) should be used-value-equivalent to 4ch assert_equals: mod(10ch,6ch) and 4ch serialize to the same thing in used values. expected "32px" but got "0px" +FAIL mod(10rem,6rem) should be used-value-equivalent to 4rem assert_equals: mod(10rem,6rem) and 4rem serialize to the same thing in used values. expected "64px" but got "0px" +FAIL mod(10vh,6vh) should be used-value-equivalent to 4vh assert_equals: mod(10vh,6vh) and 4vh serialize to the same thing in used values. expected "24px" but got "0px" +FAIL mod(10vw,6vw) should be used-value-equivalent to 4vw assert_equals: mod(10vw,6vw) and 4vw serialize to the same thing in used values. expected "32px" but got "0px" +FAIL mod(10vmin,6vmin) should be used-value-equivalent to 4vmin assert_equals: mod(10vmin,6vmin) and 4vmin serialize to the same thing in used values. expected "24px" but got "0px" +FAIL mod(10vmax,6vmax) should be used-value-equivalent to 4vmax assert_equals: mod(10vmax,6vmax) and 4vmax serialize to the same thing in used values. expected "32px" but got "0px" +PASS mod(10s,6s) should be used-value-equivalent to 4s +PASS mod(10ms,6ms) should be used-value-equivalent to 4ms +FAIL mod(10deg,6deg) should be used-value-equivalent to 4deg Cannot read properties of undefined (reading 'split') +FAIL mod(10grad,6grad) should be used-value-equivalent to 4grad Cannot read properties of undefined (reading 'split') +FAIL mod(10rad,6rad) should be used-value-equivalent to 4rad Cannot read properties of undefined (reading 'split') +FAIL mod(10turn,6turn) should be used-value-equivalent to 4turn Cannot read properties of undefined (reading 'split') +FAIL rem(10px,6px) should be used-value-equivalent to 4px assert_equals: rem(10px,6px) and 4px serialize to the same thing in used values. expected "4px" but got "0px" +FAIL rem(10cm,6cm) should be used-value-equivalent to 4cm assert_equals: rem(10cm,6cm) and 4cm serialize to the same thing in used values. expected "151.181px" but got "0px" +FAIL rem(10mm,6mm) should be used-value-equivalent to 4mm assert_equals: rem(10mm,6mm) and 4mm serialize to the same thing in used values. expected "15.1181px" but got "0px" +FAIL rem(10Q, 6Q) should be used-value-equivalent to 4Q assert_equals: rem(10Q, 6Q) and 4Q serialize to the same thing in used values. expected "3.77953px" but got "0px" +FAIL rem(10in,6in) should be used-value-equivalent to 4in assert_equals: rem(10in,6in) and 4in serialize to the same thing in used values. expected "384px" but got "0px" +FAIL rem(10pc,6pc) should be used-value-equivalent to 4pc assert_equals: rem(10pc,6pc) and 4pc serialize to the same thing in used values. expected "64px" but got "0px" +FAIL rem(10em,6em) should be used-value-equivalent to 4em assert_equals: rem(10em,6em) and 4em serialize to the same thing in used values. expected "64px" but got "0px" +FAIL rem(10ex,6ex) should be used-value-equivalent to 4ex assert_equals: rem(10ex,6ex) and 4ex serialize to the same thing in used values. expected "28px" but got "0px" +FAIL rem(10ch,6ch) should be used-value-equivalent to 4ch assert_equals: rem(10ch,6ch) and 4ch serialize to the same thing in used values. expected "32px" but got "0px" +FAIL rem(10rem,6rem) should be used-value-equivalent to 4rem assert_equals: rem(10rem,6rem) and 4rem serialize to the same thing in used values. expected "64px" but got "0px" +FAIL rem(10vh,6vh) should be used-value-equivalent to 4vh assert_equals: rem(10vh,6vh) and 4vh serialize to the same thing in used values. expected "24px" but got "0px" +FAIL rem(10vw,6vw) should be used-value-equivalent to 4vw assert_equals: rem(10vw,6vw) and 4vw serialize to the same thing in used values. expected "32px" but got "0px" +FAIL rem(10vmin,6vmin) should be used-value-equivalent to 4vmin assert_equals: rem(10vmin,6vmin) and 4vmin serialize to the same thing in used values. expected "24px" but got "0px" +FAIL rem(10vmax,6vmax) should be used-value-equivalent to 4vmax assert_equals: rem(10vmax,6vmax) and 4vmax serialize to the same thing in used values. expected "32px" but got "0px" +PASS rem(10s,6s) should be used-value-equivalent to 4s +PASS rem(10ms,6ms) should be used-value-equivalent to 4ms +FAIL rem(10deg,6deg) should be used-value-equivalent to 4deg Cannot read properties of undefined (reading 'split') +FAIL rem(10grad,6grad) should be used-value-equivalent to 4grad Cannot read properties of undefined (reading 'split') +FAIL rem(10rad,6rad) should be used-value-equivalent to 4rad Cannot read properties of undefined (reading 'split') +FAIL rem(10turn,6turn) should be used-value-equivalent to 4turn Cannot read properties of undefined (reading 'split') +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/css/css-values/signs-abs-computed-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/css/css-values/signs-abs-computed-expected.txt new file mode 100644 index 0000000..031583b --- /dev/null +++ b/third_party/blink/web_tests/platform/win/external/wpt/css/css-values/signs-abs-computed-expected.txt
@@ -0,0 +1,146 @@ +This is a testharness.js-based test. +Found 142 tests; 87 PASS, 55 FAIL, 0 TIMEOUT, 0 NOTRUN. +FAIL abs(1) should be used-value-equivalent to 1 assert_equals: abs(1) and 1 serialize to the same thing in used values. expected "matrix(1, 0, 0, 1, 0, 0)" but got "none" +FAIL sign(1) should be used-value-equivalent to 1 assert_equals: sign(1) and 1 serialize to the same thing in used values. expected "matrix(1, 0, 0, 1, 0, 0)" but got "none" +FAIL abs(-1) should be used-value-equivalent to 1 assert_equals: abs(-1) and 1 serialize to the same thing in used values. expected "matrix(1, 0, 0, 1, 0, 0)" but got "none" +FAIL sign(-1) should be used-value-equivalent to -1 assert_equals: sign(-1) and -1 serialize to the same thing in used values. expected "matrix(-1, 0, 0, -1, 0, 0)" but got "none" +PASS abs(sign(1)) should be used-value-equivalent to 1 +PASS abs(sign(sign(1))) should be used-value-equivalent to 1 +PASS sign(sign(sign(1) + sign(1))) should be used-value-equivalent to 1 +FAIL calc(abs(0.1 + 0.2) + 0.05) should be used-value-equivalent to 0.35 Cannot read properties of undefined (reading 'split') +FAIL calc(sign(0.1 + 0.2) - 0.05) should be used-value-equivalent to 0.95 Cannot read properties of undefined (reading 'split') +FAIL calc(abs(0.1 + 0.2) * 2) should be used-value-equivalent to 0.6 Cannot read properties of undefined (reading 'split') +FAIL calc(abs(sign(0.1) + 0.2) / 2) should be used-value-equivalent to 0.6 Cannot read properties of undefined (reading 'split') +FAIL calc(abs(0.1 + 0.2) * -2) should be used-value-equivalent to -0.6 Cannot read properties of undefined (reading 'split') +FAIL calc(sign(0.1 - 0.2) - 0.05) should be used-value-equivalent to -1.05 Cannot read properties of undefined (reading 'split') +FAIL calc(sign(1) + sign(1) - 0.05) should be used-value-equivalent to 1.95 Cannot read properties of undefined (reading 'split') +FAIL calc(sign(-0)) should be used-value-equivalent to -0 assert_equals: calc(sign(-0)) and -0 serialize to the same thing in used values. expected "matrix(0, 0, 0, 0, 0, 0)" but got "none" +FAIL calc(sign(0)) should be used-value-equivalent to 0 assert_equals: calc(sign(0)) and 0 serialize to the same thing in used values. expected "matrix(0, 0, 0, 0, 0, 0)" but got "none" +PASS sign(1px) should be used-value-equivalent to 1 +PASS sign(1cm) should be used-value-equivalent to 1 +PASS sign(1mm) should be used-value-equivalent to 1 +PASS sign(1Q) should be used-value-equivalent to 1 +PASS sign(1in) should be used-value-equivalent to 1 +PASS sign(1pc) should be used-value-equivalent to 1 +PASS sign(1pt) should be used-value-equivalent to 1 +PASS sign(1em) should be used-value-equivalent to 1 +PASS sign(1ex) should be used-value-equivalent to 1 +PASS sign(1ch) should be used-value-equivalent to 1 +PASS sign(1rem) should be used-value-equivalent to 1 +PASS sign(1vh) should be used-value-equivalent to 1 +PASS sign(1vw) should be used-value-equivalent to 1 +PASS sign(1vmin) should be used-value-equivalent to 1 +PASS sign(1vmax) should be used-value-equivalent to 1 +PASS sign(-1px) should be used-value-equivalent to -1 +PASS sign(-1cm) should be used-value-equivalent to -1 +PASS sign(-1mm) should be used-value-equivalent to -1 +PASS sign(-1Q) should be used-value-equivalent to -1 +PASS sign(-1in) should be used-value-equivalent to -1 +PASS sign(-1pc) should be used-value-equivalent to -1 +PASS sign(-1pt) should be used-value-equivalent to -1 +PASS sign(-1em) should be used-value-equivalent to -1 +PASS sign(-1ex) should be used-value-equivalent to -1 +PASS sign(-1ch) should be used-value-equivalent to -1 +PASS sign(-1rem) should be used-value-equivalent to -1 +PASS sign(-1vh) should be used-value-equivalent to -1 +PASS sign(-1vw) should be used-value-equivalent to -1 +PASS sign(-1vmin) should be used-value-equivalent to -1 +PASS sign(-1vmax) should be used-value-equivalent to -1 +PASS sign(1s) should be used-value-equivalent to 1 +PASS sign(1ms) should be used-value-equivalent to 1 +PASS sign(-1s) should be used-value-equivalent to -1 +PASS sign(-1ms) should be used-value-equivalent to -1 +PASS sign(1deg) should be used-value-equivalent to 1 +PASS sign(1grad) should be used-value-equivalent to 1 +PASS sign(1rad) should be used-value-equivalent to 1 +PASS sign(1turn) should be used-value-equivalent to 1 +PASS sign(-1deg) should be used-value-equivalent to -1 +PASS sign(-1grad) should be used-value-equivalent to -1 +PASS sign(-1rad) should be used-value-equivalent to -1 +PASS sign(-1turn) should be used-value-equivalent to -1 +PASS sign(0px) should be used-value-equivalent to 0 +PASS sign(0cm) should be used-value-equivalent to 0 +PASS sign(0mm) should be used-value-equivalent to 0 +PASS sign(0Q) should be used-value-equivalent to 0 +PASS sign(0in) should be used-value-equivalent to 0 +PASS sign(0pc) should be used-value-equivalent to 0 +PASS sign(0pt) should be used-value-equivalent to 0 +PASS sign(0em) should be used-value-equivalent to 0 +PASS sign(0ex) should be used-value-equivalent to 0 +PASS sign(0ch) should be used-value-equivalent to 0 +PASS sign(0rem) should be used-value-equivalent to 0 +PASS sign(0vh) should be used-value-equivalent to 0 +PASS sign(0vw) should be used-value-equivalent to 0 +PASS sign(0vmin) should be used-value-equivalent to 0 +PASS sign(0vmax) should be used-value-equivalent to 0 +PASS sign(-0px) should be used-value-equivalent to -0 +PASS sign(-0cm) should be used-value-equivalent to -0 +PASS sign(-0mm) should be used-value-equivalent to -0 +PASS sign(-0Q) should be used-value-equivalent to -0 +PASS sign(-0in) should be used-value-equivalent to -0 +PASS sign(-0pc) should be used-value-equivalent to -0 +PASS sign(-0pt) should be used-value-equivalent to -0 +PASS sign(-0em) should be used-value-equivalent to -0 +PASS sign(-0ex) should be used-value-equivalent to -0 +PASS sign(-0ch) should be used-value-equivalent to -0 +PASS sign(-0rem) should be used-value-equivalent to -0 +PASS sign(-0vh) should be used-value-equivalent to -0 +PASS sign(-0vw) should be used-value-equivalent to -0 +PASS sign(-0vmin) should be used-value-equivalent to -0 +PASS sign(-0vmax) should be used-value-equivalent to -0 +PASS sign(0s) should be used-value-equivalent to 0 +PASS sign(0ms) should be used-value-equivalent to 0 +PASS sign(-0s) should be used-value-equivalent to 0 +PASS sign(-0ms) should be used-value-equivalent to 0 +PASS sign(0deg) should be used-value-equivalent to 0 +PASS sign(0grad) should be used-value-equivalent to 0 +PASS sign(0rad) should be used-value-equivalent to 0 +PASS sign(0turn) should be used-value-equivalent to 0 +PASS sign(-0deg) should be used-value-equivalent to -0 +PASS sign(-0grad) should be used-value-equivalent to -0 +PASS sign(-0rad) should be used-value-equivalent to -0 +PASS sign(-0turn) should be used-value-equivalent to -0 +FAIL abs(1px) should be used-value-equivalent to 1px assert_equals: abs(1px) and 1px serialize to the same thing in used values. expected "1px" but got "0px" +FAIL abs(1cm) should be used-value-equivalent to 1cm assert_equals: abs(1cm) and 1cm serialize to the same thing in used values. expected "37.7953px" but got "0px" +FAIL abs(1mm) should be used-value-equivalent to 1mm assert_equals: abs(1mm) and 1mm serialize to the same thing in used values. expected "3.77953px" but got "0px" +FAIL abs(1Q) should be used-value-equivalent to 1Q assert_equals: abs(1Q) and 1Q serialize to the same thing in used values. expected "0.944882px" but got "0px" +FAIL abs(1in) should be used-value-equivalent to 1in assert_equals: abs(1in) and 1in serialize to the same thing in used values. expected "96px" but got "0px" +FAIL abs(1pc) should be used-value-equivalent to 1pc assert_equals: abs(1pc) and 1pc serialize to the same thing in used values. expected "16px" but got "0px" +FAIL abs(1pt) should be used-value-equivalent to 1pt assert_equals: abs(1pt) and 1pt serialize to the same thing in used values. expected "1.33333px" but got "0px" +FAIL abs(1em) should be used-value-equivalent to 1em assert_equals: abs(1em) and 1em serialize to the same thing in used values. expected "16px" but got "0px" +FAIL abs(1ex) should be used-value-equivalent to 1ex assert_equals: abs(1ex) and 1ex serialize to the same thing in used values. expected "7px" but got "0px" +FAIL abs(1ch) should be used-value-equivalent to 1ch assert_equals: abs(1ch) and 1ch serialize to the same thing in used values. expected "8px" but got "0px" +FAIL abs(1rem) should be used-value-equivalent to 1rem assert_equals: abs(1rem) and 1rem serialize to the same thing in used values. expected "16px" but got "0px" +FAIL abs(1vh) should be used-value-equivalent to 1vh assert_equals: abs(1vh) and 1vh serialize to the same thing in used values. expected "6px" but got "0px" +FAIL abs(1vw) should be used-value-equivalent to 1vw assert_equals: abs(1vw) and 1vw serialize to the same thing in used values. expected "8px" but got "0px" +FAIL abs(1vmin) should be used-value-equivalent to 1vmin assert_equals: abs(1vmin) and 1vmin serialize to the same thing in used values. expected "6px" but got "0px" +FAIL abs(1vmax) should be used-value-equivalent to 1vmax assert_equals: abs(1vmax) and 1vmax serialize to the same thing in used values. expected "8px" but got "0px" +FAIL abs(-1px) should be used-value-equivalent to 1px assert_equals: abs(-1px) and 1px serialize to the same thing in used values. expected "1px" but got "0px" +FAIL abs(-1cm) should be used-value-equivalent to 1cm assert_equals: abs(-1cm) and 1cm serialize to the same thing in used values. expected "37.7953px" but got "0px" +FAIL abs(-1mm) should be used-value-equivalent to 1mm assert_equals: abs(-1mm) and 1mm serialize to the same thing in used values. expected "3.77953px" but got "0px" +FAIL abs(-1Q) should be used-value-equivalent to 1Q assert_equals: abs(-1Q) and 1Q serialize to the same thing in used values. expected "0.944882px" but got "0px" +FAIL abs(-1in) should be used-value-equivalent to 1in assert_equals: abs(-1in) and 1in serialize to the same thing in used values. expected "96px" but got "0px" +FAIL abs(-1pc) should be used-value-equivalent to 1pc assert_equals: abs(-1pc) and 1pc serialize to the same thing in used values. expected "16px" but got "0px" +FAIL abs(-1pt) should be used-value-equivalent to 1pt assert_equals: abs(-1pt) and 1pt serialize to the same thing in used values. expected "1.33333px" but got "0px" +FAIL abs(-1em) should be used-value-equivalent to 1em assert_equals: abs(-1em) and 1em serialize to the same thing in used values. expected "16px" but got "0px" +FAIL abs(-1ex) should be used-value-equivalent to 1ex assert_equals: abs(-1ex) and 1ex serialize to the same thing in used values. expected "7px" but got "0px" +FAIL abs(-1ch) should be used-value-equivalent to 1ch assert_equals: abs(-1ch) and 1ch serialize to the same thing in used values. expected "8px" but got "0px" +FAIL abs(-1rem) should be used-value-equivalent to 1rem assert_equals: abs(-1rem) and 1rem serialize to the same thing in used values. expected "16px" but got "0px" +FAIL abs(-1vh) should be used-value-equivalent to 1vh assert_equals: abs(-1vh) and 1vh serialize to the same thing in used values. expected "6px" but got "0px" +FAIL abs(-1vw) should be used-value-equivalent to 1vw assert_equals: abs(-1vw) and 1vw serialize to the same thing in used values. expected "8px" but got "0px" +FAIL abs(-1vmin) should be used-value-equivalent to 1vmin assert_equals: abs(-1vmin) and 1vmin serialize to the same thing in used values. expected "6px" but got "0px" +FAIL abs(-1vmax) should be used-value-equivalent to 1vmax assert_equals: abs(-1vmax) and 1vmax serialize to the same thing in used values. expected "8px" but got "0px" +FAIL abs(1s) should be used-value-equivalent to 1s assert_equals: abs(1s) and 1s serialize to the same thing in used values. expected "1s" but got "0s" +FAIL abs(1ms) should be used-value-equivalent to 1ms assert_equals: abs(1ms) and 1ms serialize to the same thing in used values. expected "0.001s" but got "0s" +FAIL abs(-1s) should be used-value-equivalent to 1s assert_equals: abs(-1s) and 1s serialize to the same thing in used values. expected "1s" but got "0s" +FAIL abs(-1ms) should be used-value-equivalent to 1ms assert_equals: abs(-1ms) and 1ms serialize to the same thing in used values. expected "0.001s" but got "0s" +FAIL abs(1deg) should be used-value-equivalent to 1deg Cannot read properties of undefined (reading 'split') +FAIL abs(1grad) should be used-value-equivalent to 1grad Cannot read properties of undefined (reading 'split') +FAIL abs(1rad) should be used-value-equivalent to 1rad Cannot read properties of undefined (reading 'split') +FAIL abs(1turn) should be used-value-equivalent to 1turn Cannot read properties of undefined (reading 'split') +FAIL abs(-1deg) should be used-value-equivalent to 1deg Cannot read properties of undefined (reading 'split') +FAIL abs(-1grad) should be used-value-equivalent to 1grad Cannot read properties of undefined (reading 'split') +FAIL abs(-1rad) should be used-value-equivalent to 1rad Cannot read properties of undefined (reading 'split') +FAIL abs(-1turn) should be used-value-equivalent to 1turn Cannot read properties of undefined (reading 'split') +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt index 7b176c77..fd1255fa 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -235,6 +235,7 @@ getter canGoBack getter canGoForward getter current + getter oncurrentchange getter onnavigate getter onnavigateerror getter onnavigatesuccess @@ -247,9 +248,15 @@ method navigate method reload method updateCurrent + setter oncurrentchange setter onnavigate setter onnavigateerror setter onnavigatesuccess +interface AppHistoryCurrentChangeEvent : Event + attribute @@toStringTag + getter from + getter navigationType + method constructor interface AppHistoryDestination attribute @@toStringTag getter id
diff --git a/tools/cast3p/OWNERS b/tools/cast3p/OWNERS new file mode 100644 index 0000000..b886434 --- /dev/null +++ b/tools/cast3p/OWNERS
@@ -0,0 +1,4 @@ +chonggu@google.com +mfoltz@google.com +riazantsevv@google.com +rwkeane@google.com \ No newline at end of file
diff --git a/tools/cast3p/README.md b/tools/cast3p/README.md new file mode 100644 index 0000000..0b273d5 --- /dev/null +++ b/tools/cast3p/README.md
@@ -0,0 +1,5 @@ +This directory contains Python code used for interacting with the binaries +related to OEM integration for Cast running on third-party hardware. +These binaries can be fetched by setting checkout_cast3p=True in .gclient. +go/upstreaming-the-cast-web-runtime details the effort to upstream the +Cast Web Runtime.
diff --git a/tools/cast3p/runtime.version b/tools/cast3p/runtime.version new file mode 100644 index 0000000..3f82e17 --- /dev/null +++ b/tools/cast3p/runtime.version
@@ -0,0 +1 @@ +273826 \ No newline at end of file
diff --git a/tools/cast3p/update_runtime.py b/tools/cast3p/update_runtime.py new file mode 100755 index 0000000..1624be1 --- /dev/null +++ b/tools/cast3p/update_runtime.py
@@ -0,0 +1,69 @@ +#!/usr/bin/env python3 +# Copyright 2021 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. + +import logging +import os +import subprocess +import shutil +import sys +import tempfile + +from zipfile import ZipFile + +DIR_SOURCE_ROOT = os.path.abspath( + os.path.join(os.path.dirname(__file__), os.pardir, os.pardir)) + +sys.path.append(os.path.join(DIR_SOURCE_ROOT, 'build')) +import find_depot_tools + +RUNTIME_SIGNATURE_FILE = '.version' +WEB_RUNTIME_ROOT = os.path.abspath( + os.path.join(DIR_SOURCE_ROOT, 'third_party', 'cast_web_runtime')) +ZIP_PATH_TEMPLATE = ( + 'gs://gtv-eureka/internal/master/core_runtime-eng/{version}' \ + '/core_runtime_package.zip') + + +# Fetches a .zip file from GCS and uncompresses it to |output_dir|. +def DownloadAndUnpackFromCloudStorage(url, output_dir): + with tempfile.TemporaryDirectory() as tmpdir: + temp_zip_file = os.path.join(tmpdir, 'web_runtime.zip') + cmd = [ + os.path.join(find_depot_tools.DEPOT_TOOLS_PATH, 'gsutil.py'), 'cp', url, + temp_zip_file + ] + task = subprocess.check_call(cmd, + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL) + with ZipFile(temp_zip_file, 'r') as zip_ref: + zip_ref.extractall(output_dir) + + +def MakeCleanDirectory(directory_name): + if os.path.exists(directory_name): + shutil.rmtree(directory_name) + os.mkdir(directory_name) + + +def main(): + runtime_version = open( + os.path.join(os.path.dirname(__file__), + 'runtime.version')).read().strip() + signature_file_path = os.path.join(WEB_RUNTIME_ROOT, RUNTIME_SIGNATURE_FILE) + current_signature = (open(signature_file_path, 'r').read().strip() + if os.path.exists(signature_file_path) else '') + if current_signature != runtime_version: + logging.info( + 'Downloading Cast Web Runtime version {}...'.format(runtime_version)) + MakeCleanDirectory(WEB_RUNTIME_ROOT) + DownloadAndUnpackFromCloudStorage( + ZIP_PATH_TEMPLATE.format(version=runtime_version), WEB_RUNTIME_ROOT) + with open(signature_file_path, 'w') as f: + f.write(runtime_version) + return 0 + + +if __name__ == '__main__': + sys.exit(main())
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index d71fb1c..1f6376b2 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -49,6 +49,7 @@ 'fuchsia-official': 'fuchsia_official_optimize_goma', 'linux-archive-rel': 'release_bot', 'linux-archive-dbg': 'debug_bot', + 'linux-archive-tagged': 'release_bot', 'linux-official': 'official_optimize_goma', 'mac-archive-rel': 'release_bot_mac_strip_minimal_symbols', 'mac-archive-dbg': 'debug_bot',
diff --git a/tools/mb/mb_config_expectations/chromium.json b/tools/mb/mb_config_expectations/chromium.json index 3497b9ed..1557087 100644 --- a/tools/mb/mb_config_expectations/chromium.json +++ b/tools/mb/mb_config_expectations/chromium.json
@@ -49,6 +49,14 @@ "use_goma": true } }, + "linux-archive-tagged": { + "gn_args": { + "dcheck_always_on": false, + "is_component_build": false, + "is_debug": false, + "use_goma": true + } + }, "linux-official": { "gn_args": { "is_official_build": true,
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index d9a8816..1a9cd2ab 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -45904,6 +45904,7 @@ <int value="59" label="SBOX_ERROR_CANNOT_INIT_BROKERSERVICES"/> <int value="60" label="SBOX_ERROR_CANNOT_UPDATE_JOB_PROCESS_LIMIT"/> <int value="61" label="SBOX_ERROR_CANNOT_CREATE_LOWBOX_IMPERSONATION_TOKEN"/> + <int value="62" label="SBOX_ERROR_UNSANDBOXED_PROCESS"/> <int value="1002" label="LAUNCH_RESULT_SUCCESS"/> <int value="1003" label="LAUNCH_RESULT_FAILURE"/> </enum> @@ -47648,6 +47649,7 @@ label="OverlayScrollbarFlashAfterAnyScrollUpdate:enabled"/> <int value="-1907565048" label="HtmlBaseUsernameDetector:disabled"/> <int value="-1907342706" label="ReadItLaterInMenu:disabled"/> + <int value="-1905470520" label="FirmwareUpdaterApp:enabled"/> <int value="-1903365454" label="SyncPseudoUSSPreferences:disabled"/> <int value="-1899715534" label="GamepadPollingInterval:enabled"/> <int value="-1899652563" label="ReportFeedUserActions:enabled"/> @@ -48782,6 +48784,7 @@ <int value="-1052219252" label="disable-captive-portal-bypass-proxy"/> <int value="-1052115254" label="TextfieldFocusOnTapUp:disabled"/> <int value="-1051509976" label="ServiceWorkerOnUI:disabled"/> + <int value="-1050006327" label="FirmwareUpdaterApp:disabled"/> <int value="-1048901516" label="ChromeMemex:enabled"/> <int value="-1048011353" label="LongPressBackNewDesign:disabled"/> <int value="-1046641729" label="TranslateUI:enabled"/> @@ -50086,6 +50089,7 @@ <int value="-15879016" label="OmniboxUIExperimentUnboldSuggestionText:disabled"/> <int value="-13918890" label="disable-download-notification"/> + <int value="-13180015" label="WebUsbDeviceDetection:disabled"/> <int value="-12225998" label="ShareButtonInTopToolbar:disabled"/> <int value="-11983392" label="MagnifierContinuousMouseFollowingModeSetting:enabled"/> @@ -50172,6 +50176,7 @@ <int value="54258707" label="NewTabstripAnimation:enabled"/> <int value="54571864" label="EnableDisplayZoomSetting:enabled"/> <int value="56072855" label="VaapiWebPImageDecodeAcceleration:disabled"/> + <int value="56605515" label="BookmarksImprovedSaveFlow:enabled"/> <int value="56723110" label="enable-webfonts-intervention"/> <int value="56900498" label="OmniboxOneClickUnelide:enabled"/> <int value="57255632" label="site-isolation-for-password-sites:disabled"/> @@ -52298,6 +52303,7 @@ <int value="1713230497" label="ColorCorrectRendering:disabled"/> <int value="1714016217" label="EnableHeuristicPalmDetectionFilter:enabled"/> <int value="1714520147" label="MBIMode:disabled"/> + <int value="1714746366" label="BookmarksImprovedSaveFlow:disabled"/> <int value="1714922056" label="GlobalMediaControls:disabled"/> <int value="1715338237" label="ContextualSearchSecondTap:disabled"/> <int value="1716104463" label="enable-fullscreen-app-list"/> @@ -52408,6 +52414,7 @@ <int value="1803465156" label="enable-zero-suggest-most-visited"/> <int value="1803470125" label="SyncUSSSessions:enabled"/> <int value="1803914892" label="TemporaryUnexpireFlagsM76:enabled"/> + <int value="1806450300" label="WebUsbDeviceDetection:enabled"/> <int value="1807374811" label="CCTModuleCache:enabled"/> <int value="1809940714" label="SpeculativeLaunchServiceWorker:disabled"/> <int value="1810258949" label="DisplayLocking:enabled"/>
diff --git a/tools/metrics/histograms/metadata/arc/histograms.xml b/tools/metrics/histograms/metadata/arc/histograms.xml index cc6be8c..49a57c2f 100644 --- a/tools/metrics/histograms/metadata/arc/histograms.xml +++ b/tools/metrics/histograms/metadata/arc/histograms.xml
@@ -635,7 +635,10 @@ </histogram> <histogram name="Arc.CupsPrinting.PageCount" units="units" - expires_after="2022-03-04"> + expires_after="2020-10-04"> + <obsolete> + Removed 2021-09. + </obsolete> <owner>skau@chromium.org</owner> <owner>vkuzkokov@google.com</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/browser/histograms.xml b/tools/metrics/histograms/metadata/browser/histograms.xml index 4b6351f..163a6bcc4 100644 --- a/tools/metrics/histograms/metadata/browser/histograms.xml +++ b/tools/metrics/histograms/metadata/browser/histograms.xml
@@ -101,6 +101,7 @@ <token key="Survey"> <variant name=".General"/> <variant name=".OnboardingExperience"/> + <variant name=".SmartLock"/> <variant name=".Unlock"/> </token> </histogram>
diff --git a/tools/metrics/histograms/metadata/content/histograms.xml b/tools/metrics/histograms/metadata/content/histograms.xml index 66a0c02..147cb2d 100644 --- a/tools/metrics/histograms/metadata/content/histograms.xml +++ b/tools/metrics/histograms/metadata/content/histograms.xml
@@ -1547,6 +1547,19 @@ </summary> </histogram> +<histogram name="ContentSuggestions.Feed.WebFeed.NewFollow.IsRecommended" + enum="Boolean" expires_after="2022-09-01"> + <owner>harringtond@chromium.org</owner> + <owner>feed@chromium.org</owner> + <summary> + Whether the followed web feed was recommended by the server. + + Reported upon successfully following a web feed. Reported as 'true' if the + web feed was recommended, even if the user did not see or interact with + recommendation UI. + </summary> +</histogram> + <histogram name="ContentSuggestions.Feed.WebFeed.Opened" units="index" expires_after="never"> <!-- expires-never: key feature metric. We will need the Opened
diff --git a/tools/metrics/histograms/metadata/password/histograms.xml b/tools/metrics/histograms/metadata/password/histograms.xml index ddeaee9..7f52c84 100644 --- a/tools/metrics/histograms/metadata/password/histograms.xml +++ b/tools/metrics/histograms/metadata/password/histograms.xml
@@ -2664,6 +2664,9 @@ <histogram name="PasswordProtection.AndroidVisualFeaturesNativeViewHeight" units="dip" expires_after="2021-10-04"> + <obsolete> + Removed 09-2021 + </obsolete> <owner>drubery@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary> @@ -2677,6 +2680,9 @@ <histogram name="PasswordProtection.AndroidVisualFeaturesNativeViewNull" enum="BooleanNull" expires_after="2021-10-04"> + <obsolete> + Removed 09-2021 + </obsolete> <owner>drubery@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary> @@ -2690,6 +2696,9 @@ <histogram name="PasswordProtection.AndroidVisualFeaturesNativeViewWidth" units="dip" expires_after="2021-10-04"> + <obsolete> + Removed 09-2021 + </obsolete> <owner>drubery@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary> @@ -2703,6 +2712,9 @@ <histogram name="PasswordProtection.AndroidVisualFeaturesViewNull" enum="BooleanNull" expires_after="2021-10-04"> + <obsolete> + Removed 09-2021 + </obsolete> <owner>drubery@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/sb_client/histograms.xml b/tools/metrics/histograms/metadata/sb_client/histograms.xml index 48b67c2..8192e124 100644 --- a/tools/metrics/histograms/metadata/sb_client/histograms.xml +++ b/tools/metrics/histograms/metadata/sb_client/histograms.xml
@@ -439,7 +439,7 @@ </histogram> <histogram name="SBClientPhishing.CacheDetectsPhishing" - enum="BooleanIsPhishing" expires_after="2021-09-17"> + enum="BooleanIsPhishing" expires_after="2022-09-17"> <owner>drubery@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary> @@ -501,7 +501,9 @@ <histogram name="SBClientPhishing.ClientModelDownloadResponseOrErrorCode" enum="CombinedHttpResponseAndNetErrorCode" expires_after="M94"> - <owner>drubery@google.com</owner> + <obsolete> + Remove 09-2021 + </obsolete> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary> Response or error codes from the SafeBrowsing service. Logged after a @@ -828,7 +830,7 @@ </histogram> <histogram name="SBClientPhishing.TermFeatureChunkTime" units="ms" - expires_after="2021-10-17"> + expires_after="2022-10-17"> <owner>drubery@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary> @@ -837,7 +839,7 @@ </histogram> <histogram name="SBClientPhishing.TermFeatureIterations" units="units" - expires_after="2021-10-31"> + expires_after="2022-10-17"> <owner>drubery@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary> @@ -846,7 +848,7 @@ </histogram> <histogram name="SBClientPhishing.TermFeatureTimeout" units="units" - expires_after="2021-10-17"> + expires_after="2022-10-17"> <owner>drubery@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/software/histograms.xml b/tools/metrics/histograms/metadata/software/histograms.xml index b5cf64c4..ab0993f 100644 --- a/tools/metrics/histograms/metadata/software/histograms.xml +++ b/tools/metrics/histograms/metadata/software/histograms.xml
@@ -361,6 +361,9 @@ <histogram name="SoftwareReporter.OnDemandUpdateRequired" enum="BooleanRequired" expires_after="M95"> + <obsolete> + Removed 09-2021 + </obsolete> <owner>drubery@chromium.org</owner> <owner>bdea@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> @@ -372,7 +375,7 @@ </histogram> <histogram name="SoftwareReporter.OnDemandUpdateSucceeded" - enum="BooleanSuccess" expires_after="M95"> + enum="BooleanSuccess" expires_after="2022-08-25"> <owner>drubery@chromium.org</owner> <owner>bdea@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> @@ -384,7 +387,7 @@ </histogram> <histogram name="SoftwareReporter.PostCleanupSettingsReset" units="counts" - expires_after="M95"> + expires_after="2022-08-25"> <owner>drubery@chromium.org</owner> <owner>bdea@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> @@ -396,7 +399,7 @@ </histogram> <histogram name="SoftwareReporter.PromptDialogResponse" - enum="SoftwareReporterPromptDialogResponse" expires_after="M95"> + enum="SoftwareReporterPromptDialogResponse" expires_after="2022-08-25"> <owner>drubery@chromium.org</owner> <owner>bdea@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> @@ -409,6 +412,9 @@ <histogram name="SoftwareReporter.PromptShownWithType" enum="SoftwareReporterPromptShownWithType" expires_after="M95"> + <obsolete> + Removed 09-2021 + </obsolete> <owner>drubery@chromium.org</owner> <owner>bdea@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> @@ -423,7 +429,7 @@ </histogram> <histogram name="SoftwareReporter.ReporterSequenceType" - enum="SoftwareReporterSequenceType" expires_after="M95"> + enum="SoftwareReporterSequenceType" expires_after="2022-08-25"> <owner>drubery@chromium.org</owner> <owner>bdea@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> @@ -460,6 +466,9 @@ <histogram name="SoftwareReporter.ScannerLogsAcceptance" enum="BooleanAccepted" expires_after="M95"> + <obsolete> + Removed 09-2021 + </obsolete> <owner>drubery@chromium.org</owner> <owner>bdea@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> @@ -473,6 +482,9 @@ <histogram name="SoftwareReporter.TaggedProfileForResetting" enum="Boolean" expires_after="M95"> + <obsolete> + Removed 09-2021 + </obsolete> <owner>drubery@chromium.org</owner> <owner>bdea@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/uma/histograms.xml b/tools/metrics/histograms/metadata/uma/histograms.xml index 212ce46b..aeaf128 100644 --- a/tools/metrics/histograms/metadata/uma/histograms.xml +++ b/tools/metrics/histograms/metadata/uma/histograms.xml
@@ -505,7 +505,7 @@ </histogram> <histogram name="UMA.MetricsReporting.Toggle" enum="MetricsReportingChange" - expires_after="2021-10-31"> + expires_after="2022-05-01"> <owner>asvitkine@chromium.org</owner> <owner>src/base/metrics/OWNERS</owner> <summary> @@ -528,7 +528,7 @@ </histogram> <histogram name="UMA.MetricsService.Initialize.Time" units="microseconds" - expires_after="2021-10-31"> + expires_after="2022-05-01"> <owner>asvitkine@chromium.org</owner> <owner>src/base/metrics/OWNERS</owner> <summary> @@ -550,7 +550,7 @@ </histogram> <histogram name="UMA.NegativeSamples.Increment" units="increment" - expires_after="2021-10-31"> + expires_after="2022-05-01"> <owner>asvitkine@chromium.org</owner> <owner>bcwhite@chromium.org</owner> <owner>src/base/metrics/OWNERS</owner> @@ -560,7 +560,7 @@ </histogram> <histogram name="UMA.NegativeSamples.Reason" enum="NegativeSampleReason" - expires_after="2021-10-31"> + expires_after="2022-05-01"> <owner>asvitkine@chromium.org</owner> <owner>bcwhite@chromium.org</owner> <owner>src/base/metrics/OWNERS</owner>
diff --git a/ui/base/ime/fuchsia/input_method_fuchsia.cc b/ui/base/ime/fuchsia/input_method_fuchsia.cc index 7751b9f..20f0ccb 100644 --- a/ui/base/ime/fuchsia/input_method_fuchsia.cc +++ b/ui/base/ime/fuchsia/input_method_fuchsia.cc
@@ -10,6 +10,7 @@ #include <utility> #include "base/fuchsia/process_context.h" +#include "base/logging.h" #include "ui/base/ime/text_input_client.h" #include "ui/events/base_event_utils.h" #include "ui/events/keycodes/dom/dom_code.h" @@ -54,6 +55,8 @@ } void InputMethodFuchsia::CancelComposition(const TextInputClient* client) { + DVLOG(1) << __func__; + if (virtual_keyboard_controller_) { // FIDL asynchronicity makes it impossible to know whether a recent // visibility update might be in flight, so always call Dismiss. @@ -62,6 +65,8 @@ } void InputMethodFuchsia::OnTextInputTypeChanged(const TextInputClient* client) { + DVLOG(1) << __func__; + InputMethodBase::OnTextInputTypeChanged(client); if (!virtual_keyboard_controller_)
diff --git a/ui/base/ui_base_features.cc b/ui/base/ui_base_features.cc index fab6ad29..03a8fcd 100644 --- a/ui/base/ui_base_features.cc +++ b/ui/base/ui_base_features.cc
@@ -92,13 +92,6 @@ const base::Feature kSystemKeyboardLock{"SystemKeyboardLock", base::FEATURE_ENABLED_BY_DEFAULT}; -const base::Feature kNotificationIndicator = {"EnableNotificationIndicator", - base::FEATURE_ENABLED_BY_DEFAULT}; - -bool IsNotificationIndicatorEnabled() { - return base::FeatureList::IsEnabled(kNotificationIndicator); -} - // Enables GPU rasterization for all UI drawing (where not blocklisted). const base::Feature kUiGpuRasterization = {"UiGpuRasterization", #if defined(OS_APPLE) || BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_FUCHSIA) || \
diff --git a/ui/base/ui_base_features.h b/ui/base/ui_base_features.h index fefa70b4..fdd2755 100644 --- a/ui/base/ui_base_features.h +++ b/ui/base/ui_base_features.h
@@ -38,12 +38,8 @@ COMPONENT_EXPORT(UI_BASE_FEATURES) extern const base::Feature kSystemKeyboardLock; COMPONENT_EXPORT(UI_BASE_FEATURES) -extern const base::Feature kNotificationIndicator; -COMPONENT_EXPORT(UI_BASE_FEATURES) extern const base::Feature kUiCompositorScrollWithLayers; -COMPONENT_EXPORT(UI_BASE_FEATURES) bool IsNotificationIndicatorEnabled(); - COMPONENT_EXPORT(UI_BASE_FEATURES) bool IsUiGpuRasterizationEnabled(); #if defined(OS_WIN) || defined(OS_ANDROID)
diff --git a/ui/gfx/linux/gpu_memory_buffer_support_x11.cc b/ui/gfx/linux/gpu_memory_buffer_support_x11.cc index 5b89bfd..aa5641c 100644 --- a/ui/gfx/linux/gpu_memory_buffer_support_x11.cc +++ b/ui/gfx/linux/gpu_memory_buffer_support_x11.cc
@@ -11,6 +11,7 @@ #include "base/containers/contains.h" #include "base/debug/crash_logging.h" +#include "base/logging.h" #include "base/posix/eintr_wrapper.h" #include "ui/gfx/buffer_format_util.h" #include "ui/gfx/buffer_types.h" @@ -118,7 +119,10 @@ gfx::BufferFormat format, const gfx::Size& size, gfx::BufferUsage usage) { - DCHECK(device_); + if (!device_) { + LOG(ERROR) << "Device could not be created."; + return nullptr; + } DCHECK(base::Contains(supported_configs_, gfx::BufferUsageAndFormat(usage, format)));
diff --git a/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc b/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc index a039b40..8bb847d 100644 --- a/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc +++ b/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc
@@ -104,12 +104,12 @@ DCHECK_EQ(state_, State::kIdle); DCHECK(!origin_window_); - origin_window_ = source == DragEventSource::kTouch - ? window_manager_->GetCurrentTouchFocusedWindow() - : window_manager_->GetCurrentPointerFocusedWindow(); - if (!origin_window_) { - LOG(ERROR) << "Failed to get focused window. drag_source=" - << static_cast<int>(source); + WaylandWindow* origin_window = + source == DragEventSource::kTouch + ? window_manager_->GetCurrentTouchFocusedWindow() + : window_manager_->GetCurrentPointerFocusedWindow(); + if (!origin_window) { + LOG(ERROR) << "Failed to get focused window. source=" << source; return false; } @@ -120,8 +120,7 @@ // causing hangs as observerd in crbug.com/1209269. auto serial = GetAndValidateSerialForDrag(source); if (!serial.has_value()) { - LOG(ERROR) << "Invalid state when trying to start drag. source=" - << static_cast<int>(source); + LOG(ERROR) << "Invalid state when trying to start drag. source=" << source; return false; } @@ -137,7 +136,7 @@ icon_surface_ = std::make_unique<WaylandSurface>(connection_, nullptr); if (icon_surface_->Initialize()) { // Corresponds to actual scale factor of the origin surface. - icon_surface_->SetSurfaceBufferScale(origin_window_->window_scale()); + icon_surface_->SetSurfaceBufferScale(origin_window->window_scale()); } else { LOG(ERROR) << "Failed to create drag icon surface."; icon_surface_.reset(); @@ -146,10 +145,11 @@ // Starts the wayland drag session setting |this| object as delegate. state_ = State::kStarted; - data_device_->StartDrag(*data_source_, *origin_window_, serial->value, + data_device_->StartDrag(*data_source_, *origin_window, serial->value, icon_surface_ ? icon_surface_->surface() : nullptr, this); + origin_window_ = origin_window; window_manager_->AddObserver(this); return true; }
diff --git a/ui/ozone/platform/wayland/host/wayland_data_drag_controller.h b/ui/ozone/platform/wayland/host/wayland_data_drag_controller.h index 8240102..8ffb84784 100644 --- a/ui/ozone/platform/wayland/host/wayland_data_drag_controller.h +++ b/ui/ozone/platform/wayland/host/wayland_data_drag_controller.h
@@ -102,6 +102,7 @@ FRIEND_TEST_ALL_PREFIXES(WaylandDataDragControllerTest, ReceiveDrag); FRIEND_TEST_ALL_PREFIXES(WaylandDataDragControllerTest, StartDrag); FRIEND_TEST_ALL_PREFIXES(WaylandDataDragControllerTest, StartDragWithText); + FRIEND_TEST_ALL_PREFIXES(WaylandDataDragControllerTest, AsyncNoopStartDrag); FRIEND_TEST_ALL_PREFIXES(WaylandDataDragControllerTest, StartDragWithWrongMimeType);
diff --git a/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc b/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc index 6c264b4..dfb2b53d 100644 --- a/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc
@@ -867,9 +867,9 @@ FocusAndPressLeftPointerButton(window_.get(), &delegate_); // Emulate a "quick" wl_pointer.button release event being processed by the - // compositor, which leads to a no-op subsequent wl_data_device.start_drag. - // In this case, the client is expected to gracefully reset state and quit - // drag loop as if the drag session was cancelled as usual. + // compositor, which leads to a no-op subsequent WaylandWindow::StartDrag. In + // this case, the client is expected to gracefully reset state and quit drag + // loop as if the drag session was cancelled as usual. SendPointerButton(window_.get(), &delegate_, BTN_LEFT, /*pressed=*/false); Sync(); @@ -884,6 +884,8 @@ Mock::VerifyAndClearExpectations(drop_handler_.get()); Mock::VerifyAndClearExpectations(this); + EXPECT_FALSE(drag_controller()->origin_window_); + window_->SetPointerFocus(restored_focus); }
diff --git a/ui/webui/resources/cr_components/BUILD.gn b/ui/webui/resources/cr_components/BUILD.gn index 008b2c9bb..aff05f1 100644 --- a/ui/webui/resources/cr_components/BUILD.gn +++ b/ui/webui/resources/cr_components/BUILD.gn
@@ -126,6 +126,7 @@ "chromeos/bluetooth/bluetooth_icon.js", "chromeos/bluetooth/bluetooth_icons.js", "chromeos/bluetooth/bluetooth_pairing_device_selection_page.js", + "chromeos/bluetooth/bluetooth_pairing_request_code_page.js", "chromeos/bluetooth/bluetooth_pairing_device_item.js", "chromeos/bluetooth/bluetooth_pairing_ui.js", "chromeos/cellular_setup/activation_code_page.m.js",
diff --git a/ui/webui/resources/cr_components/chromeos/bluetooth/BUILD.gn b/ui/webui/resources/cr_components/chromeos/bluetooth/BUILD.gn index 88c251d..0f0bb7f1 100644 --- a/ui/webui/resources/cr_components/chromeos/bluetooth/BUILD.gn +++ b/ui/webui/resources/cr_components/chromeos/bluetooth/BUILD.gn
@@ -87,9 +87,18 @@ ] } +js_library("bluetooth_pairing_request_code_page") { + deps = [ + ":bluetooth_base_page", + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/cr_elements/cr_input:cr_input.m", + ] +} + js_library("bluetooth_pairing_ui") { deps = [ ":bluetooth_pairing_device_selection_page", + ":bluetooth_pairing_request_code_page", ":cros_bluetooth_config", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", "//ui/webui/resources/js:assert.m", @@ -115,6 +124,7 @@ "bluetooth_icon.js", "bluetooth_icons.js", "bluetooth_pairing_device_selection_page.js", + "bluetooth_pairing_request_code_page.js", "bluetooth_pairing_device_item.js", "bluetooth_pairing_ui.js", "bluetooth_base_page.js",
diff --git a/ui/webui/resources/cr_components/chromeos/bluetooth/bluetooth_pairing_device_item.js b/ui/webui/resources/cr_components/chromeos/bluetooth/bluetooth_pairing_device_item.js index b4ff61c..c852466 100644 --- a/ui/webui/resources/cr_components/chromeos/bluetooth/bluetooth_pairing_device_item.js +++ b/ui/webui/resources/cr_components/chromeos/bluetooth/bluetooth_pairing_device_item.js
@@ -71,7 +71,7 @@ this.dispatchEvent(new CustomEvent('pair-device', { bubbles: true, composed: true, - detail: {deviceId: this.device.id}, + detail: {device: this.device}, })); } }
diff --git a/ui/webui/resources/cr_components/chromeos/bluetooth/bluetooth_pairing_request_code_page.html b/ui/webui/resources/cr_components/chromeos/bluetooth/bluetooth_pairing_request_code_page.html new file mode 100644 index 0000000..bf644e9 --- /dev/null +++ b/ui/webui/resources/cr_components/chromeos/bluetooth/bluetooth_pairing_request_code_page.html
@@ -0,0 +1,26 @@ +<style> + #pageBody { + align-items: center; + display: flex; + flex-direction: column; + justify-content: center; + } + + #message { + margin-bottom: 56px; + } + + #pin { + width: 336px; + } +</style> +<bluetooth-base-page button-bar-state="[[buttonBarState_]]"> + <div slot="page-body" id="pageBody"> + <div id="message"> + [[getMessage_(device.*)]] + </div> + <cr-input id="pin" minlength="1" maxlength="16" type="text" + auto-validate value="{{pinCode_}}"> + </cr-input> + </div> +</bluetooth-base-page>
diff --git a/ui/webui/resources/cr_components/chromeos/bluetooth/bluetooth_pairing_request_code_page.js b/ui/webui/resources/cr_components/chromeos/bluetooth/bluetooth_pairing_request_code_page.js new file mode 100644 index 0000000..b86a8e6 --- /dev/null +++ b/ui/webui/resources/cr_components/chromeos/bluetooth/bluetooth_pairing_request_code_page.js
@@ -0,0 +1,100 @@ +// Copyright 2021 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. + +/** + * @fileoverview + * UI element shown when authentication via PIN or PASSKEY is required + * during Bluetooth device pairing. + */ + +import './bluetooth_base_page.js'; +import '../../../cr_elements/shared_style_css.m.js'; +import '../../../cr_elements/cr_input/cr_input.m.js'; + +import {I18nBehavior, I18nBehaviorInterface} from '//resources/js/i18n_behavior.m.js'; +import {html, mixinBehaviors, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {ButtonBarState, ButtonState} from './bluetooth_types.js'; +import {mojoString16ToString} from './bluetooth_utils.js'; + +/** + * @constructor + * @extends {PolymerElement} + * @implements {I18nBehaviorInterface} + */ +const SettingsBluetoothPairingRequestCodePageElementBase = + mixinBehaviors([I18nBehavior], PolymerElement); + +/** @polymer */ +export class SettingsBluetoothRequestCodePageElement extends + SettingsBluetoothPairingRequestCodePageElementBase { + static get is() { + return 'bluetooth-pairing-request-code-page'; + } + + static get template() { + return html`{__html_template__}`; + } + + static get properties() { + return { + /** + * @type {?chromeos.bluetoothConfig.mojom.BluetoothDeviceProperties} + */ + device: { + type: Object, + value: null, + }, + + /** @private {!ButtonBarState} */ + buttonBarState_: { + type: Object, + computed: 'computeButtonBarState_(pinCode_)', + }, + + /** @private {string} */ + pinCode_: { + type: String, + value: '', + } + }; + } + + /** + * @private + * @return {string} + */ + getMessage_() { + return this.i18n('bluetoothEnterPin', this.getDeviceName_()); + } + + /** + * @private + * @return {string} + */ + getDeviceName_() { + if (!this.device) { + return ''; + } + + return mojoString16ToString(this.device.publicName); + } + + /** + * @return {!ButtonBarState} + * @private + */ + computeButtonBarState_() { + const pairButtonState = + !this.pinCode_ ? ButtonState.DISABLED : ButtonState.ENABLED; + + return { + cancel: ButtonState.ENABLED, + pair: pairButtonState, + }; + } +} + +customElements.define( + SettingsBluetoothRequestCodePageElement.is, + SettingsBluetoothRequestCodePageElement);
diff --git a/ui/webui/resources/cr_components/chromeos/bluetooth/bluetooth_pairing_ui.html b/ui/webui/resources/cr_components/chromeos/bluetooth/bluetooth_pairing_ui.html index 4712c68..d2e510ae 100644 --- a/ui/webui/resources/cr_components/chromeos/bluetooth/bluetooth_pairing_ui.html +++ b/ui/webui/resources/cr_components/chromeos/bluetooth/bluetooth_pairing_ui.html
@@ -7,11 +7,21 @@ <iron-pages attr-for-selected="id" selected="[[selectedPageId_]]"> - <bluetooth-pairing-device-selection-page - devices="[[discoveredDevices_]]" - on-pair-device="onPairDevice_" - id="deviceSelectionPage"> - </bluetooth-pairing-device-selection-page> + <template is="dom-if" if="[[shouldShowSubpage_( + SubpageId.DEVICE_SELECTION_PAGE, selectedPageId_)]]" restamp> + <bluetooth-pairing-device-selection-page + devices="[[discoveredDevices_]]" + on-pair-device="onPairDevice_" + id="deviceSelectionPage"> + </bluetooth-pairing-device-selection-page> + </template> + <template is="dom-if" if="[[shouldShowSubpage_( + SubpageId.DEVICE_REQUEST_CODE_PAGE, selectedPageId_)]]" restamp> + <bluetooth-pairing-request-code-page + device="[[selectedDevice_]]" + id="deviceRequestCodePage"> + </bluetooth-pairing-request-code-page> + </template> <!-- TODO(crbug.com/1010321): Add other bluetooth pairing subpage UI elements. --> </iron-pages> </div>
diff --git a/ui/webui/resources/cr_components/chromeos/bluetooth/bluetooth_pairing_ui.js b/ui/webui/resources/cr_components/chromeos/bluetooth/bluetooth_pairing_ui.js index 2651fae0..ab9f8e2 100644 --- a/ui/webui/resources/cr_components/chromeos/bluetooth/bluetooth_pairing_ui.js +++ b/ui/webui/resources/cr_components/chromeos/bluetooth/bluetooth_pairing_ui.js
@@ -8,8 +8,8 @@ */ import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; -import './bluetooth_base_page.js'; import './bluetooth_pairing_device_selection_page.js'; +import './bluetooth_pairing_request_code_page.js'; import {html, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {assert} from '../../../js/assert.m.js'; @@ -19,6 +19,7 @@ const BluetoothPairingSubpageId = { // TODO(crbug.com/1010321): Add missing bluetooth pairing subpages. DEVICE_SELECTION_PAGE: 'deviceSelectionPage', + DEVICE_REQUEST_CODE_PAGE: 'deviceRequestCodePage', }; /** @@ -53,6 +54,23 @@ type: Array, value: [], }, + + /** + * @private {?chromeos.bluetoothConfig.mojom.BluetoothDeviceProperties} + */ + devicePendingPairing_: { + type: Object, + value: null, + }, + + /** + * Used to access |BluetoothPairingSubpageId| type in HTML. + * @private {!BluetoothPairingSubpageId} + */ + SubpageId: { + type: Object, + value: BluetoothPairingSubpageId, + }, }; } @@ -98,7 +116,8 @@ } /** - * @param {!CustomEvent<!{deviceId: string}>} event + * @param {!CustomEvent<!{device: + * chromeos.bluetoothConfig.mojom.BluetoothDeviceProperties}>} event * @private */ onPairDevice_(event) { @@ -110,9 +129,15 @@ this.pairingDelegateReceiver_ = new chromeos.bluetoothConfig.mojom.DevicePairingDelegateReceiver(this); + + // TODO(crbug.com/1010321): Add test for |devicePendingPairing_| when + // request code page UI is added. + this.devicePendingPairing_ = event.detail.device; + assert(this.devicePendingPairing_); + this.devicePairingHandler_ .pairDevice( - event.detail.deviceId, + this.devicePendingPairing_.id, this.pairingDelegateReceiver_.$.bindNewPipeAndPassRemote()) .then(result => { this.handlePairDeviceResult_(result.result); @@ -125,6 +150,7 @@ */ handlePairDeviceResult_(result) { this.pairingDelegateReceiver_ = null; + this.devicePendingPairing_ = null; if (result === chromeos.bluetoothConfig.mojom.PairingResult.kSuccess) { this.dispatchEvent(new CustomEvent('finished', { @@ -170,6 +196,15 @@ authorizePairing() { // TODO(crbug.com/1010321): Implement this function. } + + /** + * @param {!BluetoothPairingSubpageId} subpageId + * @return {boolean} + * @private + */ + shouldShowSubpage_(subpageId) { + return this.selectedPageId_ === subpageId; + } } customElements.define(
diff --git a/url/DIR_METADATA b/url/DIR_METADATA index 6d266b0..16c80be 100644 --- a/url/DIR_METADATA +++ b/url/DIR_METADATA
@@ -7,5 +7,5 @@ # https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto monorail { - component: "Internals>Core" + component: "Blink>Network" } \ No newline at end of file