blob: 6ff55336d43b5b7f57c8bf66f5e86dff141ae15a [file] [log] [blame]
// 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/tracing/TracedValue.h"
#include <memory>
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;
}
std::unique_ptr<TracedValue> LayoutAnalyzer::toTracedValue() {
std::unique_ptr<TracedValue> tracedValue(TracedValue::create());
for (size_t i = 0; i < NumCounters; ++i) {
if (m_counters[i] > 0)
tracedValue->setInteger(nameForCounter(static_cast<Counter>(i)),
m_counters[i]);
}
return tracedValue;
}
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 "CharactersInLayoutObjectsThatAreTextAndCanNotUseTheSimpleFontCode"
"Path";
case LayoutObjectsThatAreTextAndCanUseTheSimpleFontCodePath:
return "LayoutObjectsThatAreTextAndCanUseTheSimpleFontCodePath";
case CharactersInLayoutObjectsThatAreTextAndCanUseTheSimpleFontCodePath:
return "CharactersInLayoutObjectsThatAreTextAndCanUseTheSimpleFontCodePat"
"h";
case TotalLayoutObjectsThatWereLaidOut:
return "TotalLayoutObjectsThatWereLaidOut";
}
ASSERT_NOT_REACHED();
return "";
}
} // namespace blink