| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
| 3 * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com) | 3 * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com) |
| 4 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com) | 4 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com) |
| 5 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All r
ights reserved. | 5 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All r
ights reserved. |
| 6 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> | 6 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> |
| 7 * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org> | 7 * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org> |
| 8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t
orchmobile.com/) | 8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t
orchmobile.com/) |
| 9 * Copyright (c) 2011, Code Aurora Forum. All rights reserved. | 9 * Copyright (c) 2011, Code Aurora Forum. All rights reserved. |
| 10 * Copyright (C) Research In Motion Limited 2011. All rights reserved. | 10 * Copyright (C) Research In Motion Limited 2011. All rights reserved. |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 201 collectionMode = ProcessClasses; | 201 collectionMode = ProcessClasses; |
| 202 collectFeaturesFromSelector(ruleData.selector(), metadata, collectionMode); | 202 collectFeaturesFromSelector(ruleData.selector(), metadata, collectionMode); |
| 203 m_metadata.add(metadata); | 203 m_metadata.add(metadata); |
| 204 | 204 |
| 205 if (metadata.foundSiblingSelector) | 205 if (metadata.foundSiblingSelector) |
| 206 siblingRules.append(RuleFeature(ruleData.rule(), ruleData.selectorIndex(
), ruleData.hasDocumentSecurityOrigin())); | 206 siblingRules.append(RuleFeature(ruleData.rule(), ruleData.selectorIndex(
), ruleData.hasDocumentSecurityOrigin())); |
| 207 if (ruleData.containsUncommonAttributeSelector()) | 207 if (ruleData.containsUncommonAttributeSelector()) |
| 208 uncommonAttributeRules.append(RuleFeature(ruleData.rule(), ruleData.sele
ctorIndex(), ruleData.hasDocumentSecurityOrigin())); | 208 uncommonAttributeRules.append(RuleFeature(ruleData.rule(), ruleData.sele
ctorIndex(), ruleData.hasDocumentSecurityOrigin())); |
| 209 } | 209 } |
| 210 | 210 |
| 211 bool RuleFeatureSet::classInvalidationRequiresSubtreeRecalc(const AtomicString&
className) | |
| 212 { | |
| 213 DescendantInvalidationSet* set = m_classInvalidationSets.get(className); | |
| 214 return set && set->wholeSubtreeInvalid(); | |
| 215 } | |
| 216 | |
| 217 DescendantInvalidationSet& RuleFeatureSet::ensureClassInvalidationSet(const Atom
icString& className) | 211 DescendantInvalidationSet& RuleFeatureSet::ensureClassInvalidationSet(const Atom
icString& className) |
| 218 { | 212 { |
| 219 InvalidationSetMap::AddResult addResult = m_classInvalidationSets.add(classN
ame, nullptr); | 213 InvalidationSetMap::AddResult addResult = m_classInvalidationSets.add(classN
ame, nullptr); |
| 220 if (addResult.isNewEntry) | 214 if (addResult.isNewEntry) |
| 221 addResult.storedValue->value = DescendantInvalidationSet::create(); | 215 addResult.storedValue->value = DescendantInvalidationSet::create(); |
| 222 return *addResult.storedValue->value; | 216 return *addResult.storedValue->value; |
| 223 } | 217 } |
| 224 | 218 |
| 225 void RuleFeatureSet::collectFeaturesFromSelector(const CSSSelector& selector) | 219 void RuleFeatureSet::collectFeaturesFromSelector(const CSSSelector& selector) |
| 226 { | 220 { |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 304 | 298 |
| 305 void RuleFeatureSet::clear() | 299 void RuleFeatureSet::clear() |
| 306 { | 300 { |
| 307 m_metadata.clear(); | 301 m_metadata.clear(); |
| 308 siblingRules.clear(); | 302 siblingRules.clear(); |
| 309 uncommonAttributeRules.clear(); | 303 uncommonAttributeRules.clear(); |
| 310 } | 304 } |
| 311 | 305 |
| 312 void RuleFeatureSet::scheduleStyleInvalidationForClassChange(const SpaceSplitStr
ing& changedClasses, Element* element) | 306 void RuleFeatureSet::scheduleStyleInvalidationForClassChange(const SpaceSplitStr
ing& changedClasses, Element* element) |
| 313 { | 307 { |
| 314 if (computeInvalidationSetsForClassChange(changedClasses, element)) { | 308 unsigned changedSize = changedClasses.size(); |
| 315 // FIXME: remove eager calls to setNeedsStyleRecalc here, and instead re
use the invalidation tree walk. | 309 for (unsigned i = 0; i < changedSize; ++i) { |
| 316 // This code remains for now out of conservatism about avoiding performa
nce regressions before TargetedStyleRecalc is launched. | 310 addClassToInvalidationSet(changedClasses[i], element); |
| 317 element->setNeedsStyleRecalc(SubtreeStyleChange); | |
| 318 } | 311 } |
| 319 } | 312 } |
| 320 | 313 |
| 321 void RuleFeatureSet::scheduleStyleInvalidationForClassChange(const SpaceSplitStr
ing& oldClasses, const SpaceSplitString& newClasses, Element* element) | 314 void RuleFeatureSet::scheduleStyleInvalidationForClassChange(const SpaceSplitStr
ing& oldClasses, const SpaceSplitString& newClasses, Element* element) |
| 322 { | 315 { |
| 323 if (computeInvalidationSetsForClassChange(oldClasses, newClasses, element))
{ | |
| 324 // FIXME: remove eager calls to setNeedsStyleRecalc here, and instead re
use the invalidation tree walk. | |
| 325 // This code remains for now out of conservatism about avoiding performa
nce regressions before TargetedStyleRecalc is launched. | |
| 326 element->setNeedsStyleRecalc(SubtreeStyleChange); | |
| 327 } | |
| 328 } | |
| 329 | |
| 330 bool RuleFeatureSet::computeInvalidationSetsForClassChange(const SpaceSplitStrin
g& changedClasses, Element* element) | |
| 331 { | |
| 332 unsigned changedSize = changedClasses.size(); | |
| 333 for (unsigned i = 0; i < changedSize; ++i) { | |
| 334 if (classInvalidationRequiresSubtreeRecalc(changedClasses[i])) | |
| 335 return true; | |
| 336 addClassToInvalidationSet(changedClasses[i], element); | |
| 337 } | |
| 338 return false; | |
| 339 } | |
| 340 | |
| 341 bool RuleFeatureSet::computeInvalidationSetsForClassChange(const SpaceSplitStrin
g& oldClasses, const SpaceSplitString& newClasses, Element* element) | |
| 342 { | |
| 343 if (!oldClasses.size()) | 316 if (!oldClasses.size()) |
| 344 return computeInvalidationSetsForClassChange(newClasses, element); | 317 scheduleStyleInvalidationForClassChange(newClasses, element); |
| 345 | 318 |
| 346 // Class vectors tend to be very short. This is faster than using a hash tab
le. | 319 // Class vectors tend to be very short. This is faster than using a hash tab
le. |
| 347 BitVector remainingClassBits; | 320 BitVector remainingClassBits; |
| 348 remainingClassBits.ensureSize(oldClasses.size()); | 321 remainingClassBits.ensureSize(oldClasses.size()); |
| 349 | 322 |
| 350 for (unsigned i = 0; i < newClasses.size(); ++i) { | 323 for (unsigned i = 0; i < newClasses.size(); ++i) { |
| 351 bool found = false; | 324 bool found = false; |
| 352 for (unsigned j = 0; j < oldClasses.size(); ++j) { | 325 for (unsigned j = 0; j < oldClasses.size(); ++j) { |
| 353 if (newClasses[i] == oldClasses[j]) { | 326 if (newClasses[i] == oldClasses[j]) { |
| 354 // Mark each class that is still in the newClasses so we can ski
p doing | 327 // Mark each class that is still in the newClasses so we can ski
p doing |
| 355 // an n^2 search below when looking for removals. We can't break
from | 328 // an n^2 search below when looking for removals. We can't break
from |
| 356 // this loop early since a class can appear more than once. | 329 // this loop early since a class can appear more than once. |
| 357 remainingClassBits.quickSet(j); | 330 remainingClassBits.quickSet(j); |
| 358 found = true; | 331 found = true; |
| 359 } | 332 } |
| 360 } | 333 } |
| 361 // Class was added. | 334 // Class was added. |
| 362 if (!found) { | 335 if (!found) |
| 363 if (classInvalidationRequiresSubtreeRecalc(newClasses[i])) | |
| 364 return true; | |
| 365 addClassToInvalidationSet(newClasses[i], element); | 336 addClassToInvalidationSet(newClasses[i], element); |
| 366 } | |
| 367 } | 337 } |
| 368 | 338 |
| 369 for (unsigned i = 0; i < oldClasses.size(); ++i) { | 339 for (unsigned i = 0; i < oldClasses.size(); ++i) { |
| 370 if (remainingClassBits.quickGet(i)) | 340 if (remainingClassBits.quickGet(i)) |
| 371 continue; | 341 continue; |
| 372 | |
| 373 // Class was removed. | 342 // Class was removed. |
| 374 if (classInvalidationRequiresSubtreeRecalc(oldClasses[i])) | |
| 375 return true; | |
| 376 addClassToInvalidationSet(oldClasses[i], element); | 343 addClassToInvalidationSet(oldClasses[i], element); |
| 377 } | 344 } |
| 378 return false; | |
| 379 } | 345 } |
| 380 | 346 |
| 381 void RuleFeatureSet::addClassToInvalidationSet(const AtomicString& className, El
ement* element) | 347 void RuleFeatureSet::addClassToInvalidationSet(const AtomicString& className, El
ement* element) |
| 382 { | 348 { |
| 383 if (RefPtr<DescendantInvalidationSet> invalidationSet = m_classInvalidationS
ets.get(className)) { | 349 if (RefPtr<DescendantInvalidationSet> invalidationSet = m_classInvalidationS
ets.get(className)) { |
| 384 ensurePendingInvalidationList(element).append(invalidationSet); | 350 ensurePendingInvalidationList(element).append(invalidationSet); |
| 385 element->setNeedsStyleInvalidation(); | 351 element->setNeedsStyleInvalidation(); |
| 386 } | 352 } |
| 387 } | 353 } |
| 388 | 354 |
| 389 RuleFeatureSet::InvalidationList& RuleFeatureSet::ensurePendingInvalidationList(
Element* element) | 355 RuleFeatureSet::InvalidationList& RuleFeatureSet::ensurePendingInvalidationList(
Element* element) |
| 390 { | 356 { |
| 391 PendingInvalidationMap::AddResult addResult = m_pendingInvalidationMap.add(e
lement, nullptr); | 357 PendingInvalidationMap::AddResult addResult = m_pendingInvalidationMap.add(e
lement, nullptr); |
| 392 if (addResult.isNewEntry) | 358 if (addResult.isNewEntry) |
| 393 addResult.storedValue->value = adoptPtr(new InvalidationList); | 359 addResult.storedValue->value = adoptPtr(new InvalidationList); |
| 394 return *addResult.storedValue->value; | 360 return *addResult.storedValue->value; |
| 395 } | 361 } |
| 396 | 362 |
| 397 void RuleFeatureSet::computeStyleInvalidation(Document& document) | 363 void RuleFeatureSet::computeStyleInvalidation(Document& document) |
| 398 { | 364 { |
| 399 Vector<AtomicString> invalidationClasses; | 365 Vector<AtomicString> invalidationClasses; |
| 400 if (Element* documentElement = document.documentElement()) { | 366 if (Element* documentElement = document.documentElement()) { |
| 401 if (documentElement->childNeedsStyleInvalidation()) { | 367 if (documentElement->childNeedsStyleInvalidation()) { |
| 402 invalidateStyleForClassChange(documentElement, invalidationClasses,
false); | 368 invalidateStyleForClassChange(documentElement, invalidationClasses,
false); |
| 403 } | 369 } |
| 404 } | 370 } |
| 405 document.clearChildNeedsStyleInvalidation(); | 371 document.clearChildNeedsStyleInvalidation(); |
| 372 document.clearNeedsStyleInvalidation(); |
| 406 m_pendingInvalidationMap.clear(); | 373 m_pendingInvalidationMap.clear(); |
| 407 } | 374 } |
| 408 | 375 |
| 409 bool RuleFeatureSet::invalidateStyleForClassChangeOnChildren(Element* element, V
ector<AtomicString>& invalidationClasses, bool foundInvalidationSet) | 376 bool RuleFeatureSet::invalidateStyleForClassChangeOnChildren(Element* element, V
ector<AtomicString>& invalidationClasses, bool foundInvalidationSet) |
| 410 { | 377 { |
| 411 bool someChildrenNeedStyleRecalc = false; | 378 bool someChildrenNeedStyleRecalc = false; |
| 412 for (ShadowRoot* root = element->youngestShadowRoot(); root; root = root->ol
derShadowRoot()) { | 379 for (ShadowRoot* root = element->youngestShadowRoot(); root; root = root->ol
derShadowRoot()) { |
| 413 for (Element* child = ElementTraversal::firstWithin(*root); child; child
= ElementTraversal::nextSibling(*child)) { | 380 for (Element* child = ElementTraversal::firstWithin(*root); child; child
= ElementTraversal::nextSibling(*child)) { |
| 414 bool childRecalced = invalidateStyleForClassChange(child, invalidati
onClasses, foundInvalidationSet); | 381 bool childRecalced = invalidateStyleForClassChange(child, invalidati
onClasses, foundInvalidationSet); |
| 415 someChildrenNeedStyleRecalc = someChildrenNeedStyleRecalc || childRe
calced; | 382 someChildrenNeedStyleRecalc = someChildrenNeedStyleRecalc || childRe
calced; |
| 416 } | 383 } |
| 417 } | 384 } |
| 418 for (Element* child = ElementTraversal::firstWithin(*element); child; child
= ElementTraversal::nextSibling(*child)) { | 385 for (Element* child = ElementTraversal::firstWithin(*element); child; child
= ElementTraversal::nextSibling(*child)) { |
| 419 bool childRecalced = invalidateStyleForClassChange(child, invalidationCl
asses, foundInvalidationSet); | 386 bool childRecalced = invalidateStyleForClassChange(child, invalidationCl
asses, foundInvalidationSet); |
| 420 someChildrenNeedStyleRecalc = someChildrenNeedStyleRecalc || childRecalc
ed; | 387 someChildrenNeedStyleRecalc = someChildrenNeedStyleRecalc || childRecalc
ed; |
| 421 } | 388 } |
| 422 return someChildrenNeedStyleRecalc; | 389 return someChildrenNeedStyleRecalc; |
| 423 } | 390 } |
| 424 | 391 |
| 425 bool RuleFeatureSet::invalidateStyleForClassChange(Element* element, Vector<Atom
icString>& invalidationClasses, bool foundInvalidationSet) | 392 bool RuleFeatureSet::invalidateStyleForClassChange(Element* element, Vector<Atom
icString>& invalidationClasses, bool foundInvalidationSet) |
| 426 { | 393 { |
| 427 bool thisElementNeedsStyleRecalc = false; | 394 bool thisElementNeedsStyleRecalc = false; |
| 428 int oldSize = invalidationClasses.size(); | 395 int oldSize = invalidationClasses.size(); |
| 429 | |
| 430 if (element->needsStyleInvalidation()) { | 396 if (element->needsStyleInvalidation()) { |
| 431 InvalidationList* invalidationList = m_pendingInvalidationMap.get(elemen
t); | 397 if (InvalidationList* invalidationList = m_pendingInvalidationMap.get(el
ement)) { |
| 432 ASSERT(invalidationList); | 398 // FIXME: it's really only necessary to clone the render style for t
his element, not full style recalc. |
| 433 // FIXME: it's really only necessary to clone the render style for this
element, not full style recalc. | 399 thisElementNeedsStyleRecalc = true; |
| 434 thisElementNeedsStyleRecalc = true; | 400 foundInvalidationSet = true; |
| 435 foundInvalidationSet = true; | 401 for (InvalidationList::const_iterator it = invalidationList->begin()
; it != invalidationList->end(); ++it) { |
| 436 for (InvalidationList::const_iterator it = invalidationList->begin(); it
!= invalidationList->end(); ++it) { | 402 if ((*it)->wholeSubtreeInvalid()) { |
| 437 if ((*it)->wholeSubtreeInvalid()) { | 403 element->setNeedsStyleRecalc(SubtreeStyleChange); |
| 438 element->setNeedsStyleRecalc(SubtreeStyleChange); | 404 // Even though we have set needsStyleRecalc on the whole sub
tree, we need to keep walking over the subtree |
| 439 // Even though we have set needsStyleRecalc on the whole subtree
, we need to keep walking over the subtree | 405 // in order to clear the invalidation dirty bits on all elem
ents. |
| 440 // in order to clear the invalidation dirty bits on all elements
. | 406 // FIXME: we can optimize this by having a dedicated functio
n that just traverses the tree and removes the dirty bits, |
| 441 // FIXME: we can optimize this by having a dedicated function th
at just traverses the tree and removes the dirty bits, | 407 // without checking classes etc. |
| 442 // without checking classes etc. | 408 break; |
| 443 break; | 409 } |
| 410 (*it)->getClasses(invalidationClasses); |
| 444 } | 411 } |
| 445 (*it)->getClasses(invalidationClasses); | |
| 446 } | 412 } |
| 447 } | 413 } |
| 448 | 414 |
| 449 if (element->hasClass()) { | 415 if (element->hasClass()) { |
| 450 const SpaceSplitString& classNames = element->classNames(); | 416 const SpaceSplitString& classNames = element->classNames(); |
| 451 for (Vector<AtomicString>::const_iterator it = invalidationClasses.begin
(); it != invalidationClasses.end(); ++it) { | 417 for (Vector<AtomicString>::const_iterator it = invalidationClasses.begin
(); it != invalidationClasses.end(); ++it) { |
| 452 if (classNames.contains(*it)) { | 418 if (classNames.contains(*it)) { |
| 453 thisElementNeedsStyleRecalc = true; | 419 thisElementNeedsStyleRecalc = true; |
| 454 break; | 420 break; |
| 455 } | 421 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 472 } | 438 } |
| 473 | 439 |
| 474 invalidationClasses.remove(oldSize, invalidationClasses.size() - oldSize); | 440 invalidationClasses.remove(oldSize, invalidationClasses.size() - oldSize); |
| 475 element->clearChildNeedsStyleInvalidation(); | 441 element->clearChildNeedsStyleInvalidation(); |
| 476 element->clearNeedsStyleInvalidation(); | 442 element->clearNeedsStyleInvalidation(); |
| 477 | 443 |
| 478 return thisElementNeedsStyleRecalc; | 444 return thisElementNeedsStyleRecalc; |
| 479 } | 445 } |
| 480 | 446 |
| 481 } // namespace WebCore | 447 } // namespace WebCore |
| OLD | NEW |