haikuwebkit/LayoutTests/js/dom/domjit-accessor-polymorphic...

9 lines
187 B
Plaintext
Raw Permalink Normal View History

[DOMJIT] Implement Node accessors in DOMJIT https://bugs.webkit.org/show_bug.cgi?id=163005 Reviewed by Filip Pizlo. Source/JavaScriptCore: Add some helper methods and offsetOfXXX for JSC::Weak since it is used for DOM wrapper caching. And make DOMJIT::Patchpoint in FTL closer to one in DFG. We add resultConstraint to avoid the situation that the same register is allocated to child and result. We also extend DOMJIT::Patchpoint to tell useTagTypeNumberRegister / useTagMaskRegister. * dfg/DFGSpeculativeJIT.h: (JSC::DFG::SpeculativeJIT::callOperation): * domjit/DOMJITSlowPathCalls.h: * ftl/FTLLowerDFGToB3.cpp: (JSC::FTL::DFG::LowerDFGToB3::compileCheckDOM): (JSC::FTL::DFG::LowerDFGToB3::compileCallDOM): * heap/WeakImpl.h: (JSC::WeakImpl::offsetOfJSValue): (JSC::WeakImpl::offsetOfWeakHandleOwner): * jit/AssemblyHelpers.h: (JSC::AssemblyHelpers::boxCell): (JSC::AssemblyHelpers::boxInt32): Deleted. * jit/JITOperations.h: Source/WebCore: This patch implements DOMJIT accessors in WebCore. We plan to offer 2 things in DOMJIT. 1. Hand written DOM inlining. We inject DOMJIT::Patchpoint compiler into JSC. And JSC uses this to inline DOM operation, and drop type checks. Since the operation is fully inlined, potentially it has large performance boost. Note that CSS Selector JIT compiler already does the similar things: accessing parentNode etc. directly by using offsets. 2. Exposing signature information. We will offer function type signature by some representation and pass it to JSC. JSC will use to drop type checks. Since IDL code generator already knows this, we can automatically generate such a information. Since we don't perform any inlining, the performance boost may be limited. But it's worth doing. This patch implements the first one, hand written DOM inlining facility. We add a new IDL attribute, "DOMJIT". This means that "This readonly attribute have a DOMJIT patchpoint compiler". We annotate several accessors at first. "firstChild", "lastChild", "nextSibling", "previousSibling", and "parentNode". And we implement DOMJIT::Patchpoint for that in JSNodeDOMJIT.cpp. This patchpoint will be integrated into JSC's DFG and FTL. And these tiers can drop type checks and inline the entire code of these accessors. JSC compiler still does not know much about DOM. And WebCore does not know much about each tier of JSC. WebCore just offers the generic patchpoints and they are used in both DFG and FTL tiers. The layer separation is still kept. While very small microbenchmark[1] shows performance benefit, still we cannot improve DOM benchmarks due to the lack of following implementations. Once the following implementations are implemented, we will get performance boost. 1. Super polymorphic sites. This inlining is super effective if we run some microbenchmarks. However, Dromaeo does not show so much performance benefit. This is because Dromaeo's dom-traverse.html is super polymorphic call site where JSC gives up optimization. For example, in the following dromaeo's benchmark, we can see so various DOM nodes at the `cur.firstChild` site, like, HTMLDivElement, HTMLAnchorElement, Text, Comment etc. JSC gives up optimization since we encounter so many Structures. This should be optimized since they share the large part of prototype-chain and they hit the exactly same CustomGetter, Node.prototype.firstChild. We will handle this and when we optimize it, this DOMJIT works well on Dromaeo. test( "firstChild", function(){ var nodes = document.body.childNodes, nl = nodes.length; for ( var i = 0; i < num; i++ ) { for ( var j = 0; j < nl; j++ ) { var cur = nodes[j]; while ( cur ) cur = cur.firstChild; ret = cur; } } }); 2. Emit code in IC. Currently, we only optimize DOMJIT accessors in DFG and FTL. However, we should leverage this DOMJIT::Patchpoint to emit inlined code even in Inline Caching (IC). We will emit CheckDOM's code for IC's guard phase, and emit CallDOM's code for IC's get phase. This offers performance benefit even if we live in baseline JIT code. And this should be easy. [1]: With the following one, we can see 3x improvement (26ms v.s. 80ms). var element = document.getElementsByTagName('div')[3]; var before = Date.now(); for (var i = 0; i < 1e7; ++i) element.firstChild; console.log(Date.now() - before); * CMakeLists.txt: * ForwardingHeaders/domjit/DOMJITGetterSetter.h: * ForwardingHeaders/domjit/DOMJITPatchpoint.h: Copied from Source/JavaScriptCore/domjit/DOMJITSlowPathCalls.h. * ForwardingHeaders/domjit/DOMJITPatchpointParams.h: Copied from Source/JavaScriptCore/domjit/DOMJITSlowPathCalls.h. * WebCore.xcodeproj/project.pbxproj: * bindings/js/JSDOMGlobalObject.h: * bindings/js/JSDOMWrapper.h: (WebCore::JSDOMWrapper::offsetOfWrapped): (WebCore::JSDOMWrapper::wrapped): Deleted. * bindings/js/ScriptWrappable.h: (WebCore::ScriptWrappable::offsetOfWrapper): * bindings/scripts/CodeGeneratorJS.pm: (GetJSCAttributesForAttribute): (GenerateHeader): (GeneratePropertiesHashTable): (GenerateImplementation): (GenerateHashTableValueArray): * bindings/scripts/IDLAttributes.txt: * dom/ContainerNode.h: (WebCore::ContainerNode::lastChildMemoryOffset): (WebCore::ContainerNode::lastChild): Deleted. * dom/Node.h: (WebCore::Node::flagIsContainer): (WebCore::Node::flagIsText): Deleted. * dom/Node.idl: * domjit/DOMJITHelpers.h: Added. (WebCore::DOMJITHelpers::branchIfNotWorldIsNormal): (WebCore::DOMJITHelpers::branchIfNotWeakIsLive): (WebCore::DOMJITHelpers::tryLookUpWrapperCache): (WebCore::DOMJITHelpers::toWrapper): (WebCore::DOMJITHelpers::branchIfDOMWrapper): (WebCore::DOMJITHelpers::branchIfNotDOMWrapper): (WebCore::DOMJITHelpers::branchIfNode): (WebCore::DOMJITHelpers::branchIfNotNode): (WebCore::DOMJITHelpers::branchIfElement): (WebCore::DOMJITHelpers::branchIfNotElement): (WebCore::DOMJITHelpers::branchIfDocumentWrapper): (WebCore::DOMJITHelpers::branchIfNotDocumentWrapper): * domjit/JSNodeDOMJIT.cpp: Added. (WebCore::toWrapperSlow): (WebCore::createCallDOMForOffsetAccess): (WebCore::checkNode): (WebCore::NodeFirstChildDOMJIT::checkDOM): (WebCore::NodeFirstChildDOMJIT::callDOM): (WebCore::NodeLastChildDOMJIT::checkDOM): (WebCore::NodeLastChildDOMJIT::callDOM): (WebCore::NodeNextSiblingDOMJIT::checkDOM): (WebCore::NodeNextSiblingDOMJIT::callDOM): (WebCore::NodePreviousSiblingDOMJIT::checkDOM): (WebCore::NodePreviousSiblingDOMJIT::callDOM): (WebCore::NodeParentNodeDOMJIT::checkDOM): (WebCore::NodeParentNodeDOMJIT::callDOM): Source/WTF: Add CAST_OFFSET. It is not necessary for JSCell thingy since we don't use virtual member functions. However, it is not true for WebCore DOM wrapped objects. * wtf/StdLibExtras.h: LayoutTests: * js/dom/domjit-accessor-monomorphic-expected.txt: Added. * js/dom/domjit-accessor-monomorphic.html: Added. * js/dom/domjit-accessor-polymorphic-expected.txt: Added. * js/dom/domjit-accessor-polymorphic.html: Added. Canonical link: https://commits.webkit.org/181061@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207013 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-10-10 19:57:55 +00:00
Test DOMJIT accessors work in polymorphic call sites.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS successfullyParsed is true
TEST COMPLETE