Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(392)

Side by Side Diff: Source/core/css/StyleSheetContents.cpp

Issue 196653006: Optimize StyleSheetContents::checkLoaded by keeping track of completed (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Use early return Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/css/StyleSheetContents.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * (C) 1999-2003 Lars Knoll (knoll@kde.org) 2 * (C) 1999-2003 Lars Knoll (knoll@kde.org)
3 * Copyright (C) 2004, 2006, 2007, 2012 Apple Inc. All rights reserved. 3 * Copyright (C) 2004, 2006, 2007, 2012 Apple Inc. All rights reserved.
4 * 4 *
5 * This library is free software; you can redistribute it and/or 5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public 6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either 7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version. 8 * version 2 of the License, or (at your option) any later version.
9 * 9 *
10 * This library is distributed in the hope that it will be useful, 10 * This library is distributed in the hope that it will be useful,
(...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after
367 return false; 367 return false;
368 } 368 }
369 369
370 bool StyleSheetContents::loadCompleted() const 370 bool StyleSheetContents::loadCompleted() const
371 { 371 {
372 StyleSheetContents* parentSheet = parentStyleSheet(); 372 StyleSheetContents* parentSheet = parentStyleSheet();
373 if (parentSheet) 373 if (parentSheet)
374 return parentSheet->loadCompleted(); 374 return parentSheet->loadCompleted();
375 375
376 StyleSheetContents* root = rootStyleSheet(); 376 StyleSheetContents* root = rootStyleSheet();
377 for (ClientsIterator it = root->m_clients.begin(); it != root->m_clients.end (); ++it) { 377 if (root->m_loadingClients.size())
378 if (!(*it)->loadCompleted()) 378 return false;
379 return false;
380 }
381 return true; 379 return true;
esprehn 2014/03/13 19:56:28 return rootStyleSheet()->m_loadingClients.isEmpty(
Mads Ager (chromium) 2014/03/14 09:30:18 Heh, yes, thanks!
382 } 380 }
383 381
384 void StyleSheetContents::checkLoaded() 382 void StyleSheetContents::checkLoaded()
385 { 383 {
386 if (isLoading()) 384 if (isLoading())
387 return; 385 return;
388 386
389 // Avoid |this| being deleted by scripts that run via 387 // Avoid |this| being deleted by scripts that run via
390 // ScriptableDocumentParser::executeScriptsWaitingForResources(). 388 // ScriptableDocumentParser::executeScriptsWaitingForResources().
391 // See https://bugs.webkit.org/show_bug.cgi?id=95106 389 // See https://bugs.webkit.org/show_bug.cgi?id=95106
392 RefPtrWillBeRawPtr<StyleSheetContents> protect(this); 390 RefPtrWillBeRawPtr<StyleSheetContents> protect(this);
393 391
394 StyleSheetContents* parentSheet = parentStyleSheet(); 392 StyleSheetContents* parentSheet = parentStyleSheet();
395 if (parentSheet) { 393 if (parentSheet) {
396 parentSheet->checkLoaded(); 394 parentSheet->checkLoaded();
397 return; 395 return;
398 } 396 }
399 397
400 StyleSheetContents* root = rootStyleSheet(); 398 StyleSheetContents* root = rootStyleSheet();
401 if (root->m_clients.isEmpty()) 399 if (root->m_loadingClients.isEmpty())
402 return; 400 return;
403 401
404 // Avoid |CSSSStyleSheet| and |ownerNode| being deleted by scripts that run via 402 // Avoid |CSSSStyleSheet| and |ownerNode| being deleted by scripts that run via
405 // ScriptableDocumentParser::executeScriptsWaitingForResources(). Also prote ct 403 // ScriptableDocumentParser::executeScriptsWaitingForResources(). Also prote ct
406 // the |CSSStyleSheet| from being deleted during iteration via the |sheetLoa ded| 404 // the |CSSStyleSheet| from being deleted during iteration via the |sheetLoa ded|
407 // method. 405 // method.
408 // 406 //
409 // FIXME: oilpan: with oilpan we do not need to protect the CSSStyleSheets 407 // FIXME: oilpan: with oilpan we do not need to protect the CSSStyleSheets
410 // explicitly during the iteration. The iterator will make the pointers 408 // explicitly during the iteration. The iterator will make the pointers
411 // strong during iteration so we can just directly iterate root->m_clients. 409 // strong during iteration so we can just directly iterate root->m_clients.
412 WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet>, 5> protectedClients; 410 WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> > protectedClients;
413 for (ClientsIterator it = root->m_clients.begin(); it != root->m_clients.end (); ++it) 411 protectedClients.reserveInitialCapacity(root->m_loadingClients.size());
412 for (ClientsIterator it = root->m_loadingClients.begin(); it != root->m_load ingClients.end(); ++it)
414 protectedClients.append(*it); 413 protectedClients.append(*it);
esprehn 2014/03/13 19:56:28 This should just use copyToVector()
Mads Ager (chromium) 2014/03/14 09:30:18 Oh, I didn't know about copyToVector. Much better!
415 414
416 for (unsigned i = 0; i < protectedClients.size(); ++i) { 415 for (unsigned i = 0; i < protectedClients.size(); ++i) {
417 if (protectedClients[i]->loadCompleted()) 416 if (protectedClients[i]->loadCompleted())
418 continue; 417 continue;
419 418
420 // sheetLoaded might be invoked after its owner node is removed from doc ument. 419 // sheetLoaded might be invoked after its owner node is removed from doc ument.
421 if (RefPtr<Node> ownerNode = protectedClients[i]->ownerNode()) { 420 if (RefPtr<Node> ownerNode = protectedClients[i]->ownerNode()) {
422 if (protectedClients[i]->sheetLoaded()) 421 if (protectedClients[i]->sheetLoaded())
423 ownerNode->notifyLoadedSheetAndAllCriticalSubresources(m_didLoad ErrorOccur); 422 ownerNode->notifyLoadedSheetAndAllCriticalSubresources(m_didLoad ErrorOccur);
424 } 423 }
425 } 424 }
426 } 425 }
427 426
428 void StyleSheetContents::notifyLoadedSheet(const CSSStyleSheetResource* sheet) 427 void StyleSheetContents::notifyLoadedSheet(const CSSStyleSheetResource* sheet)
429 { 428 {
430 ASSERT(sheet); 429 ASSERT(sheet);
431 m_didLoadErrorOccur |= sheet->errorOccurred(); 430 m_didLoadErrorOccur |= sheet->errorOccurred();
432 // updateLayoutIgnorePendingStyleSheets can cause us to create the RuleSet o n this 431 // updateLayoutIgnorePendingStyleSheets can cause us to create the RuleSet o n this
433 // sheet before its imports have loaded. So clear the RuleSet when the impor ts 432 // sheet before its imports have loaded. So clear the RuleSet when the impor ts
434 // load since the import's subrules are flattened into its parent sheet's Ru leSet. 433 // load since the import's subrules are flattened into its parent sheet's Ru leSet.
435 clearRuleSet(); 434 clearRuleSet();
436 } 435 }
437 436
438 void StyleSheetContents::startLoadingDynamicSheet() 437 void StyleSheetContents::startLoadingDynamicSheet()
439 { 438 {
440 StyleSheetContents* root = rootStyleSheet(); 439 StyleSheetContents* root = rootStyleSheet();
441 for (ClientsIterator it = root->m_clients.begin(); it != root->m_clients.end (); ++it) 440 for (ClientsIterator it = root->m_loadingClients.begin(); it != root->m_load ingClients.end(); ++it)
441 (*it)->startLoadingDynamicSheet();
442 for (ClientsIterator it = root->m_completedClients.begin(); it != root->m_co mpletedClients.end(); ++it)
442 (*it)->startLoadingDynamicSheet(); 443 (*it)->startLoadingDynamicSheet();
443 } 444 }
444 445
445 StyleSheetContents* StyleSheetContents::rootStyleSheet() const 446 StyleSheetContents* StyleSheetContents::rootStyleSheet() const
446 { 447 {
447 const StyleSheetContents* root = this; 448 const StyleSheetContents* root = this;
448 while (root->parentStyleSheet()) 449 while (root->parentStyleSheet())
449 root = root->parentStyleSheet(); 450 root = root->parentStyleSheet();
450 return const_cast<StyleSheetContents*>(root); 451 return const_cast<StyleSheetContents*>(root);
451 } 452 }
452 453
453 bool StyleSheetContents::hasSingleOwnerNode() const 454 bool StyleSheetContents::hasSingleOwnerNode() const
454 { 455 {
455 StyleSheetContents* root = rootStyleSheet(); 456 StyleSheetContents* root = rootStyleSheet();
456 if (root->m_clients.isEmpty()) 457 return root->hasOneClient();
esprehn 2014/03/13 19:56:28 rootStyleSheet()->hasOneClient()
Mads Ager (chromium) 2014/03/14 09:30:18 Done.
457 return false;
458 return root->m_clients.size() == 1;
459 } 458 }
460 459
461 Node* StyleSheetContents::singleOwnerNode() const 460 Node* StyleSheetContents::singleOwnerNode() const
462 { 461 {
463 StyleSheetContents* root = rootStyleSheet(); 462 StyleSheetContents* root = rootStyleSheet();
464 if (root->m_clients.isEmpty()) 463 if (root->hasOneClient()) {
465 return 0; 464 return root->m_loadingClients.size() ? (*root->m_loadingClients.begin()) ->ownerNode() : (*root->m_completedClients.begin())->ownerNode();
esprehn 2014/03/13 19:56:28 Lets break this up since it's easier to read. if
Mads Ager (chromium) 2014/03/14 09:30:18 Yes, much better, thanks.
466 ASSERT(root->m_clients.size() == 1); 465 }
467 return (*root->m_clients.begin())->ownerNode(); 466 ASSERT(root->m_loadingClients.isEmpty() && root->m_completedClients.isEmpty( ));
467 return 0;
468 } 468 }
469 469
470 Document* StyleSheetContents::singleOwnerDocument() const 470 Document* StyleSheetContents::singleOwnerDocument() const
471 { 471 {
472 Node* ownerNode = singleOwnerNode(); 472 Node* ownerNode = singleOwnerNode();
473 return ownerNode ? &ownerNode->document() : 0; 473 return ownerNode ? &ownerNode->document() : 0;
474 } 474 }
475 475
476 KURL StyleSheetContents::completeURL(const String& url) const 476 KURL StyleSheetContents::completeURL(const String& url) const
477 { 477 {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
518 return childRulesHaveFailedOrCanceledSubresources(m_childRules); 518 return childRulesHaveFailedOrCanceledSubresources(m_childRules);
519 } 519 }
520 520
521 StyleSheetContents* StyleSheetContents::parentStyleSheet() const 521 StyleSheetContents* StyleSheetContents::parentStyleSheet() const
522 { 522 {
523 return m_ownerRule ? m_ownerRule->parentStyleSheet() : 0; 523 return m_ownerRule ? m_ownerRule->parentStyleSheet() : 0;
524 } 524 }
525 525
526 void StyleSheetContents::registerClient(CSSStyleSheet* sheet) 526 void StyleSheetContents::registerClient(CSSStyleSheet* sheet)
527 { 527 {
528 ASSERT(!m_clients.contains(sheet)); 528 ASSERT(!m_loadingClients.contains(sheet) && !m_completedClients.contains(she et));
529 m_clients.add(sheet); 529 m_loadingClients.add(sheet);
esprehn 2014/03/13 19:56:28 Why is it a HashSet if you're just going to ASSERT
Mads Ager (chromium) 2014/03/14 09:30:18 The set of clients is a weak set. It does not keep
530 } 530 }
531 531
532 void StyleSheetContents::unregisterClient(CSSStyleSheet* sheet) 532 void StyleSheetContents::unregisterClient(CSSStyleSheet* sheet)
533 { 533 {
534 ASSERT(m_clients.contains(sheet)); 534 ASSERT(m_loadingClients.contains(sheet) || m_completedClients.contains(sheet ));
535 m_clients.remove(sheet); 535 m_loadingClients.remove(sheet);
536 m_completedClients.remove(sheet);
537 }
538
539 void StyleSheetContents::clientLoadCompleted(CSSStyleSheet* sheet)
540 {
541 ASSERT(m_loadingClients.contains(sheet));
542 m_loadingClients.remove(sheet);
543 m_completedClients.add(sheet);
544 }
545
546 void StyleSheetContents::clientLoadStarted(CSSStyleSheet* sheet)
547 {
548 ASSERT(m_completedClients.contains(sheet));
549 m_completedClients.remove(sheet);
550 m_loadingClients.add(sheet);
536 } 551 }
537 552
538 void StyleSheetContents::addedToMemoryCache() 553 void StyleSheetContents::addedToMemoryCache()
539 { 554 {
540 ASSERT(!m_isInMemoryCache); 555 ASSERT(!m_isInMemoryCache);
541 ASSERT(isCacheable()); 556 ASSERT(isCacheable());
542 m_isInMemoryCache = true; 557 m_isInMemoryCache = true;
543 } 558 }
544 559
545 void StyleSheetContents::removedFromMemoryCache() 560 void StyleSheetContents::removedFromMemoryCache()
(...skipping 11 matching lines...) Expand all
557 572
558 RuleSet& StyleSheetContents::ensureRuleSet(const MediaQueryEvaluator& medium, Ad dRuleFlags addRuleFlags) 573 RuleSet& StyleSheetContents::ensureRuleSet(const MediaQueryEvaluator& medium, Ad dRuleFlags addRuleFlags)
559 { 574 {
560 if (!m_ruleSet) { 575 if (!m_ruleSet) {
561 m_ruleSet = RuleSet::create(); 576 m_ruleSet = RuleSet::create();
562 m_ruleSet->addRulesFromSheet(this, medium, addRuleFlags); 577 m_ruleSet->addRulesFromSheet(this, medium, addRuleFlags);
563 } 578 }
564 return *m_ruleSet.get(); 579 return *m_ruleSet.get();
565 } 580 }
566 581
582 static void clearResolvers(WillBeHeapHashSet<RawPtrWillBeWeakMember<CSSStyleShee t> >& clients)
583 {
584 for (WillBeHeapHashSet<RawPtrWillBeWeakMember<CSSStyleSheet> >::iterator it = clients.begin(); it != clients.end(); ++it) {
585 if (Document* document = (*it)->ownerDocument())
586 document->styleEngine()->clearResolver();
587 }
588 }
589
567 void StyleSheetContents::clearRuleSet() 590 void StyleSheetContents::clearRuleSet()
568 { 591 {
569 if (StyleSheetContents* parentSheet = parentStyleSheet()) 592 if (StyleSheetContents* parentSheet = parentStyleSheet())
570 parentSheet->clearRuleSet(); 593 parentSheet->clearRuleSet();
571 594
572 // Don't want to clear the StyleResolver if the RuleSet hasn't been created 595 // Don't want to clear the StyleResolver if the RuleSet hasn't been created
573 // since we only clear the StyleResolver so that it's members are properly 596 // since we only clear the StyleResolver so that it's members are properly
574 // updated in ScopedStyleResolver::addRulesFromSheet. 597 // updated in ScopedStyleResolver::addRulesFromSheet.
575 if (!m_ruleSet) 598 if (!m_ruleSet)
576 return; 599 return;
577 600
578 // Clearing the ruleSet means we need to recreate the styleResolver data str uctures. 601 // Clearing the ruleSet means we need to recreate the styleResolver data str uctures.
579 // See the StyleResolver calls in ScopedStyleResolver::addRulesFromSheet. 602 // See the StyleResolver calls in ScopedStyleResolver::addRulesFromSheet.
580 for (ClientsIterator it = m_clients.begin(); it != m_clients.end(); ++it) { 603 clearResolvers(m_loadingClients);
581 if (Document* document = (*it)->ownerDocument()) 604 clearResolvers(m_completedClients);
582 document->styleEngine()->clearResolver(); 605 m_ruleSet.clear();
606 }
607
608 static void removeFontFaceRules(WillBeHeapHashSet<RawPtrWillBeWeakMember<CSSStyl eSheet> >& clients, const StyleRuleFontFace* fontFaceRule)
609 {
610 for (WillBeHeapHashSet<RawPtrWillBeWeakMember<CSSStyleSheet> >::iterator it = clients.begin(); it != clients.end(); ++it) {
611 if (Node* ownerNode = (*it)->ownerNode())
612 ownerNode->document().styleEngine()->removeFontFaceRules(WillBeHeapV ector<RawPtrWillBeMember<const StyleRuleFontFace> >(1, fontFaceRule));
583 } 613 }
584 m_ruleSet.clear();
585 } 614 }
586 615
587 void StyleSheetContents::notifyRemoveFontFaceRule(const StyleRuleFontFace* fontF aceRule) 616 void StyleSheetContents::notifyRemoveFontFaceRule(const StyleRuleFontFace* fontF aceRule)
588 { 617 {
589 StyleSheetContents* root = rootStyleSheet(); 618 StyleSheetContents* root = rootStyleSheet();
590 619 removeFontFaceRules(root->m_loadingClients, fontFaceRule);
591 for (ClientsIterator it = root->m_clients.begin(); it != root->m_clients.end (); ++it) { 620 removeFontFaceRules(root->m_completedClients, fontFaceRule);
592 if (Node* ownerNode = (*it)->ownerNode())
593 ownerNode->document().styleEngine()->removeFontFaceRules(WillBeHeapV ector<RawPtrWillBeMember<const StyleRuleFontFace> >(1, fontFaceRule));
594 }
595 } 621 }
596 622
597 static void findFontFaceRulesFromRules(const WillBeHeapVector<RefPtrWillBeMember <StyleRuleBase> >& rules, WillBeHeapVector<RawPtrWillBeMember<const StyleRuleFon tFace> >& fontFaceRules) 623 static void findFontFaceRulesFromRules(const WillBeHeapVector<RefPtrWillBeMember <StyleRuleBase> >& rules, WillBeHeapVector<RawPtrWillBeMember<const StyleRuleFon tFace> >& fontFaceRules)
598 { 624 {
599 for (unsigned i = 0; i < rules.size(); ++i) { 625 for (unsigned i = 0; i < rules.size(); ++i) {
600 StyleRuleBase* rule = rules[i].get(); 626 StyleRuleBase* rule = rules[i].get();
601 627
602 if (rule->isFontFaceRule()) { 628 if (rule->isFontFaceRule()) {
603 fontFaceRules.append(toStyleRuleFontFace(rule)); 629 fontFaceRules.append(toStyleRuleFontFace(rule));
604 } else if (rule->isMediaRule()) { 630 } else if (rule->isMediaRule()) {
(...skipping 14 matching lines...) Expand all
619 } 645 }
620 646
621 findFontFaceRulesFromRules(childRules(), fontFaceRules); 647 findFontFaceRulesFromRules(childRules(), fontFaceRules);
622 } 648 }
623 649
624 void StyleSheetContents::trace(Visitor* visitor) 650 void StyleSheetContents::trace(Visitor* visitor)
625 { 651 {
626 visitor->trace(m_ownerRule); 652 visitor->trace(m_ownerRule);
627 visitor->trace(m_importRules); 653 visitor->trace(m_importRules);
628 visitor->trace(m_childRules); 654 visitor->trace(m_childRules);
629 visitor->trace(m_clients); 655 visitor->trace(m_loadingClients);
656 visitor->trace(m_completedClients);
630 visitor->trace(m_ruleSet); 657 visitor->trace(m_ruleSet);
631 } 658 }
632 659
633 } 660 }
OLDNEW
« no previous file with comments | « Source/core/css/StyleSheetContents.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698