Skip to content

Commit

Permalink
Purge all resources in cache on conceal (#3586)
Browse files Browse the repository at this point in the history
b/346774396
  • Loading branch information
andrewsavage1 committed Jul 2, 2024
1 parent 6ddde25 commit e83b8ad
Show file tree
Hide file tree
Showing 12 changed files with 81 additions and 19 deletions.
5 changes: 4 additions & 1 deletion cobalt/browser/browser_module.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1712,7 +1712,10 @@ void BrowserModule::InstantiateRendererModule() {
void BrowserModule::DestroyRendererModule() {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
DCHECK(renderer_module_);

base::task_runner_util::PostBlockingTask(
web_module_->task_runner(), FROM_HERE,
base::Bind(&WebModule::WaitForItall,
base::Unretained(web_module_.get())));
screen_shot_writer_.reset();
renderer_module_.reset();
}
Expand Down
11 changes: 7 additions & 4 deletions cobalt/browser/web_module.cc
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,8 @@ class WebModule::Impl {
class DocumentLoadedObserver;

// Purge all resource caches owned by the WebModule.
void PurgeResourceCaches(bool should_retain_remote_typeface_cache);
void PurgeResourceCaches(bool should_retain_remote_typeface_cache,
bool on_conceal = false);

// Disable callbacks in all resource caches owned by the WebModule.
void DisableCallbacksInResourceCaches();
Expand Down Expand Up @@ -1130,14 +1131,15 @@ void WebModule::Impl::Conceal(render_tree::ResourceProvider* resource_provider,
// Purge the cached resources prior to the freeze. That may cancel pending
// loads, allowing the freeze to occur faster and preventing unnecessary
// callbacks.
loader_factory_->Conceal();
window_->document()->PurgeCachedResources();

// Clear out any currently tracked animating images.
animated_image_tracker_->Reset();

// Purge the resource caches before running any freeze logic. This will force
// any pending callbacks that the caches are batching to run.
PurgeResourceCaches(should_retain_remote_typeface_cache_on_freeze_);
PurgeResourceCaches(should_retain_remote_typeface_cache_on_freeze_, true);

#if defined(ENABLE_DEBUGGER)
// The debug overlay may be holding onto a render tree, clear that out.
Expand Down Expand Up @@ -1184,6 +1186,7 @@ void WebModule::Impl::Reveal(render_tree::ResourceProvider* resource_provider,
DCHECK(resource_provider);
SetResourceProvider(resource_provider);

image_cache_->OnReveal();
window_->document()->PurgeCachedResources();
PurgeResourceCaches(should_retain_remote_typeface_cache_on_freeze_);

Expand Down Expand Up @@ -1244,8 +1247,8 @@ void WebModule::Impl::InjectWindowOnOfflineEvent() {
}

void WebModule::Impl::PurgeResourceCaches(
bool should_retain_remote_typeface_cache) {
image_cache_->Purge();
bool should_retain_remote_typeface_cache, bool on_conceal) {
image_cache_->Purge(on_conceal);
if (should_retain_remote_typeface_cache) {
remote_typeface_cache_->ProcessPendingCallbacks();
} else {
Expand Down
12 changes: 6 additions & 6 deletions cobalt/browser/web_module.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,12 @@ namespace browser {
class WebModule : public base::CurrentThread::DestructionObserver,
public LifecycleObserver {
public:
// The task runner this object is running on.
base::SequencedTaskRunner* task_runner() const {
DCHECK(web_agent_);
return web_agent_ ? web_agent_->task_runner() : nullptr;
}
void WaitForItall() {}
struct Options {
typedef base::Callback<scoped_refptr<script::Wrappable>(
WebModule*, web::EnvironmentSettings*)>
Expand Down Expand Up @@ -482,12 +488,6 @@ class WebModule : public base::CurrentThread::DestructionObserver,

void GetIsReadyToFreeze(volatile bool* is_ready_to_freeze);

// The task runner this object is running on.
base::SequencedTaskRunner* task_runner() const {
DCHECK(web_agent_);
return web_agent_ ? web_agent_->task_runner() : nullptr;
}

// Private implementation object.
std::unique_ptr<Impl> impl_;

Expand Down
2 changes: 2 additions & 0 deletions cobalt/loader/decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ class Decoder {
// aborted.
virtual bool Suspend() = 0;

virtual void Conceal() {}

// Resumes the decode of this resource, starting over from the zero state.
virtual void Resume(render_tree::ResourceProvider* resource_provider) = 0;

Expand Down
7 changes: 7 additions & 0 deletions cobalt/loader/image/threaded_image_decoder_proxy.cc
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ void ThreadedImageDecoderProxy::DecodeChunkPassed(
}

void ThreadedImageDecoderProxy::Finish() {
base::AutoLock auto_lock(conceal_lock_);
if (is_concealed_) return;
load_task_runner_->PostTask(
FROM_HERE, base::Bind(&ImageDecoder::Finish,
base::Unretained(image_decoder_.get())));
Expand All @@ -135,6 +137,11 @@ void ThreadedImageDecoderProxy::Resume(
resource_provider));
}

void ThreadedImageDecoderProxy::Conceal() {
base::AutoLock auto_lock(conceal_lock_);
is_concealed_ = true;
}

} // namespace image
} // namespace loader
} // namespace cobalt
5 changes: 5 additions & 0 deletions cobalt/loader/image/threaded_image_decoder_proxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "cobalt/loader/image/image_data_decoder.h"
#include "cobalt/loader/image/image_decoder.h"
#include "cobalt/render_tree/resource_provider.h"
#include "starboard/common/mutex.h"

namespace cobalt {
namespace loader {
Expand Down Expand Up @@ -64,6 +65,7 @@ class ThreadedImageDecoderProxy : public Decoder {
void Finish() override;
bool Suspend() override;
void Resume(render_tree::ResourceProvider* resource_provider) override;
void Conceal() override;

private:
ThreadedImageDecoderProxy(
Expand All @@ -84,6 +86,9 @@ class ThreadedImageDecoderProxy : public Decoder {

// The actual image decoder.
std::unique_ptr<ImageDecoder> image_decoder_;

mutable base::Lock conceal_lock_;
bool is_concealed_ = false;
};

} // namespace image
Expand Down
5 changes: 5 additions & 0 deletions cobalt/loader/loader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,11 @@ void Loader::Resume(render_tree::ResourceProvider* resource_provider) {
if (!is_load_complete_) Start();
}

void Loader::Conceal() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
decoder_->Conceal();
}

bool Loader::DidFailFromTransientError() const {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return fetcher_ && fetcher_->did_fail_from_transient_error();
Expand Down
2 changes: 2 additions & 0 deletions cobalt/loader/loader.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ class Loader {
// called.
void Resume(render_tree::ResourceProvider* resource_provider);

void Conceal();

bool DidFailFromTransientError() const;

void LoadComplete(const base::Optional<std::string>& status);
Expand Down
15 changes: 15 additions & 0 deletions cobalt/loader/loader_factory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,11 @@ void LoaderFactory::Resume(render_tree::ResourceProvider* resource_provider) {
ResumeActiveLoaders(resource_provider);
}

void LoaderFactory::Conceal() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
ConcealActiveLoaders();
}

void LoaderFactory::UpdateResourceProvider(
render_tree::ResourceProvider* resource_provider) {
DCHECK(resource_provider);
Expand Down Expand Up @@ -208,5 +213,15 @@ void LoaderFactory::ResumeActiveLoaders(
base::task_runner_util::WaitForFence(load_thread_.task_runner(), FROM_HERE);
}

void LoaderFactory::ConcealActiveLoaders() {
for (LoaderSet::const_iterator iter = active_loaders_.begin();
iter != active_loaders_.end(); ++iter) {
(*iter)->Conceal();
}

// Wait for all loader thread messages to be flushed before returning.
base::task_runner_util::WaitForFence(load_thread_.task_runner(), FROM_HERE);
}

} // namespace loader
} // namespace cobalt
2 changes: 2 additions & 0 deletions cobalt/loader/loader_factory.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ class LoaderFactory : public ScriptLoaderFactory {
// previous resource provider must have been cleared before this method is
// called.
void Resume(render_tree::ResourceProvider* resource_provider);
void Conceal();

// Resets a new resource provider for this loader factory to use. The
// previous resource provider must have been cleared before this method is
Expand All @@ -106,6 +107,7 @@ class LoaderFactory : public ScriptLoaderFactory {
private:
void SuspendActiveLoaders();
void ResumeActiveLoaders(render_tree::ResourceProvider* resource_provider);
void ConcealActiveLoaders();

// Used to cache the fetched raw data. Note that currently the cache is only
// used to cache Image data. We may introduce more caches once we want to
Expand Down
9 changes: 5 additions & 4 deletions cobalt/loader/resource_cache.cc
Original file line number Diff line number Diff line change
Expand Up @@ -189,10 +189,10 @@ void ResourceCacheBase::SetCapacity(uint32 capacity) {
ReclaimMemoryAndMaybeProcessPendingCallbacks(cache_capacity_);
}

void ResourceCacheBase::Purge() {
void ResourceCacheBase::Purge(bool on_conceal) {
DCHECK_CALLED_ON_VALID_THREAD(resource_cache_thread_checker_);
ProcessPendingCallbacks();
reclaim_memory_func_.Run(0, true);
reclaim_memory_func_.Run(0, true, on_conceal);
}

void ResourceCacheBase::ProcessPendingCallbacks() {
Expand Down Expand Up @@ -289,8 +289,9 @@ void ResourceCacheBase::NotifyResourceLoadingRetryScheduled(

void ResourceCacheBase::ReclaimMemoryAndMaybeProcessPendingCallbacks(
uint32 bytes_to_reclaim_down_to) {
bool on_conceal = false;
reclaim_memory_func_.Run(bytes_to_reclaim_down_to,
false /*log_warning_if_over*/);
false /*log_warning_if_over*/, on_conceal);
// If the current size of the cache is still greater than
// |bytes_to_reclaim_down_to| after reclaiming memory, then process any
// pending callbacks and try again. References to the cached resources are
Expand All @@ -299,7 +300,7 @@ void ResourceCacheBase::ReclaimMemoryAndMaybeProcessPendingCallbacks(
if (memory_size_in_bytes_ > bytes_to_reclaim_down_to) {
ProcessPendingCallbacks();
reclaim_memory_func_.Run(bytes_to_reclaim_down_to,
true /*log_warning_if_over*/);
true /*log_warning_if_over*/, on_conceal);
}
}

Expand Down
25 changes: 21 additions & 4 deletions cobalt/loader/resource_cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ class CachedResource : public CachedResourceBase {
// returns |resource_| even if it is NULL to indicate no resource is
// available.
scoped_refptr<ResourceType> TryGetResource();
void SetIsConcealed(bool val) { is_concealed_ = val; }

private:
friend class ResourceCache<CacheType>;
Expand All @@ -286,6 +287,7 @@ class CachedResource : public CachedResourceBase {

const base::Callback<void(CachedResource*)> on_resource_destroyed_;
scoped_refptr<ResourceType> resource_;
bool is_concealed_ = false;

DISALLOW_COPY_AND_ASSIGN(CachedResource);
};
Expand Down Expand Up @@ -347,6 +349,7 @@ void CachedResource<CacheType>::OnContentProduced(
DCHECK_CALLED_ON_VALID_THREAD(cached_resource_thread_checker_);
DCHECK(!resource_);

if (is_concealed_) return;
resource_ = resource;
}

Expand Down Expand Up @@ -402,7 +405,7 @@ class CachedResourceReferenceWithCallbacks {
class ResourceCacheBase {
public:
typedef base::Callback<void(uint32 bytes_to_reclaim_down_to,
bool log_warning_if_over)>
bool log_warning_if_over, bool on_conceal)>
ReclaimMemoryFunc;

// Set a callback that the loader will query to determine if the URL is safe
Expand All @@ -419,7 +422,7 @@ class ResourceCacheBase {
uint32 capacity() const { return cache_capacity_; }
void SetCapacity(uint32 capacity);

void Purge();
void Purge(bool on_conceal = false);

// Processes all pending callbacks regardless of the state of
// |callback_blocking_loading_resource_set_|.
Expand Down Expand Up @@ -508,6 +511,7 @@ class ResourceCacheBase {
bool is_processing_pending_callbacks_ = false;
// Whether or not callbacks are currently disabled.
bool are_callbacks_disabled_ = false;
bool is_concealed_ = false;

base::CVal<base::cval::SizeInBytes, base::CValPublic> memory_size_in_bytes_;
base::CVal<base::cval::SizeInBytes, base::CValPublic>
Expand Down Expand Up @@ -570,6 +574,11 @@ class ResourceCache : public ResourceCacheBase {
// all unreferenced resources are released.
std::unique_ptr<WeakCachedResourceType> CreateWeakCachedResource(
const scoped_refptr<CachedResourceType>& cached_resource);
void OnReveal() {
for (auto& it : cached_resource_map_) {
it.second->SetIsConcealed(false);
}
}

private:
typedef base::hash_map<std::string, CachedResourceType*> CachedResourceMap;
Expand Down Expand Up @@ -601,7 +610,8 @@ class ResourceCache : public ResourceCacheBase {
// Releases unreferenced cache objects until our total cache memory usage is
// less than or equal to |bytes_to_reclaim_down_to|, or until there are no
// more unreferenced cache objects to release.
void ReclaimMemory(uint32 bytes_to_reclaim_down_to, bool log_warning_if_over);
void ReclaimMemory(uint32 bytes_to_reclaim_down_to, bool log_warning_if_over,
bool on_conceal = false);

const CreateLoaderFunction create_loader_function_;
const NotifyResourceRequestedFunction notify_resource_requested_function_;
Expand Down Expand Up @@ -907,12 +917,19 @@ void ResourceCache<CacheType>::NotifyWeakResourceDestroyed(

template <typename CacheType>
void ResourceCache<CacheType>::ReclaimMemory(uint32 bytes_to_reclaim_down_to,
bool log_warning_if_over) {
bool log_warning_if_over,
bool on_conceal) {
DCHECK_CALLED_ON_VALID_THREAD(resource_cache_thread_checker_);

ResourceMap* resource_maps[] = {&unreferenced_cached_resource_map_,
&weak_referenced_cached_resource_map_};

if (on_conceal) {
for (auto& it : cached_resource_map_) {
it.second->SetIsConcealed(true);
}
}

for (size_t i = 0; i < SB_ARRAY_SIZE(resource_maps); ++i) {
while (memory_size_in_bytes_ > bytes_to_reclaim_down_to &&
!resource_maps[i]->empty()) {
Expand Down

0 comments on commit e83b8ad

Please sign in to comment.