+2015-09-17 Dean Jackson <dino@apple.com>
+
+ Cyclic resources were not detected if the reference had deep containers
+ https://bugs.webkit.org/show_bug.cgi?id=149182
+
+ Reviewed by John Honeycutt.
+
+ During our examination of the SVG rendering tree looking for cycles,
+ if a resource pointed to something that had a nested structure, and
+ one of the parent nodes in that structure was a container object
+ without resources itself, we were not looking into the children.
+
+ Test: svg/custom/pattern-content-cycle-w-resourceless-container.html
+
+ * rendering/svg/SVGResourcesCycleSolver.cpp:
+ (WebCore::SVGResourcesCycleSolver::resourceContainsCycles): We should still
+ check all children resources, but not exit early if there are none. Instead
+ we should recurse into any children.
+ (WebCore::SVGResourcesCycleSolver::resolveCycles): Changes to some debug
+ code that no longer compiled (it's still off by default, but at least
+ it will work now).
+
2015-09-17 Myles C. Maxfield <mmaxfield@apple.com>
REGRESSION(r188871): 50% regression in page load time of Wikipedia home page
HashSet<RenderSVGResourceContainer*> resourceSet;
resources->buildSetOfResources(resourceSet);
- // Walk all resources and check wheter they reference any resource contained in the resources set.
+ // Walk all resources and check whether they reference any resource contained in the resources set.
for (auto* resource : resourceSet) {
if (m_allResources.contains(resource))
return true;
// <marker id="a"> <path marker-start="url(#b)"/> ...
// <marker id="b"> <path marker-start="url(#a)"/> ...
for (auto& child : childrenOfType<RenderElement>(renderer)) {
- auto* childResources = SVGResourcesCache::cachedResourcesForRenderer(child);
- if (!childResources)
- continue;
-
- // A child of the given 'resource' contains resources.
- HashSet<RenderSVGResourceContainer*> childResourceSet;
- childResources->buildSetOfResources(childResourceSet);
-
- // Walk all child resources and check wheter they reference any resource contained in the resources set.
- for (auto* resource : childResourceSet) {
- if (m_allResources.contains(resource))
- return true;
+ if (auto* childResources = SVGResourcesCache::cachedResourcesForRenderer(child)) {
+ // A child of the given 'resource' contains resources.
+ HashSet<RenderSVGResourceContainer*> childResourceSet;
+ childResources->buildSetOfResources(childResourceSet);
+
+ // Walk all child resources and check whether they reference any resource contained in the resources set.
+ for (auto* resource : childResourceSet) {
+ if (m_allResources.contains(resource))
+ return true;
+ }
}
// Walk children recursively, stop immediately if we found a cycle
ancestorResources.add(&resource);
#if DEBUG_CYCLE_DETECTION > 0
- fprintf(stderr, "\nDetecting wheter any resources references any of following objects:\n");
+ fprintf(stderr, "\nDetecting whether any resources references any of following objects:\n");
{
fprintf(stderr, "Local resources:\n");
- for (auto* resource : localResources)
- fprintf(stderr, "|> %s: object=%p (node=%p)\n", resource->renderName(), resource, resource->node());
+ for (RenderObject* resource : localResources)
+ fprintf(stderr, "|> %s : %p (node %p)\n", resource->renderName(), resource, resource->node());
fprintf(stderr, "Parent resources:\n");
- for (auto* resource : ancestorResources)
- fprintf(stderr, "|> %s: object=%p (node=%p)\n", resource->renderName(), resource, resource->node());
+ for (RenderObject* resource : ancestorResources)
+ fprintf(stderr, "|> %s : %p (node %p)\n", resource->renderName(), resource, resource->node());
}
#endif
ASSERT(!m_allResources.isEmpty());
// The job of this function is to determine wheter any of the 'resources' associated with the given 'renderer'
- // references us (or wheter any of its kids references us) -> that's a cycle, we need to find and break it.
+ // references us (or whether any of its kids references us) -> that's a cycle, we need to find and break it.
for (auto* resource : localResources) {
if (ancestorResources.contains(resource) || resourceContainsCycles(*resource))
breakCycle(*resource);
#if DEBUG_CYCLE_DETECTION > 0
fprintf(stderr, "\nAfter cycle detection:\n");
- m_resources.dump(m_renderer);
+ m_resources.dump(&m_renderer);
#endif
m_allResources.clear();