// Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "core/layout/LayoutAnalyzer.h" #include "core/frame/FrameView.h" #include "core/layout/LayoutBlock.h" #include "core/layout/LayoutObject.h" #include "core/layout/LayoutText.h" #include "platform/TracedValue.h" namespace blink { LayoutAnalyzer::Scope::Scope(const LayoutObject& o) : m_layoutObject(o) , m_analyzer(o.frameView()->layoutAnalyzer()) { if (m_analyzer) m_analyzer->push(o); } LayoutAnalyzer::Scope::~Scope() { if (m_analyzer) m_analyzer->pop(m_layoutObject); } LayoutAnalyzer::BlockScope::BlockScope(const LayoutBlock& block) : m_block(block) , m_width(block.frameRect().width()) , m_height(block.frameRect().height()) { } LayoutAnalyzer::BlockScope::~BlockScope() { LayoutAnalyzer* analyzer = m_block.frameView()->layoutAnalyzer(); if (!analyzer) return; bool changed = false; if (m_width != m_block.frameRect().width()) { analyzer->increment(LayoutBlockWidthChanged); changed = true; } if (m_height != m_block.frameRect().height()) { analyzer->increment(LayoutBlockHeightChanged); changed = true; } analyzer->increment(changed ? LayoutBlockSizeChanged : LayoutBlockSizeDidNotChange); } void LayoutAnalyzer::reset() { m_startMs = currentTimeMS(); m_depth = 0; for (size_t i = 0; i < NumCounters; ++i) { m_counters[i] = 0; } } void LayoutAnalyzer::push(const LayoutObject& o) { increment(TotalLayoutObjectsThatWereLaidOut); if (!o.everHadLayout()) increment(LayoutObjectsThatHadNeverHadLayout); if (o.selfNeedsLayout()) increment(LayoutObjectsThatNeedLayoutForThemselves); if (o.needsPositionedMovementLayout()) increment(LayoutObjectsThatNeedPositionedMovementLayout); if (o.isOutOfFlowPositioned()) increment(LayoutObjectsThatAreOutOfFlowPositioned); if (o.isTableCell()) increment(LayoutObjectsThatAreTableCells); if (o.isFloating()) increment(LayoutObjectsThatAreFloating); if (o.style()->specifiesColumns()) increment(LayoutObjectsThatSpecifyColumns); if (o.hasLayer()) increment(LayoutObjectsThatHaveALayer); if (o.isLayoutInline() && o.alwaysCreateLineBoxesForLayoutInline()) increment(LayoutInlineObjectsThatAlwaysCreateLineBoxes); if (o.isText()) { const LayoutText& t = *toLayoutText(&o); if (t.canUseSimpleFontCodePath()) { increment(LayoutObjectsThatAreTextAndCanUseTheSimpleFontCodePath); increment(CharactersInLayoutObjectsThatAreTextAndCanUseTheSimpleFontCodePath, t.textLength()); } else { increment(LayoutObjectsThatAreTextAndCanNotUseTheSimpleFontCodePath); increment(CharactersInLayoutObjectsThatAreTextAndCanNotUseTheSimpleFontCodePath, t.textLength()); } } ++m_depth; // This refers to LayoutAnalyzer depth, which is generally closer to C++ // stack recursion depth, not layout tree depth or DOM tree depth. m_counters[LayoutAnalyzerStackMaximumDepth] = max(m_counters[LayoutAnalyzerStackMaximumDepth], m_depth); } void LayoutAnalyzer::pop(const LayoutObject& o) { ASSERT(m_depth > 0); --m_depth; } PassOwnPtr LayoutAnalyzer::toTracedValue() { OwnPtr tracedValue(TracedValue::create()); for (size_t i = 0; i < NumCounters; ++i) { if (m_counters[i] > 0) tracedValue->setInteger(nameForCounter(static_cast(i)), m_counters[i]); } return tracedValue.release(); } const char* LayoutAnalyzer::nameForCounter(Counter counter) const { switch (counter) { case LayoutBlockWidthChanged: return "LayoutBlockWidthChanged"; case LayoutBlockHeightChanged: return "LayoutBlockHeightChanged"; case LayoutBlockSizeChanged: return "LayoutBlockSizeChanged"; case LayoutBlockSizeDidNotChange: return "LayoutBlockSizeDidNotChange"; case LayoutObjectsThatSpecifyColumns: return "LayoutObjectsThatSpecifyColumns"; case LayoutAnalyzerStackMaximumDepth: return "LayoutAnalyzerStackMaximumDepth"; case LayoutObjectsThatAreFloating: return "LayoutObjectsThatAreFloating"; case LayoutObjectsThatHaveALayer: return "LayoutObjectsThatHaveALayer"; case LayoutInlineObjectsThatAlwaysCreateLineBoxes: return "LayoutInlineObjectsThatAlwaysCreateLineBoxes"; case LayoutObjectsThatHadNeverHadLayout: return "LayoutObjectsThatHadNeverHadLayout"; case LayoutObjectsThatAreOutOfFlowPositioned: return "LayoutObjectsThatAreOutOfFlowPositioned"; case LayoutObjectsThatNeedPositionedMovementLayout: return "LayoutObjectsThatNeedPositionedMovementLayout"; case PerformLayoutRootLayoutObjects: return "PerformLayoutRootLayoutObjects"; case LayoutObjectsThatNeedLayoutForThemselves: return "LayoutObjectsThatNeedLayoutForThemselves"; case LayoutObjectsThatNeedSimplifiedLayout: return "LayoutObjectsThatNeedSimplifiedLayout"; case LayoutObjectsThatAreTableCells: return "LayoutObjectsThatAreTableCells"; case LayoutObjectsThatAreTextAndCanNotUseTheSimpleFontCodePath: return "LayoutObjectsThatAreTextAndCanNotUseTheSimpleFontCodePath"; case CharactersInLayoutObjectsThatAreTextAndCanNotUseTheSimpleFontCodePath: return "CharactersInLayoutObjectsThatAreTextAndCanNotUseTheSimpleFontCodePath"; case LayoutObjectsThatAreTextAndCanUseTheSimpleFontCodePath: return "LayoutObjectsThatAreTextAndCanUseTheSimpleFontCodePath"; case CharactersInLayoutObjectsThatAreTextAndCanUseTheSimpleFontCodePath: return "CharactersInLayoutObjectsThatAreTextAndCanUseTheSimpleFontCodePath"; case TotalLayoutObjectsThatWereLaidOut: return "TotalLayoutObjectsThatWereLaidOut"; } ASSERT_NOT_REACHED(); return ""; } } // namespace blink