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 |