Diff
Modified: trunk/LayoutTests/ChangeLog (207238 => 207239)
--- trunk/LayoutTests/ChangeLog 2016-10-12 20:41:49 UTC (rev 207238)
+++ trunk/LayoutTests/ChangeLog 2016-10-12 20:47:51 UTC (rev 207239)
@@ -1,3 +1,12 @@
+2016-10-12 Yusuke Suzuki <utatane....@gmail.com>
+
+ [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.
+
+ * js/dom/domjit-accessor-node-type.html: Added.
+
2016-10-12 Chris Dumez <cdu...@apple.com>
Update more events to stop using legacy [ConstructorTemplate=Event]
Added: trunk/LayoutTests/js/dom/domjit-accessor-node-type.html (0 => 207239)
--- trunk/LayoutTests/js/dom/domjit-accessor-node-type.html (rev 0)
+++ trunk/LayoutTests/js/dom/domjit-accessor-node-type.html 2016-10-12 20:47:51 UTC (rev 207239)
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<iframe id="xmlframe" _onload_="frameLoaded()" style="height:0px" src="" 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=""
+</body>
+</html>
Modified: trunk/Source/_javascript_Core/ChangeLog (207238 => 207239)
--- trunk/Source/_javascript_Core/ChangeLog 2016-10-12 20:41:49 UTC (rev 207238)
+++ trunk/Source/_javascript_Core/ChangeLog 2016-10-12 20:47:51 UTC (rev 207239)
@@ -1,3 +1,48 @@
+2016-10-12 Yusuke Suzuki <utatane....@gmail.com>
+
+ [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.
+
+ 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.
+
+ * _javascript_Core.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/_javascript_Core/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:
+
2016-10-12 Keith Miller <keith_mil...@apple.com>
Handle non-function, non-undefined comparator in Array.prototype.sort
Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (207238 => 207239)
--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2016-10-12 20:41:49 UTC (rev 207238)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2016-10-12 20:47:51 UTC (rev 207239)
@@ -2096,6 +2096,7 @@
E33F50851B8437A000413856 /* JSInternalPromiseDeferred.h in Headers */ = {isa = PBXBuildFile; fileRef = E33F50831B8437A000413856 /* JSInternalPromiseDeferred.h */; settings = {ATTRIBUTES = (Private, ); }; };
E33F50871B8449EF00413856 /* JSInternalPromiseConstructor.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = E33F50861B8449EF00413856 /* JSInternalPromiseConstructor.lut.h */; };
E354622B1B6065D100545386 /* ConstructAbility.h in Headers */ = {isa = PBXBuildFile; fileRef = E354622A1B6065D100545386 /* ConstructAbility.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ E3555B8A1DAE03A500F36921 /* DOMJITCallDOMPatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = E3555B891DAE03A200F36921 /* DOMJITCallDOMPatchpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
E355F3521B7DC85300C50DC5 /* ModuleLoaderPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E355F3501B7DC85300C50DC5 /* ModuleLoaderPrototype.cpp */; };
E355F3531B7DC85300C50DC5 /* ModuleLoaderPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = E355F3511B7DC85300C50DC5 /* ModuleLoaderPrototype.h */; };
E35E035F1B7AB43E0073AD2A /* InspectorInstrumentationObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E35E035D1B7AB43E0073AD2A /* InspectorInstrumentationObject.cpp */; };
@@ -4399,6 +4400,7 @@
E33F50861B8449EF00413856 /* JSInternalPromiseConstructor.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSInternalPromiseConstructor.lut.h; sourceTree = "<group>"; };
E33F50881B844A1A00413856 /* InternalPromiseConstructor.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode._javascript_; path = InternalPromiseConstructor.js; sourceTree = "<group>"; };
E354622A1B6065D100545386 /* ConstructAbility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConstructAbility.h; sourceTree = "<group>"; };
+ E3555B891DAE03A200F36921 /* DOMJITCallDOMPatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMJITCallDOMPatchpoint.h; sourceTree = "<group>"; };
E355F3501B7DC85300C50DC5 /* ModuleLoaderPrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ModuleLoaderPrototype.cpp; sourceTree = "<group>"; };
E355F3511B7DC85300C50DC5 /* ModuleLoaderPrototype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ModuleLoaderPrototype.h; sourceTree = "<group>"; };
E35E035D1B7AB43E0073AD2A /* InspectorInstrumentationObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InspectorInstrumentationObject.cpp; sourceTree = "<group>"; };
@@ -7195,6 +7197,7 @@
E3FF752D1D9CE9EA00C7E16D /* domjit */ = {
isa = PBXGroup;
children = (
+ E3555B891DAE03A200F36921 /* DOMJITCallDOMPatchpoint.h */,
E3FF752F1D9CEA1200C7E16D /* DOMJITGetterSetter.h */,
E3C08E3B1DA41B7B0039478F /* DOMJITPatchpoint.h */,
E37AD83A1DA4928000F3D412 /* DOMJITPatchpointParams.h */,
@@ -8072,6 +8075,7 @@
A7C1EAF017987AB600299DB2 /* CLoopStackInlines.h in Headers */,
BC18C4270E16F5CD00B34460 /* JSString.h in Headers */,
86E85539111B9968001AF51E /* JSStringBuilder.h in Headers */,
+ E3555B8A1DAE03A500F36921 /* DOMJITCallDOMPatchpoint.h in Headers */,
70EC0EC31AA0D7DA00B6AAFA /* JSStringIterator.h in Headers */,
0F070A471D543A8B006E7232 /* CellContainer.h in Headers */,
2600B5A7152BAAA70091EE5F /* JSStringJoiner.h in Headers */,
Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (207238 => 207239)
--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2016-10-12 20:41:49 UTC (rev 207238)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2016-10-12 20:47:51 UTC (rev 207239)
@@ -2687,12 +2687,19 @@
return false;
addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.structureSet())), thisNode);
+ Ref<DOMJIT::Patchpoint> checkDOMPatchpoint = domJIT->checkDOM();
+ m_graph.m_domJITPatchpoints.append(checkDOMPatchpoint.ptr());
// We do not need to emit CheckCell thingy here. When the custom accessor is replaced to different one, Structure transition occurs.
- addToGraph(CheckDOM, OpInfo(domJIT), OpInfo(domJIT->thisClassInfo()), thisNode);
- Node* globalObject = addToGraph(GetGlobalObject, thisNode);
- addVarArgChild(globalObject); // GlobalObject of thisNode is always used to create a DOMWrapper.
+ addToGraph(CheckDOM, OpInfo(checkDOMPatchpoint.ptr()), OpInfo(domJIT->thisClassInfo()), thisNode);
+
+ Ref<DOMJIT::CallDOMPatchpoint> callDOMPatchpoint = domJIT->callDOM();
+ m_graph.m_domJITPatchpoints.append(callDOMPatchpoint.ptr());
+ if (callDOMPatchpoint->requireGlobalObject) {
+ Node* globalObject = addToGraph(GetGlobalObject, thisNode);
+ addVarArgChild(globalObject); // GlobalObject of thisNode is always used to create a DOMWrapper.
+ }
addVarArgChild(thisNode);
- set(VirtualRegister(resultOperand), addToGraph(Node::VarArg, CallDOM, OpInfo(domJIT), OpInfo(prediction)));
+ set(VirtualRegister(resultOperand), addToGraph(Node::VarArg, CallDOM, OpInfo(callDOMPatchpoint.ptr()), OpInfo(prediction)));
return true;
}
Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (207238 => 207239)
--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2016-10-12 20:41:49 UTC (rev 207238)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2016-10-12 20:47:51 UTC (rev 207239)
@@ -1703,10 +1703,14 @@
fixEdge<CellUse>(node->child1());
break;
- case CallDOM:
- fixEdge<KnownCellUse>(m_graph.varArgChild(node, 0)); // GlobalObject.
- fixEdge<CellUse>(m_graph.varArgChild(node, 1)); // DOM.
+ case CallDOM: {
+ int childIndex = 0;
+ DOMJIT::CallDOMPatchpoint* patchpoint = node->callDOMPatchpoint();
+ if (patchpoint->requireGlobalObject)
+ fixEdge<KnownCellUse>(m_graph.varArgChild(node, childIndex++)); // GlobalObject.
+ fixEdge<CellUse>(m_graph.varArgChild(node, childIndex++)); // DOM.
break;
+ }
#if !ASSERT_DISABLED
// Have these no-op cases here to ensure that nobody forgets to add handlers for new opcodes.
Modified: trunk/Source/_javascript_Core/dfg/DFGGraph.h (207238 => 207239)
--- trunk/Source/_javascript_Core/dfg/DFGGraph.h 2016-10-12 20:41:49 UTC (rev 207238)
+++ trunk/Source/_javascript_Core/dfg/DFGGraph.h 2016-10-12 20:47:51 UTC (rev 207239)
@@ -904,6 +904,7 @@
HashMap<CodeBlock*, std::unique_ptr<BytecodeKills>> m_bytecodeKills;
HashSet<std::pair<JSObject*, PropertyOffset>> m_safeToLoad;
HashMap<PropertyTypeKey, InferredType::Descriptor> m_inferredTypes;
+ Vector<RefPtr<DOMJIT::Patchpoint>> m_domJITPatchpoints;
std::unique_ptr<Dominators> m_dominators;
std::unique_ptr<PrePostNumbering> m_prePostNumbering;
std::unique_ptr<NaturalLoops> m_naturalLoops;
Modified: trunk/Source/_javascript_Core/dfg/DFGNode.h (207238 => 207239)
--- trunk/Source/_javascript_Core/dfg/DFGNode.h 2016-10-12 20:41:49 UTC (rev 207238)
+++ trunk/Source/_javascript_Core/dfg/DFGNode.h 2016-10-12 20:47:51 UTC (rev 207239)
@@ -59,7 +59,8 @@
namespace JSC {
namespace DOMJIT {
-class GetterSetter;
+class Patchpoint;
+class CallDOMPatchpoint;
}
namespace Profiler {
@@ -2314,17 +2315,28 @@
return m_opInfo.as<BasicBlockLocation*>();
}
- bool hasDOMJIT() const
+ bool hasCheckDOMPatchpoint() const
{
- return op() == CheckDOM || op() == CallDOM;
+ return op() == CheckDOM;
}
- DOMJIT::GetterSetter* domJIT()
+ DOMJIT::Patchpoint* checkDOMPatchpoint()
{
- ASSERT(hasDOMJIT());
- return m_opInfo.as<DOMJIT::GetterSetter*>();
+ ASSERT(hasCheckDOMPatchpoint());
+ return m_opInfo.as<DOMJIT::Patchpoint*>();
}
+ bool hasCallDOMPatchpoint() const
+ {
+ return op() == CallDOM;
+ }
+
+ DOMJIT::CallDOMPatchpoint* callDOMPatchpoint()
+ {
+ ASSERT(hasCallDOMPatchpoint());
+ return m_opInfo.as<DOMJIT::CallDOMPatchpoint*>();
+ }
+
bool hasClassInfo() const
{
return op() == CheckDOM;
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (207238 => 207239)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2016-10-12 20:41:49 UTC (rev 207238)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2016-10-12 20:47:51 UTC (rev 207239)
@@ -7130,29 +7130,31 @@
void SpeculativeJIT::compileCallDOM(Node* node)
{
- Ref<DOMJIT::Patchpoint> patchpoint = node->domJIT()->callDOM();
+ DOMJIT::CallDOMPatchpoint* patchpoint = node->callDOMPatchpoint();
Vector<GPRReg> gpScratch;
Vector<FPRReg> fpScratch;
Vector<DOMJIT::Value> regs;
- // FIXME: patchpoint should have a way to tell this can reuse "base" register.
- // Teaching DFG about DOMJIT::Patchpoint clobber information is nice.
- SpeculateCellOperand globalObject(this, m_jit.graph().varArgChild(node, 0));
- SpeculateCellOperand base(this, m_jit.graph().varArgChild(node, 1));
JSValueRegsTemporary result(this);
-
regs.append(result.regs());
- regs.append(DOMJIT::Value(globalObject.gpr(), m_state.forNode(m_jit.graph().varArgChild(node, 0)).value()));
- regs.append(DOMJIT::Value(base.gpr(), m_state.forNode(m_jit.graph().varArgChild(node, 1)).value()));
-#if USE(JSVALUE64)
- regs.append(static_cast<GPRReg>(GPRInfo::tagMaskRegister));
- regs.append(static_cast<GPRReg>(GPRInfo::tagTypeNumberRegister));
-#endif
+ int childIndex = 0;
+
+ Optional<SpeculateCellOperand> globalObject;
+ if (patchpoint->requireGlobalObject) {
+ Edge& globalObjectEdge = m_jit.graph().varArgChild(node, childIndex++);
+ globalObject = SpeculateCellOperand(this, globalObjectEdge);
+ regs.append(DOMJIT::Value(globalObject->gpr(), m_state.forNode(globalObjectEdge).value()));
+ }
+
+ Edge& baseEdge = m_jit.graph().varArgChild(node, childIndex++);
+ SpeculateCellOperand base(this, baseEdge);
+ regs.append(DOMJIT::Value(base.gpr(), m_state.forNode(baseEdge).value()));
+
Vector<GPRTemporary> gpTempraries;
Vector<FPRTemporary> fpTempraries;
- allocateTemporaryRegistersForPatchpoint(this, gpTempraries, fpTempraries, gpScratch, fpScratch, patchpoint.get());
+ allocateTemporaryRegistersForPatchpoint(this, gpTempraries, fpTempraries, gpScratch, fpScratch, *patchpoint);
DOMJITPatchpointParams params(this, WTFMove(regs), WTFMove(gpScratch), WTFMove(fpScratch));
patchpoint->generator()->run(m_jit, params);
jsValueResult(result.regs(), node);
@@ -7161,7 +7163,7 @@
void SpeculativeJIT::compileCheckDOM(Node* node)
{
// FIXME: We can add the fallback implementation that inlines jsDynamicCast things here.
- Ref<DOMJIT::Patchpoint> patchpoint = node->domJIT()->checkDOM();
+ DOMJIT::Patchpoint* patchpoint = node->checkDOMPatchpoint();
Vector<GPRReg> gpScratch;
Vector<FPRReg> fpScratch;
@@ -7173,7 +7175,7 @@
Vector<GPRTemporary> gpTempraries;
Vector<FPRTemporary> fpTempraries;
- allocateTemporaryRegistersForPatchpoint(this, gpTempraries, fpTempraries, gpScratch, fpScratch, patchpoint.get());
+ allocateTemporaryRegistersForPatchpoint(this, gpTempraries, fpTempraries, gpScratch, fpScratch, *patchpoint);
DOMJITPatchpointParams params(this, WTFMove(regs), WTFMove(gpScratch), WTFMove(fpScratch));
CCallHelpers::JumpList failureCases = patchpoint->generator()->run(m_jit, params);
Copied: trunk/Source/_javascript_Core/domjit/DOMJITCallDOMPatchpoint.h (from rev 207238, trunk/Source/_javascript_Core/domjit/DOMJITGetterSetter.h) (0 => 207239)
--- trunk/Source/_javascript_Core/domjit/DOMJITCallDOMPatchpoint.h (rev 0)
+++ trunk/Source/_javascript_Core/domjit/DOMJITCallDOMPatchpoint.h 2016-10-12 20:47:51 UTC (rev 207239)
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(JIT)
+
+#include "DOMJITPatchpoint.h"
+#include "RegisterSet.h"
+
+namespace JSC { namespace DOMJIT {
+
+class CallDOMPatchpoint : public Patchpoint {
+public:
+ static Ref<CallDOMPatchpoint> create()
+ {
+ return adoptRef(*new CallDOMPatchpoint());
+ }
+
+ // To look up DOMWrapper cache, GlobalObject is required.
+ // FIXME: Later, we will extend this patchpoint to represent the result type by DOMJIT::Signature.
+ // And after that, we will automatically pass a global object when the result type includes a DOM wrapper thing.
+ // https://bugs.webkit.org/show_bug.cgi?id=162980
+ bool requireGlobalObject { true };
+
+private:
+ CallDOMPatchpoint() = default;
+};
+
+} }
+
+#endif
Modified: trunk/Source/_javascript_Core/domjit/DOMJITGetterSetter.h (207238 => 207239)
--- trunk/Source/_javascript_Core/domjit/DOMJITGetterSetter.h 2016-10-12 20:41:49 UTC (rev 207238)
+++ trunk/Source/_javascript_Core/domjit/DOMJITGetterSetter.h 2016-10-12 20:47:51 UTC (rev 207239)
@@ -25,7 +25,7 @@
#pragma once
-#include "DOMJITPatchpoint.h"
+#include "DOMJITCallDOMPatchpoint.h"
#include "PropertySlot.h"
#include "PutPropertySlot.h"
#include "SpeculatedType.h"
@@ -51,7 +51,7 @@
const ClassInfo* thisClassInfo() const { return m_thisClassInfo; }
#if ENABLE(JIT)
- virtual Ref<DOMJIT::Patchpoint> callDOM() = 0;
+ virtual Ref<DOMJIT::CallDOMPatchpoint> callDOM() = 0;
virtual Ref<DOMJIT::Patchpoint> checkDOM() = 0;
#endif
Modified: trunk/Source/_javascript_Core/domjit/DOMJITPatchpoint.h (207238 => 207239)
--- trunk/Source/_javascript_Core/domjit/DOMJITPatchpoint.h 2016-10-12 20:41:49 UTC (rev 207238)
+++ trunk/Source/_javascript_Core/domjit/DOMJITPatchpoint.h 2016-10-12 20:47:51 UTC (rev 207239)
@@ -62,9 +62,10 @@
uint8_t numGPScratchRegisters { 0 };
uint8_t numFPScratchRegisters { 0 };
-private:
+protected:
Patchpoint() = default;
+private:
RefPtr<PatchpointGenerator> m_generator;
};
Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (207238 => 207239)
--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2016-10-12 20:41:49 UTC (rev 207238)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2016-10-12 20:47:51 UTC (rev 207239)
@@ -8724,7 +8724,7 @@
{
LValue cell = lowCell(m_node->child1());
- RefPtr<DOMJIT::Patchpoint> domJIT = m_node->domJIT()->checkDOM();
+ DOMJIT::Patchpoint* domJIT = m_node->checkDOMPatchpoint();
PatchpointValue* patchpoint = m_out.patchpoint(Void);
patchpoint->appendSomeRegister(cell);
@@ -8769,13 +8769,25 @@
void compileCallDOM()
{
- LValue globalObject = lowCell(m_graph.varArgChild(m_node, 0));
- LValue cell = lowCell(m_graph.varArgChild(m_node, 1));
+ DOMJIT::CallDOMPatchpoint* domJIT = m_node->callDOMPatchpoint();
+ int childIndex = 0;
- RefPtr<DOMJIT::Patchpoint> domJIT = m_node->domJIT()->callDOM();
+ LValue globalObject;
+ JSValue globalObjectConstant;
+ if (domJIT->requireGlobalObject) {
+ Edge& globalObjectEdge = m_graph.varArgChild(m_node, childIndex++);
+ globalObject = lowCell(globalObjectEdge);
+ globalObjectConstant = m_state.forNode(globalObjectEdge).value();
+ }
+
+ Edge& baseEdge = m_graph.varArgChild(m_node, childIndex++);
+ LValue base = lowCell(baseEdge);
+ JSValue baseConstant = m_state.forNode(baseEdge).value();
+
PatchpointValue* patchpoint = m_out.patchpoint(Int64);
- patchpoint->appendSomeRegister(globalObject);
- patchpoint->appendSomeRegister(cell);
+ if (domJIT->requireGlobalObject)
+ patchpoint->appendSomeRegister(globalObject);
+ patchpoint->appendSomeRegister(base);
patchpoint->append(m_tagMask, ValueRep::reg(GPRInfo::tagMaskRegister));
patchpoint->append(m_tagTypeNumber, ValueRep::reg(GPRInfo::tagTypeNumberRegister));
RefPtr<PatchpointExceptionHandle> exceptionHandle = preparePatchpointForExceptions(patchpoint);
@@ -8786,8 +8798,6 @@
State* state = &m_ftlState;
Node* node = m_node;
- JSValue child1Constant = m_state.forNode(m_graph.varArgChild(m_node, 0)).value();
- JSValue child2Constant = m_state.forNode(m_graph.varArgChild(m_node, 1)).value();
patchpoint->setGenerator(
[=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
AllowMacroScratchRegisterUsage allowScratch(jit);
@@ -8796,11 +8806,11 @@
Vector<FPRReg> fpScratch;
Vector<DOMJIT::Value> regs;
- // FIXME: patchpoint should have a way to tell this can reuse "base" register.
- // Teaching DFG about DOMJIT::Patchpoint clobber information is nice.
+ int childIndex = 1;
regs.append(JSValueRegs(params[0].gpr()));
- regs.append(DOMJIT::Value(params[1].gpr(), child1Constant));
- regs.append(DOMJIT::Value(params[2].gpr(), child2Constant));
+ if (domJIT->requireGlobalObject)
+ regs.append(DOMJIT::Value(params[childIndex++].gpr(), globalObjectConstant));
+ regs.append(DOMJIT::Value(params[childIndex++].gpr(), baseConstant));
for (unsigned i = 0; i < domJIT->numGPScratchRegisters; ++i)
gpScratch.append(params.gpScratch(i));
Modified: trunk/Source/_javascript_Core/jsc.cpp (207238 => 207239)
--- trunk/Source/_javascript_Core/jsc.cpp 2016-10-12 20:41:49 UTC (rev 207238)
+++ trunk/Source/_javascript_Core/jsc.cpp 2016-10-12 20:47:51 UTC (rev 207239)
@@ -620,12 +620,13 @@
return patchpoint;
}
- Ref<DOMJIT::Patchpoint> callDOM() override
+ Ref<DOMJIT::CallDOMPatchpoint> callDOM() override
{
- Ref<DOMJIT::Patchpoint> patchpoint = DOMJIT::Patchpoint::create();
+ Ref<DOMJIT::CallDOMPatchpoint> patchpoint = DOMJIT::CallDOMPatchpoint::create();
+ patchpoint->requireGlobalObject = false;
patchpoint->setGenerator([=](CCallHelpers& jit, const DOMJIT::PatchpointParams& params) {
JSValueRegs results = params[0].jsValueRegs();
- GPRReg dom = params[2].gpr();
+ GPRReg dom = params[1].gpr();
params.addSlowPathCall(jit.jump(), jit, static_cast<EncodedJSValue(*)(ExecState*, void*)>([](ExecState*, void* pointer) {
return JSValue::encode(jsNumber(static_cast<DOMJITGetter*>(pointer)->value()));
Modified: trunk/Source/_javascript_Core/llint/LLIntData.cpp (207238 => 207239)
--- trunk/Source/_javascript_Core/llint/LLIntData.cpp 2016-10-12 20:41:49 UTC (rev 207238)
+++ trunk/Source/_javascript_Core/llint/LLIntData.cpp 2016-10-12 20:47:51 UTC (rev 207239)
@@ -161,16 +161,16 @@
STATIC_ASSERT(JSFunctionType == 23);
STATIC_ASSERT(ArrayType == 31);
STATIC_ASSERT(DerivedArrayType == 32);
- STATIC_ASSERT(ProxyObjectType == 116);
- STATIC_ASSERT(Int8ArrayType == 100);
- STATIC_ASSERT(Int16ArrayType == 101);
- STATIC_ASSERT(Int32ArrayType == 102);
- STATIC_ASSERT(Uint8ArrayType == 103);
- STATIC_ASSERT(Uint8ClampedArrayType == 104);
- STATIC_ASSERT(Uint16ArrayType == 105);
- STATIC_ASSERT(Uint32ArrayType == 106);
- STATIC_ASSERT(Float32ArrayType == 107);
- STATIC_ASSERT(Float64ArrayType == 108);
+ STATIC_ASSERT(ProxyObjectType == 49);
+ STATIC_ASSERT(Int8ArrayType == 33);
+ STATIC_ASSERT(Int16ArrayType == 34);
+ STATIC_ASSERT(Int32ArrayType == 35);
+ STATIC_ASSERT(Uint8ArrayType == 36);
+ STATIC_ASSERT(Uint8ClampedArrayType == 37);
+ STATIC_ASSERT(Uint16ArrayType == 38);
+ STATIC_ASSERT(Uint32ArrayType == 39);
+ STATIC_ASSERT(Float32ArrayType == 40);
+ STATIC_ASSERT(Float64ArrayType == 41);
STATIC_ASSERT(MasqueradesAsUndefined == 1);
STATIC_ASSERT(ImplementsDefaultHasInstance == 2);
STATIC_ASSERT(FirstConstantRegisterIndex == 0x40000000);
Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm (207238 => 207239)
--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm 2016-10-12 20:41:49 UTC (rev 207238)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm 2016-10-12 20:47:51 UTC (rev 207239)
@@ -350,19 +350,19 @@
const JSFunctionType = 23
const ArrayType = 31
const DerivedArrayType = 32
-const ProxyObjectType = 116
+const ProxyObjectType = 49
# The typed array types need to be numbered in a particular order because of the manually written
# switch statement in get_by_val and put_by_val.
-const Int8ArrayType = 100
-const Int16ArrayType = 101
-const Int32ArrayType = 102
-const Uint8ArrayType = 103
-const Uint8ClampedArrayType = 104
-const Uint16ArrayType = 105
-const Uint32ArrayType = 106
-const Float32ArrayType = 107
-const Float64ArrayType = 108
+const Int8ArrayType = 33
+const Int16ArrayType = 34
+const Int32ArrayType = 35
+const Uint8ArrayType = 36
+const Uint8ClampedArrayType = 37
+const Uint16ArrayType = 38
+const Uint32ArrayType = 39
+const Float32ArrayType = 40
+const Float64ArrayType = 41
const FirstArrayType = Int8ArrayType
const LastArrayType = Float64ArrayType
Modified: trunk/Source/_javascript_Core/runtime/JSType.h (207238 => 207239)
--- trunk/Source/_javascript_Core/runtime/JSType.h 2016-10-12 20:41:49 UTC (rev 207238)
+++ trunk/Source/_javascript_Core/runtime/JSType.h 2016-10-12 20:47:51 UTC (rev 207239)
@@ -65,7 +65,7 @@
ArrayType,
DerivedArrayType,
- Int8ArrayType = 100,
+ Int8ArrayType,
Int16ArrayType,
Int32ArrayType,
Uint8ArrayType,
@@ -87,8 +87,10 @@
JSSetType,
LastJSCObjectType = JSSetType,
+ MaxJSType = 0b11111111,
};
-COMPILE_ASSERT(sizeof(JSType) == sizeof(uint8_t), sizeof_jstype_is_one_byte);
+static_assert(sizeof(JSType) == sizeof(uint8_t), "sizeof(JSType) is one byte.");
+static_assert(LastJSCObjectType < 128, "The highest bit is reserved for embedder's extension.");
} // namespace JSC
Modified: trunk/Source/WebCore/ChangeLog (207238 => 207239)
--- trunk/Source/WebCore/ChangeLog 2016-10-12 20:41:49 UTC (rev 207238)
+++ trunk/Source/WebCore/ChangeLog 2016-10-12 20:47:51 UTC (rev 207239)
@@ -1,3 +1,55 @@
+2016-10-12 Yusuke Suzuki <utatane....@gmail.com>
+
+ [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.
+
+ 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/_javascript_Core/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):
+
2016-10-12 Chris Dumez <cdu...@apple.com>
Update more events to stop using legacy [ConstructorTemplate=Event]
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (207238 => 207239)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2016-10-12 20:41:49 UTC (rev 207238)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2016-10-12 20:47:51 UTC (rev 207239)
@@ -6143,6 +6143,7 @@
E1FF8F6D180DB5BE00132674 /* CryptoAlgorithmRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = E1FF8F6B180DB5BE00132674 /* CryptoAlgorithmRegistry.h */; };
E3150EA61DA7219000194012 /* JSNodeDOMJIT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E3AFA9641DA6E908002861BD /* JSNodeDOMJIT.cpp */; };
E3150EA71DA7219300194012 /* DOMJITHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = E3150EA51DA7218D00194012 /* DOMJITHelpers.h */; };
+ E377FE4D1DADE16500CDD025 /* NodeConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = E3D049931DADC04500718F3C /* NodeConstants.h */; settings = {ATTRIBUTES = (Private, ); }; };
E38838981BAD145F00D62EE3 /* ScriptModuleLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38838941BAD145F00D62EE3 /* ScriptModuleLoader.cpp */; };
E38838991BAD145F00D62EE3 /* ScriptModuleLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = E38838951BAD145F00D62EE3 /* ScriptModuleLoader.h */; };
E3B2F0EB1D7F4C9D00B0C9D1 /* LoadableClassicScript.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E3B2F0E31D7F35EC00B0C9D1 /* LoadableClassicScript.cpp */; };
@@ -13784,6 +13785,7 @@
E3B2F0E71D7F35EC00B0C9D1 /* LoadableScript.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LoadableScript.h; sourceTree = "<group>"; };
E3B2F0E81D7F35EC00B0C9D1 /* LoadableScriptClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LoadableScriptClient.h; sourceTree = "<group>"; };
E3B2F0E91D7F3D3C00B0C9D1 /* LoadableScript.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LoadableScript.cpp; sourceTree = "<group>"; };
+ E3D049931DADC04500718F3C /* NodeConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NodeConstants.h; sourceTree = "<group>"; };
E3FA38611D716E7600AA5950 /* PendingScriptClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PendingScriptClient.h; sourceTree = "<group>"; };
E401C27417CE53EC00C41A35 /* ElementIteratorAssertions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElementIteratorAssertions.h; sourceTree = "<group>"; };
E401E0A31C3C0B8300F34D10 /* StyleChange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleChange.h; sourceTree = "<group>"; };
@@ -23275,6 +23277,7 @@
63D7B32C0E78CD3F00F7617C /* NodeRenderStyle.h */,
E43105B716750F0C00DB2FB8 /* NodeTraversal.cpp */,
E43105BA16750F1600DB2FB8 /* NodeTraversal.h */,
+ E3D049931DADC04500718F3C /* NodeConstants.h */,
9382AAB10D8C386100F357A6 /* NodeWithIndex.h */,
E46B41F81CB24E70008F11DE /* NoEventDispatchAssertion.h */,
8369E58F1AFDD0300087DF68 /* NonDocumentTypeChildNode.idl */,
@@ -25847,6 +25850,7 @@
51058AE21D67C229009A538C /* MockGamepadProvider.h in Headers */,
5EA3D6DF1C859D7F00300BBB /* MockMediaEndpoint.h in Headers */,
CDF2B0131820540600F2B424 /* MockMediaPlayerMediaSource.h in Headers */,
+ E377FE4D1DADE16500CDD025 /* NodeConstants.h in Headers */,
CDF2B0151820540600F2B424 /* MockMediaSourcePrivate.h in Headers */,
07D6A4F41BED5F8800174146 /* MockRealtimeAudioSource.h in Headers */,
07D6A4F01BECF2D200174146 /* MockRealtimeMediaSource.h in Headers */,
Modified: trunk/Source/WebCore/bindings/js/JSDOMWrapper.h (207238 => 207239)
--- trunk/Source/WebCore/bindings/js/JSDOMWrapper.h 2016-10-12 20:41:49 UTC (rev 207238)
+++ trunk/Source/WebCore/bindings/js/JSDOMWrapper.h 2016-10-12 20:47:51 UTC (rev 207239)
@@ -22,6 +22,7 @@
#pragma once
#include "JSDOMGlobalObject.h"
+#include "NodeConstants.h"
#include <runtime/JSDestructibleObject.h>
namespace WebCore {
@@ -29,11 +30,26 @@
class JSDOMWindow;
class ScriptExecutionContext;
-static const uint8_t JSDOMWrapperType = JSC::LastJSCObjectType + 1;
-static const uint8_t JSNodeType = JSC::LastJSCObjectType + 2;
-static const uint8_t JSDocumentWrapperType = JSC::LastJSCObjectType + 3;
-static const uint8_t JSElementType = JSC::LastJSCObjectType + 4;
+// We encode Node type into JSType. The format is the following.
+// offset | 7 | 6 5 4 | 3 2 1 0 |
+// value | 1 | Kind | NodeType |
+static const uint8_t JSNodeTypeMask = 0b00001111;
+static const uint8_t JSDOMWrapperType = 0b10000000;
+static const uint8_t JSNodeType = 0b10010000;
+static const uint8_t JSTextNodeType = JSNodeType | NodeConstants::TEXT_NODE;
+static const uint8_t JSProcessingInstructionNodeType = JSNodeType | NodeConstants::PROCESSING_INSTRUCTION_NODE;
+static const uint8_t JSDocumentTypeNodeType = JSNodeType | NodeConstants::DOCUMENT_TYPE_NODE;
+static const uint8_t JSDocumentFragmentNodeType = JSNodeType | NodeConstants::DOCUMENT_FRAGMENT_NODE;
+static const uint8_t JSDocumentWrapperType = JSNodeType | NodeConstants::DOCUMENT_NODE;
+static const uint8_t JSCommentNodeType = JSNodeType | NodeConstants::COMMENT_NODE;
+static const uint8_t JSCDATASectionNodeType = JSNodeType | NodeConstants::CDATA_SECTION_NODE;
+static const uint8_t JSAttrNodeType = JSNodeType | NodeConstants::ATTRIBUTE_NODE;
+static const uint8_t JSElementType = 0b10100000 | NodeConstants::ELEMENT_NODE;
+
+static_assert(JSDOMWrapperType > JSC::LastJSCObjectType, "JSC::JSType offers the highest bit.");
+static_assert(NodeConstants::LastNodeType <= JSNodeTypeMask, "NodeType should be represented in 4bit.");
+
class JSDOMObject : public JSC::JSDestructibleObject {
public:
typedef JSC::JSDestructibleObject Base;
Modified: trunk/Source/WebCore/bindings/js/JSNodeCustom.h (207238 => 207239)
--- trunk/Source/WebCore/bindings/js/JSNodeCustom.h 2016-10-12 20:41:49 UTC (rev 207238)
+++ trunk/Source/WebCore/bindings/js/JSNodeCustom.h 2016-10-12 20:47:51 UTC (rev 207239)
@@ -85,4 +85,9 @@
return value.asCell()->type() >= JSNodeType ? JSC::jsCast<JSNode*>(value) : nullptr;
}
+ALWAYS_INLINE JSC::JSValue JSNode::nodeType(JSC::ExecState&) const
+{
+ return JSC::jsNumber(static_cast<uint8_t>(type()) & JSNodeTypeMask);
+}
+
} // namespace WebCore
Modified: trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm (207238 => 207239)
--- trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm 2016-10-12 20:41:49 UTC (rev 207238)
+++ trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm 2016-10-12 20:47:51 UTC (rev 207239)
@@ -1170,6 +1170,40 @@
return $result;
}
+sub GetJSTypeForNode
+{
+ my ($codeGenerator, $interface) = @_;
+
+ if ($codeGenerator->InheritsInterface($interface, "Document")) {
+ return "JSDocumentWrapperType";
+ }
+ if ($codeGenerator->InheritsInterface($interface, "DocumentFragment")) {
+ return "JSDocumentFragmentNodeType";
+ }
+ if ($codeGenerator->InheritsInterface($interface, "DocumentType")) {
+ return "JSDocumentTypeNodeType";
+ }
+ if ($codeGenerator->InheritsInterface($interface, "ProcessingInstruction")) {
+ return "JSProcessingInstructionNodeType";
+ }
+ if ($codeGenerator->InheritsInterface($interface, "CDATASection")) {
+ return "JSCDATASectionNodeType";
+ }
+ if ($codeGenerator->InheritsInterface($interface, "Attr")) {
+ return "JSAttrNodeType";
+ }
+ if ($codeGenerator->InheritsInterface($interface, "Comment")) {
+ return "JSCommentNodeType";
+ }
+ if ($codeGenerator->InheritsInterface($interface, "Text")) {
+ return "JSTextNodeType";
+ }
+ if ($codeGenerator->InheritsInterface($interface, "Element")) {
+ return "JSElementType";
+ }
+ return "JSNodeType";
+}
+
sub GenerateHeader
{
my ($object, $interface, $enumerations, $dictionaries) = @_;
@@ -1368,12 +1402,9 @@
push(@headerContent, " {\n");
if (IsDOMGlobalObject($interface)) {
push(@headerContent, " return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::GlobalObjectType, StructureFlags), info());\n");
- } elsif ($codeGenerator->InheritsInterface($interface, "Document")) {
- push(@headerContent, " return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::JSType(JSDocumentWrapperType), StructureFlags), info());\n");
- } elsif ($codeGenerator->InheritsInterface($interface, "Element")) {
- push(@headerContent, " return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::JSType(JSElementType), StructureFlags), info());\n");
} elsif ($codeGenerator->InheritsInterface($interface, "Node")) {
- push(@headerContent, " return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::JSType(JSNodeType), StructureFlags), info());\n");
+ my $type = GetJSTypeForNode($codeGenerator, $interface);
+ push(@headerContent, " return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::JSType($type), StructureFlags), info());\n");
} else {
push(@headerContent, " return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());\n");
}
@@ -1669,7 +1700,7 @@
push(@headerContent, " $domJITClassName();\n");
push(@headerContent, "#if ENABLE(JIT)\n");
push(@headerContent, " Ref<JSC::DOMJIT::Patchpoint> checkDOM() override;\n");
- push(@headerContent, " Ref<JSC::DOMJIT::Patchpoint> callDOM() override;\n");
+ push(@headerContent, " Ref<JSC::DOMJIT::CallDOMPatchpoint> callDOM() override;\n");
push(@headerContent, "#endif\n");
push(@headerContent, "};\n\n");
}
Modified: trunk/Source/WebCore/dom/Node.idl (207238 => 207239)
--- trunk/Source/WebCore/dom/Node.idl 2016-10-12 20:41:49 UTC (rev 207238)
+++ trunk/Source/WebCore/dom/Node.idl 2016-10-12 20:47:51 UTC (rev 207239)
@@ -46,7 +46,7 @@
// FIXME: the spec says this can also raise on retrieval.
[CEReactions, SetterMayThrowLegacyException] attribute DOMString? nodeValue;
- readonly attribute unsigned short nodeType;
+ [DOMJIT, CustomGetter] readonly attribute unsigned short nodeType;
[DOMJIT] readonly attribute Node? parentNode;
readonly attribute NodeList childNodes;
[DOMJIT] readonly attribute Node? firstChild;
Copied: trunk/Source/WebCore/dom/NodeConstants.h (from rev 207238, trunk/Source/_javascript_Core/domjit/DOMJITGetterSetter.h) (0 => 207239)
--- trunk/Source/WebCore/dom/NodeConstants.h (rev 0)
+++ trunk/Source/WebCore/dom/NodeConstants.h 2016-10-12 20:47:51 UTC (rev 207239)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+namespace WebCore {
+
+struct NodeConstants {
+ enum NodeType {
+ ELEMENT_NODE = 1,
+ ATTRIBUTE_NODE = 2,
+ TEXT_NODE = 3,
+ CDATA_SECTION_NODE = 4,
+ PROCESSING_INSTRUCTION_NODE = 7,
+ COMMENT_NODE = 8,
+ DOCUMENT_NODE = 9,
+ DOCUMENT_TYPE_NODE = 10,
+ DOCUMENT_FRAGMENT_NODE = 11,
+ };
+
+ enum DeprecatedNodeType {
+ ENTITY_REFERENCE_NODE = 5,
+ ENTITY_NODE = 6,
+ NOTATION_NODE = 12,
+ };
+
+ static const uint8_t LastNodeType = NOTATION_NODE;
+};
+
+} // namespace WebCore::NodeType
Modified: trunk/Source/WebCore/domjit/JSNodeDOMJIT.cpp (207238 => 207239)
--- trunk/Source/WebCore/domjit/JSNodeDOMJIT.cpp 2016-10-12 20:41:49 UTC (rev 207238)
+++ trunk/Source/WebCore/domjit/JSNodeDOMJIT.cpp 2016-10-12 20:47:51 UTC (rev 207239)
@@ -50,9 +50,9 @@
}
template<typename WrappedNode>
-static Ref<DOMJIT::Patchpoint> createCallDOMForOffsetAccess(ptrdiff_t offset, IsContainerGuardRequirement isContainerGuardRequirement)
+static Ref<DOMJIT::CallDOMPatchpoint> createCallDOMForOffsetAccess(ptrdiff_t offset, IsContainerGuardRequirement isContainerGuardRequirement)
{
- Ref<DOMJIT::Patchpoint> patchpoint = DOMJIT::Patchpoint::create();
+ Ref<DOMJIT::CallDOMPatchpoint> patchpoint = DOMJIT::CallDOMPatchpoint::create();
patchpoint->numGPScratchRegisters = 1;
patchpoint->setGenerator([=](CCallHelpers& jit, const DOMJIT::PatchpointParams& params) {
JSValueRegs result = params[0].jsValueRegs();
@@ -98,7 +98,7 @@
return checkNode();
}
-Ref<DOMJIT::Patchpoint> NodeFirstChildDOMJIT::callDOM()
+Ref<DOMJIT::CallDOMPatchpoint> NodeFirstChildDOMJIT::callDOM()
{
return createCallDOMForOffsetAccess<Node>(CAST_OFFSET(Node*, ContainerNode*) + ContainerNode::firstChildMemoryOffset(), IsContainerGuardRequirement::Required);
}
@@ -109,7 +109,7 @@
return checkNode();
}
-Ref<DOMJIT::Patchpoint> NodeLastChildDOMJIT::callDOM()
+Ref<DOMJIT::CallDOMPatchpoint> NodeLastChildDOMJIT::callDOM()
{
return createCallDOMForOffsetAccess<Node>(CAST_OFFSET(Node*, ContainerNode*) + ContainerNode::lastChildMemoryOffset(), IsContainerGuardRequirement::Required);
}
@@ -120,7 +120,7 @@
return checkNode();
}
-Ref<DOMJIT::Patchpoint> NodeNextSiblingDOMJIT::callDOM()
+Ref<DOMJIT::CallDOMPatchpoint> NodeNextSiblingDOMJIT::callDOM()
{
return createCallDOMForOffsetAccess<Node>(Node::nextSiblingMemoryOffset(), IsContainerGuardRequirement::NotRequired);
}
@@ -131,7 +131,7 @@
return checkNode();
}
-Ref<DOMJIT::Patchpoint> NodePreviousSiblingDOMJIT::callDOM()
+Ref<DOMJIT::CallDOMPatchpoint> NodePreviousSiblingDOMJIT::callDOM()
{
return createCallDOMForOffsetAccess<Node>(Node::previousSiblingMemoryOffset(), IsContainerGuardRequirement::NotRequired);
}
@@ -142,11 +142,32 @@
return checkNode();
}
-Ref<DOMJIT::Patchpoint> NodeParentNodeDOMJIT::callDOM()
+Ref<DOMJIT::CallDOMPatchpoint> NodeParentNodeDOMJIT::callDOM()
{
return createCallDOMForOffsetAccess<ContainerNode>(Node::parentNodeMemoryOffset(), IsContainerGuardRequirement::NotRequired);
}
+// Node#nodeType.
+Ref<DOMJIT::Patchpoint> NodeNodeTypeDOMJIT::checkDOM()
+{
+ return checkNode();
}
+Ref<DOMJIT::CallDOMPatchpoint> NodeNodeTypeDOMJIT::callDOM()
+{
+ Ref<DOMJIT::CallDOMPatchpoint> patchpoint = DOMJIT::CallDOMPatchpoint::create();
+ patchpoint->requireGlobalObject = false;
+ patchpoint->setGenerator([=](CCallHelpers& jit, const DOMJIT::PatchpointParams& params) {
+ JSValueRegs result = params[0].jsValueRegs();
+ GPRReg node = params[1].gpr();
+ jit.load8(CCallHelpers::Address(node, JSC::JSCell::typeInfoTypeOffset()), result.payloadGPR());
+ jit.and32(CCallHelpers::TrustedImm32(JSNodeTypeMask), result.payloadGPR());
+ jit.boxInt32(result.payloadGPR(), result);
+ return CCallHelpers::JumpList();
+ });
+ return patchpoint;
+}
+
+}
+
#endif