haikuwebkit/LayoutTests/js/dom/domjit-accessor-node-type.html

56 lines
1.7 KiB
HTML
Raw Permalink Normal View History

[DOMJIT][JSC] Explore the way to embed nodeType into JSC::JSType in WebCore https://bugs.webkit.org/show_bug.cgi?id=163245 Reviewed by Filip Pizlo. Source/JavaScriptCore: We reserve the highest bit of JSC::JSType for extensions outside JSC. JSC does not use JSType bits so many: only 52 types are defined. And we extend CallDOM patchpoint to claim that it does not require a global object. This global object is used to generate a DOM wrapper. However, nodeType does not require it since it just returns integer. In the future, we will extend CallDOM to claim its result type. And we can decide this `requireGlobalObject` condition automatically according to the result type. * JavaScriptCore.xcodeproj/project.pbxproj: * dfg/DFGByteCodeParser.cpp: (JSC::DFG::ByteCodeParser::handleDOMJITGetter): * dfg/DFGFixupPhase.cpp: (JSC::DFG::FixupPhase::fixupNode): * dfg/DFGGraph.h: * dfg/DFGNode.h: (JSC::DFG::Node::hasCheckDOMPatchpoint): (JSC::DFG::Node::checkDOMPatchpoint): (JSC::DFG::Node::hasCallDOMPatchpoint): (JSC::DFG::Node::callDOMPatchpoint): (JSC::DFG::Node::hasDOMJIT): Deleted. (JSC::DFG::Node::domJIT): Deleted. * dfg/DFGSpeculativeJIT.cpp: (JSC::DFG::SpeculativeJIT::compileCallDOM): (JSC::DFG::SpeculativeJIT::compileCheckDOM): * domjit/DOMJITCallDOMPatchpoint.h: Copied from Source/JavaScriptCore/domjit/DOMJITGetterSetter.h. (JSC::DOMJIT::CallDOMPatchpoint::create): * domjit/DOMJITGetterSetter.h: * domjit/DOMJITPatchpoint.h: * ftl/FTLLowerDFGToB3.cpp: (JSC::FTL::DFG::LowerDFGToB3::compileCheckDOM): (JSC::FTL::DFG::LowerDFGToB3::compileCallDOM): * jsc.cpp: * llint/LLIntData.cpp: (JSC::LLInt::Data::performAssertions): * llint/LowLevelInterpreter.asm: * runtime/JSType.h: Source/WebCore: Node.nodeType accessor is so frequently called. For example, jQuery's $ function uses this to distinguish DOM objects from the other JS objects. So every time you call `$(dom)`, nodeType accessor is called. In addition to that, jQuery's prev, next, parent etc. also uses this `nodeType`. And Ember.js also uses it. And ... So this function is super critical for DOM performance. The challenge is that there is no room for putting NodeType into C++ Node class. Node class has a 32bit field to store some data. However, these bits are already exhausted. Extending Node class is unacceptable since it significantly enlarges memory consumption of WebKit (Node is everywhere!). Unfortunately, current Node::nodeType is implemented as a virtual function even though this function is frequently called from JS world. Interestingly, we already store some duplicate data in JSObject, JSC::JSType. WebCore already extends it with JSElementType, JSNodeType, and JSDocumentWrapperType. And these types are corresponding to specific NodeTypes. For example, JSElementType should have ELEMENT_NODE type. This patch further extends this JSC::JSType in WebCore side safely. We embed NodeType bits into JSC::JSType. This design offers significantly faster nodeType implementation. Furthermore, it makes DOMJIT easy for nodeType accessor. Even without the IC change[1], Dromaeo dom-query shows 8 - 10% improvement, 1452.96 runs/s vs 1578.56 runs/s. We can expect that this improvement will be applied to the other benchmarks / real applications when the IC change is landed. [1]: https://bugs.webkit.org/show_bug.cgi?id=163226 * WebCore.xcodeproj/project.pbxproj: * bindings/js/JSDOMWrapper.h: * bindings/js/JSNodeCustom.h: (WebCore::JSNode::nodeType): * bindings/scripts/CodeGeneratorJS.pm: (GetJSTypeForNode): (GenerateHeader): * dom/Node.idl: * dom/NodeConstants.h: Copied from Source/JavaScriptCore/domjit/DOMJITGetterSetter.h. * domjit/JSNodeDOMJIT.cpp: (WebCore::createCallDOMForOffsetAccess): (WebCore::NodeFirstChildDOMJIT::callDOM): (WebCore::NodeLastChildDOMJIT::callDOM): (WebCore::NodeNextSiblingDOMJIT::callDOM): (WebCore::NodePreviousSiblingDOMJIT::callDOM): (WebCore::NodeParentNodeDOMJIT::callDOM): (WebCore::NodeNodeTypeDOMJIT::checkDOM): (WebCore::NodeNodeTypeDOMJIT::callDOM): LayoutTests: * js/dom/domjit-accessor-node-type.html: Added. Canonical link: https://commits.webkit.org/181186@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207239 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-10-12 20:47:51 +00:00
<!DOCTYPE html>
<html>
<head>
<script src="../../resources/js-test-pre.js"></script>
</head>
<body>
<iframe id="xmlframe" onload="frameLoaded()" style="height:0px" src="data:application/xhtml+xml,<?xml version='1.0' encoding='UTF-8'?><body/>"></iframe>
<script>
description('Test DOMJIT nodeType accessor works.');
if (window.testRunner)
testRunner.waitUntilDone();
var target = null;
var result = null;
function runTest()
{
var xmlDocument = document.getElementById('xmlframe').contentDocument;
var targets = [
[document.body, Node.ELEMENT_NODE],
[document.createAttribute('Cocoa'), Node.ATTRIBUTE_NODE],
[document.createTextNode('Cocoa'), Node.TEXT_NODE],
[xmlDocument.createCDATASection('test'), Node.CDATA_SECTION_NODE],
[xmlDocument.createProcessingInstruction('target', 'test'), Node.PROCESSING_INSTRUCTION_NODE],
[document.createComment('Cocoa'), Node.COMMENT_NODE],
[document, Node.DOCUMENT_NODE],
[document.doctype, Node.DOCUMENT_TYPE_NODE],
[document.createDocumentFragment(), Node.DOCUMENT_FRAGMENT_NODE],
];
for ([target, result] of targets) {
var text = `
function test${result}(element, result)
{
for (var i = 0; i < 1e4; ++i) {
if (element.nodeType !== result)
return false;
}
return true;
}
`;
shouldBeTrue(`(${text})(target, ${result})`);
}
if (window.testRunner)
testRunner.notifyDone();
}
function frameLoaded()
{
runTest();
}
</script>
<script src="../../resources/js-test-post.js"></script>
</body>
</html>