何时在哪里thread构建的,先找到构建rendertree的code.
有RenderTreeBuilder类。
上面1.16rendering basics中讲了,RenderTree是通过对dom节点执行attach操作建立的。在dom被建立时,对其节点执行attach操作,即可创建renderobject, 建立rendertree. 当docuemnt关闭,或从dom中移除一个节点时,对该节点执行detach操作,就可将他对应的rendreobject从rendertree中移除。
下面看看最简单的调用element::attach的callstack,是在收到了html数据加载完之后,先对document节点执行attach,他会对子节点执行attach.
#0 WebCore::Element::attach(this=0x3ea08068, context=...) at../../third_party/WebKit/Source/core/dom/Element.cpp:1357
#1 0x60d15a9c inWebCore::Node::reattach(this=this@entry=0x3ea08068, context=...) at../../third_party/WebKit/Source/core/dom/Node.cpp:973
#2 0x60d0cbce inWebCore::Element::recalcOwnStyle(this=this@entry=0x3ea08068, change=change@entry=WebCore::Force) at../../third_party/WebKit/Source/core/dom/Element.cpp:1552
#3 0x60d0cd0a inWebCore::Element::recalcStyle(this=0x3ea08068, change=WebCore::Force, nextTextSibling=0x0) at../../third_party/WebKit/Source/core/dom/Element.cpp:1518
#4 0x60d034f6 inWebCore::Document::updateStyle(this=this@entry=0x3ea04000, change=<optimized out>,change@entry=WebCore::NoChange) at../../third_party/WebKit/Source/core/dom/Document.cpp:1946
#5 0x60d038e6 inWebCore::Document::updateRenderTree(this=this@entry=0x3ea04000,change=change@entry=WebCore::NoChange) at../../third_party/WebKit/Source/core/dom/Document.cpp:1882
#6 0x60d03a32 inWebCore::Document::updateRenderTreeIfNeeded(this=this@entry=0x3ea04000) at../../third_party/WebKit/Source/core/dom/Document.h:486
#7 0x60d04744 inWebCore::Document::finishedParsing(this=0x3ea04000) at../../third_party/WebKit/Source/core/dom/Document.cpp:4705
#8 0x60b9e1bc inWebCore::HTMLConstructionSite::finishedParsing (this=<optimizedout>) at../../third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp:543
#9 0x60bae026 inWebCore::HTMLTreeBuilder::finished(this=<optimized out>) at../../third_party/WebKit/Source/core/html/parser/HTMLTreeBuilder.cpp:2796
#10 0x60b9f71c inWebCore::HTMLDocumentParser::end (this=this@entry=0x2e46c480) at../../third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp:828
#11 0x60b9f730 inWebCore::HTMLDocumentParser::attemptToRunDeferredScriptsAndEnd(this=this@entry=0x2e46c480) at../../third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp:839
#12 0x60ba008c inWebCore::HTMLDocumentParser::prepareToStopParsing (this=0x2e46c480)at../../third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp:240
#13 0x60ba13d6 inWebCore::HTMLDocumentParser::processParsedChunkFromBackgroundParser(this=this@entry=0x2e46c480, popChunk=...) at../../third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp:491
#14 0x60ba1538 inWebCore::HTMLDocumentParser::pumpPendingSpeculations(this=this@entry=0x2e46c480) at../../third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp:530
#15 0x60ba1770 inWebCore::HTMLDocumentParser::didReceiveParsedChunkFromBackgroundParser(this=0x2e46c480, chunk=...) at../../third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp:363
#16 0x60b9b6c2 in operator()(p1=..., c=..., this=<optimized out>) at../../third_party/WebKit/Source/wtf/Functional.h:210
#17WTF::BoundFunctionImpl<WTF::FunctionWrapper<void(WebCore::HTMLDocumentParser::*)(WTF::PassOwnPtr<WebCore::HTMLDocumentParser::ParsedChunk>)>,void (WTF::WeakPtr<WebCore::HTMLDocumentParser>,WTF::PassOwnPtr<W
#18 0x6154d7fc in operator()(this=0x650edab8) at../../third_party/WebKit/Source/wtf/Functional.h:577
#19 WTF::callFunctionObject(context=0x650edab8) at../../third_party/WebKit/Source/wtf/MainThread.cpp:62
#20 0x6144d6d6 in Run (a1=<optimizedout>, this=<synthetic pointer>) at../../base/bind_internal.h:171
#21 MakeItSo (a1=<optimized out>,runnable=...) at ../../base/bind_internal.h:871
#22 base::internal::Invoker<1,base::internal::BindState<base::internal::RunnableAdapter<void(*)(void*)>, void (void*), void (void*)>, void(void*)>::Run(base::internal::BindStateBase*) (base=<optimizedout>)
at../../base/bind_internal.h:1169
#23 0x614f31f0 in Run(this=0x65ce4d00) at ../../base/callback.h:401
#24 base::MessageLoop::RunTask(this=this@entry=0x5abea008, pending_task=...) at../../base/message_loop/message_loop.cc:450
#25 0x614f329c inbase::MessageLoop::DeferOrRunPendingTask (this=this@entry=0x5abea008,pending_task=...) at ../../base/message_loop/message_loop.cc:462
#26 0x614f39b2 inbase::MessageLoop::DoWork (this=0x5abea008) at../../base/message_loop/message_loop.cc:576
#27 0x614f3f02 inbase::MessagePumpDefault::Run (this=0x5abea500, delegate=0x5abea008)at ../../base/message_loop/message_pump_default.cc:32
#28 0x614f35d6 inbase::MessageLoop::RunHandler (this=0x5abea008) at../../base/message_loop/message_loop.cc:400
#29 0x614fab78 in base::RunLoop::Run(this=this@entry=0x65ce4d70) at ../../base/run_loop.cc:49
#30 0x614f2c04 inbase::MessageLoop::Run (this=<optimized out>) at../../base/message_loop/message_loop.cc:293
#31 0x615036d6 inbase::Thread::ThreadMain (this=0x57b80c78) at../../base/threading/thread.cc:225
#32 0x615014fe in base::(anonymousnamespace)::ThreadFunc (params=<optimized out>) at../../base/threading/platform_thread_posix.cc:80
#33 0x40196a5c in __thread_entry ()from /tmp/tshao-adb-gdb-libs/system/lib/libc.so
void Element::attach(constAttachContext& context)
{
RenderTreeBuilder(this,//创建本节点的renderer.context.resolvedStyle).createRendererForElementIfNeeded();
ContainerNode::attach(context);//对本节点的childern执行attach.
。。。
}
这里使用RenderTreeBuilder.来针对一个dom节点建立renderobject并加入到rendertree中。
voidRenderTreeBuilder::createRendererForElementIfNeeded()
{
Element* element =toElement(m_node);
RenderStyle& style =this->style();
RenderObject* newRenderer = element->createRenderer(&style);
这里创建renderobject,实际调用RenderObject::createObject.
RenderObject* parentRenderer =this->parentRenderer();
RenderObject* nextRenderer =this->nextRenderer();
element->setRenderer(newRenderer);
newRenderer->setStyle(&style);// setStyle() can depend on renderer() already being set.
parentRenderer->addChild(newRenderer, nextRenderer);
创建renderer,并把其加入parentrenderer的孩子,够在renderobject tree.
}
我们看看如何创建RenderObject:
RenderObject*RenderObject::createObject(Element* element, RenderStyle* style)
{
ASSERT(isAllowedToModifyRenderTreeStructure(element->document()));
// Minimal support for contentproperties replacing an entire element.
// Works only if we have exactlyone piece of content and it's a URL.
// Otherwise acts as if wedidn't support this feature.
const ContentData* contentData =style->contentData();
if (contentData &&!contentData->next() && contentData->isImage() &&!element->isPseudoElement()) {
RenderImage* image = newRenderImage(element);
//RenderImageResourceStyleImage requires a style being present on theimage but we don't want to
// trigger a style changenow as the node is not fully attached. Moving this code to stylechange
// doesn't make sense as itshould be run once at renderer creation.
image->setStyleInternal(style);
if (const StyleImage*styleImage = static_cast<constImageContentData*>(contentData)->image()) {
image->setImageResource(RenderImageResourceStyleImage::create(const_cast<StyleImage*>(styleImage)));
image->setIsGeneratedContent();
} else
image->setImageResource(RenderImageResource::create());
image->setStyleInternal(nullptr);
return image;
}
switch (style->display()) {
case NONE:
return 0;
case INLINE:
return newRenderInline(element);
case BLOCK:
case INLINE_BLOCK:
return newRenderBlockFlow(element);
case LIST_ITEM:
return newRenderListItem(element);
case TABLE:
case INLINE_TABLE:
return newRenderTable(element);
case TABLE_ROW_GROUP:
case TABLE_HEADER_GROUP:
case TABLE_FOOTER_GROUP:
return newRenderTableSection(element);
case TABLE_ROW:
return newRenderTableRow(element);
case TABLE_COLUMN_GROUP:
case TABLE_COLUMN:
return newRenderTableCol(element);
case TABLE_CELL:
return newRenderTableCell(element);
case TABLE_CAPTION:
return newRenderTableCaption(element);
case BOX:
case INLINE_BOX:
return newRenderDeprecatedFlexibleBox(element);
case FLEX:
case INLINE_FLEX:
return newRenderFlexibleBox(element);
case GRID:
case INLINE_GRID:
return newRenderGrid(element);
}
return 0;
}