📄 cache.cpp
字号:
m_inPruneDeadResources = false;}void Cache::setCapacities(unsigned minDeadBytes, unsigned maxDeadBytes, unsigned totalBytes){ ASSERT(minDeadBytes <= maxDeadBytes); ASSERT(maxDeadBytes <= totalBytes); m_minDeadCapacity = minDeadBytes; m_maxDeadCapacity = maxDeadBytes; m_capacity = totalBytes; prune();}void Cache::evict(CachedResource* resource){ // The resource may have already been removed by someone other than our caller, // who needed a fresh copy for a reload. See <http://bugs.webkit.org/show_bug.cgi?id=12479#c6>. if (resource->inCache()) { if (!resource->isCacheValidator()) { // Notify all doc loaders that might be observing this object still that it has been // extracted from the set of resources. // No need to do this for cache validator resources, they are replaced automatically by using CachedResourceHandles. HashSet<DocLoader*>::iterator end = m_docLoaders.end(); for (HashSet<DocLoader*>::iterator itr = m_docLoaders.begin(); itr != end; ++itr) (*itr)->removeCachedResource(resource); } // Remove from the resource map. m_resources.remove(resource->url()); resource->setInCache(false); // Remove from the appropriate LRU list. removeFromLRUList(resource); removeFromLiveDecodedResourcesList(resource); // Subtract from our size totals. int delta = -static_cast<int>(resource->size()); if (delta) adjustSize(resource->hasClients(), delta); } else ASSERT(m_resources.get(resource->url()) != resource); if (resource->canDelete()) delete resource;}void Cache::addDocLoader(DocLoader* docLoader){ m_docLoaders.add(docLoader);}void Cache::removeDocLoader(DocLoader* docLoader){ m_docLoaders.remove(docLoader);}static inline unsigned fastLog2(unsigned i){ unsigned log2 = 0; if (i & (i - 1)) log2 += 1; if (i >> 16) log2 += 16, i >>= 16; if (i >> 8) log2 += 8, i >>= 8; if (i >> 4) log2 += 4, i >>= 4; if (i >> 2) log2 += 2, i >>= 2; if (i >> 1) log2 += 1; return log2;}Cache::LRUList* Cache::lruListFor(CachedResource* resource){ unsigned accessCount = max(resource->accessCount(), 1U); unsigned queueIndex = fastLog2(resource->size() / accessCount);#ifndef NDEBUG resource->m_lruIndex = queueIndex;#endif if (m_allResources.size() <= queueIndex) m_allResources.grow(queueIndex + 1); return &m_allResources[queueIndex];}void Cache::removeFromLRUList(CachedResource* resource){ // If we've never been accessed, then we're brand new and not in any list. if (resource->accessCount() == 0) return;#ifndef NDEBUG unsigned oldListIndex = resource->m_lruIndex;#endif LRUList* list = lruListFor(resource);#ifndef NDEBUG // Verify that the list we got is the list we want. ASSERT(resource->m_lruIndex == oldListIndex); // Verify that we are in fact in this list. bool found = false; for (CachedResource* current = list->m_head; current; current = current->m_nextInAllResourcesList) { if (current == resource) { found = true; break; } } ASSERT(found);#endif CachedResource* next = resource->m_nextInAllResourcesList; CachedResource* prev = resource->m_prevInAllResourcesList; if (next == 0 && prev == 0 && list->m_head != resource) return; resource->m_nextInAllResourcesList = 0; resource->m_prevInAllResourcesList = 0; if (next) next->m_prevInAllResourcesList = prev; else if (list->m_tail == resource) list->m_tail = prev; if (prev) prev->m_nextInAllResourcesList = next; else if (list->m_head == resource) list->m_head = next;}void Cache::insertInLRUList(CachedResource* resource){ // Make sure we aren't in some list already. ASSERT(!resource->m_nextInAllResourcesList && !resource->m_prevInAllResourcesList); ASSERT(resource->inCache()); ASSERT(resource->accessCount() > 0); LRUList* list = lruListFor(resource); resource->m_nextInAllResourcesList = list->m_head; if (list->m_head) list->m_head->m_prevInAllResourcesList = resource; list->m_head = resource; if (!resource->m_nextInAllResourcesList) list->m_tail = resource; #ifndef NDEBUG // Verify that we are in now in the list like we should be. list = lruListFor(resource); bool found = false; for (CachedResource* current = list->m_head; current; current = current->m_nextInAllResourcesList) { if (current == resource) { found = true; break; } } ASSERT(found);#endif}void Cache::resourceAccessed(CachedResource* resource){ ASSERT(resource->inCache()); // Need to make sure to remove before we increase the access count, since // the queue will possibly change. removeFromLRUList(resource); // If this is the first time the resource has been accessed, adjust the size of the cache to account for its initial size. if (!resource->accessCount()) adjustSize(resource->hasClients(), resource->size()); // Add to our access count. resource->increaseAccessCount(); // Now insert into the new queue. insertInLRUList(resource);}void Cache::removeFromLiveDecodedResourcesList(CachedResource* resource){ // If we've never been accessed, then we're brand new and not in any list. if (!resource->m_inLiveDecodedResourcesList) return; resource->m_inLiveDecodedResourcesList = false;#ifndef NDEBUG // Verify that we are in fact in this list. bool found = false; for (CachedResource* current = m_liveDecodedResources.m_head; current; current = current->m_nextInLiveResourcesList) { if (current == resource) { found = true; break; } } ASSERT(found);#endif CachedResource* next = resource->m_nextInLiveResourcesList; CachedResource* prev = resource->m_prevInLiveResourcesList; if (next == 0 && prev == 0 && m_liveDecodedResources.m_head != resource) return; resource->m_nextInLiveResourcesList = 0; resource->m_prevInLiveResourcesList = 0; if (next) next->m_prevInLiveResourcesList = prev; else if (m_liveDecodedResources.m_tail == resource) m_liveDecodedResources.m_tail = prev; if (prev) prev->m_nextInLiveResourcesList = next; else if (m_liveDecodedResources.m_head == resource) m_liveDecodedResources.m_head = next;}void Cache::insertInLiveDecodedResourcesList(CachedResource* resource){ // Make sure we aren't in the list already. ASSERT(!resource->m_nextInLiveResourcesList && !resource->m_prevInLiveResourcesList && !resource->m_inLiveDecodedResourcesList); resource->m_inLiveDecodedResourcesList = true; resource->m_nextInLiveResourcesList = m_liveDecodedResources.m_head; if (m_liveDecodedResources.m_head) m_liveDecodedResources.m_head->m_prevInLiveResourcesList = resource; m_liveDecodedResources.m_head = resource; if (!resource->m_nextInLiveResourcesList) m_liveDecodedResources.m_tail = resource; #ifndef NDEBUG // Verify that we are in now in the list like we should be. bool found = false; for (CachedResource* current = m_liveDecodedResources.m_head; current; current = current->m_nextInLiveResourcesList) { if (current == resource) { found = true; break; } } ASSERT(found);#endif}void Cache::addToLiveResourcesSize(CachedResource* resource){ m_liveSize += resource->size(); m_deadSize -= resource->size();}void Cache::removeFromLiveResourcesSize(CachedResource* resource){ m_liveSize -= resource->size(); m_deadSize += resource->size();}void Cache::adjustSize(bool live, int delta){ if (live) { ASSERT(delta >= 0 || ((int)m_liveSize + delta >= 0)); m_liveSize += delta; } else { ASSERT(delta >= 0 || ((int)m_deadSize + delta >= 0)); m_deadSize += delta; }}void Cache::TypeStatistic::addResource(CachedResource* o){ bool purged = o->wasPurged(); bool purgeable = o->isPurgeable() && !purged; int pageSize = (o->encodedSize() + o->overheadSize() + 4095) & ~4095; count++; size += purged ? 0 : o->size(); liveSize += o->hasClients() ? o->size() : 0; decodedSize += o->decodedSize(); purgeableSize += purgeable ? pageSize : 0; purgedSize += purged ? pageSize : 0;}Cache::Statistics Cache::getStatistics(){ Statistics stats; CachedResourceMap::iterator e = m_resources.end(); for (CachedResourceMap::iterator i = m_resources.begin(); i != e; ++i) { CachedResource* resource = i->second; switch (resource->type()) { case CachedResource::ImageResource: stats.images.addResource(resource); break; case CachedResource::CSSStyleSheet: stats.cssStyleSheets.addResource(resource); break; case CachedResource::Script: stats.scripts.addResource(resource); break;#if ENABLE(XSLT) case CachedResource::XSLStyleSheet: stats.xslStyleSheets.addResource(resource); break;#endif case CachedResource::FontResource: stats.fonts.addResource(resource); break;#if ENABLE(XBL) case CachedResource::XBL: stats.xblDocs.addResource(resource) break;#endif default: break; } } return stats;}void Cache::setDisabled(bool disabled){ m_disabled = disabled; if (!m_disabled) return; for (;;) { CachedResourceMap::iterator i = m_resources.begin(); if (i == m_resources.end()) break; evict(i->second); }}#ifndef NDEBUGvoid Cache::dumpStats(){ Statistics s = getStatistics(); printf("%-11s %-11s %-11s %-11s %-11s %-11s %-11s\n", "", "Count", "Size", "LiveSize", "DecodedSize", "PurgeableSize", "PurgedSize"); printf("%-11s %-11s %-11s %-11s %-11s %-11s %-11s\n", "-----------", "-----------", "-----------", "-----------", "-----------", "-----------", "-----------"); printf("%-11s %11d %11d %11d %11d %11d %11d\n", "Images", s.images.count, s.images.size, s.images.liveSize, s.images.decodedSize, s.images.purgeableSize, s.images.purgedSize); printf("%-11s %11d %11d %11d %11d %11d %11d\n", "CSS", s.cssStyleSheets.count, s.cssStyleSheets.size, s.cssStyleSheets.liveSize, s.cssStyleSheets.decodedSize, s.cssStyleSheets.purgeableSize, s.cssStyleSheets.purgedSize);#if ENABLE(XSLT) printf("%-11s %11d %11d %11d %11d %11d %11d\n", "XSL", s.xslStyleSheets.count, s.xslStyleSheets.size, s.xslStyleSheets.liveSize, s.xslStyleSheets.decodedSize, s.xslStyleSheets.purgeableSize, s.xslStyleSheets.purgedSize);#endif printf("%-11s %11d %11d %11d %11d %11d %11d\n", "JavaScript", s.scripts.count, s.scripts.size, s.scripts.liveSize, s.scripts.decodedSize, s.scripts.purgeableSize, s.scripts.purgedSize); printf("%-11s %11d %11d %11d %11d %11d %11d\n", "Fonts", s.fonts.count, s.fonts.size, s.fonts.liveSize, s.fonts.decodedSize, s.fonts.purgeableSize, s.fonts.purgedSize); printf("%-11s %-11s %-11s %-11s %-11s %-11s %-11s\n\n", "-----------", "-----------", "-----------", "-----------", "-----------", "-----------", "-----------");}void Cache::dumpLRULists(bool includeLive) const{ printf("LRU-SP lists in eviction order (Kilobytes decoded, Kilobytes encoded, Access count, Referenced):\n"); int size = m_allResources.size(); for (int i = size - 1; i >= 0; i--) { printf("\n\nList %d: ", i); CachedResource* current = m_allResources[i].m_tail; while (current) { CachedResource* prev = current->m_prevInAllResourcesList; if (includeLive || !current->hasClients()) printf("(%.1fK, %.1fK, %uA, %dR); ", current->decodedSize() / 1024.0f, (current->encodedSize() + current->overheadSize()) / 1024.0f, current->accessCount(), current->hasClients()); current = prev; } }}#endif} // namespace WebCore
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -