Diff
Modified: trunk/LayoutTests/ChangeLog (207012 => 207013)
--- trunk/LayoutTests/ChangeLog 2016-10-10 19:42:51 UTC (rev 207012)
+++ trunk/LayoutTests/ChangeLog 2016-10-10 19:57:55 UTC (rev 207013)
@@ -1,3 +1,15 @@
+2016-10-10 Yusuke Suzuki <[email protected]>
+
+ [DOMJIT] Implement Node accessors in DOMJIT
+ https://bugs.webkit.org/show_bug.cgi?id=163005
+
+ Reviewed by Filip Pizlo.
+
+ * 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.
+
2016-10-10 Ryan Haddad <[email protected]>
Marking media/controls/airplay-picker.html as flaky on ElCapitan+.
Added: trunk/LayoutTests/js/dom/domjit-accessor-monomorphic-expected.txt (0 => 207013)
--- trunk/LayoutTests/js/dom/domjit-accessor-monomorphic-expected.txt (rev 0)
+++ trunk/LayoutTests/js/dom/domjit-accessor-monomorphic-expected.txt 2016-10-10 19:57:55 UTC (rev 207013)
@@ -0,0 +1,13 @@
+Test DOMJIT accessors work in monomorphic call sites.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+PASS func("firstChild", document.getElementById("target"), document.getElementById("firstChild")) is true
+PASS func("lastChild", document.getElementById("target"), document.getElementById("lastChild")) is true
+PASS func("nextSibling", document.getElementById("target"), document.getElementById("nextSibling")) is true
+PASS func("previousSibling", document.getElementById("target"), document.getElementById("previousSibling")) is true
+PASS func("parentNode", document.getElementById("target"), document.getElementById("parentNode")) is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/js/dom/domjit-accessor-monomorphic.html (0 => 207013)
--- trunk/LayoutTests/js/dom/domjit-accessor-monomorphic.html (rev 0)
+++ trunk/LayoutTests/js/dom/domjit-accessor-monomorphic.html 2016-10-10 19:57:55 UTC (rev 207013)
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<div id="parentNode">
+<div id="previousSibling"></div><div id="target"><div id="firstChild"></div><div id="lastChild"></div></div><div id="nextSibling"></div>
+</div>
+
+<script>
+description('Test DOMJIT accessors work in monomorphic call sites.');
+var tests = [
+ "firstChild",
+ "lastChild",
+ "nextSibling",
+ "previousSibling",
+ "parentNode",
+].map(function (name) {
+ var func = `
+ return function ${name}(name, element, result) {
+ for (var i = 0; i < 1e4; ++i) {
+ if (element.${name} !== result)
+ return false;
+ }
+ return true;
+ };
+ `;
+ return [ name, Function(func)() ];
+});
+
+for (var [name, func] of tests) {
+ shouldBeTrue(`func("${name}", document.getElementById("target"), document.getElementById("${name}"))`);
+}
+</script>
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/js/dom/domjit-accessor-polymorphic-expected.txt (0 => 207013)
--- trunk/LayoutTests/js/dom/domjit-accessor-polymorphic-expected.txt (rev 0)
+++ trunk/LayoutTests/js/dom/domjit-accessor-polymorphic-expected.txt 2016-10-10 19:57:55 UTC (rev 207013)
@@ -0,0 +1,8 @@
+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
+
Added: trunk/LayoutTests/js/dom/domjit-accessor-polymorphic.html (0 => 207013)
--- trunk/LayoutTests/js/dom/domjit-accessor-polymorphic.html (rev 0)
+++ trunk/LayoutTests/js/dom/domjit-accessor-polymorphic.html 2016-10-10 19:57:55 UTC (rev 207013)
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<div id="parentNode0">
+<div id="previousSibling0"></div><div id="target0"><div id="firstChild0"></div><div id="lastChild0"></div></div><div id="nextSibling0"></div>
+</div>
+
+<section id="parentNode1">
+<section id="previousSibling1"></section><section id="target1"><section id="firstChild1"></section><section id="lastChild1"></section></section><section id="nextSibling1"></section>
+</section>
+
+<span id="parentNode2">
+<span id="previousSibling2"></span><span id="target2"><span id="firstChild2"></span><span id="lastChild2"></span></span><span id="nextSibling2"></span>
+</span>
+
+<script>
+description('Test DOMJIT accessors work in polymorphic call sites.');
+var tests = [
+ "firstChild",
+ "lastChild",
+ "nextSibling",
+ "previousSibling",
+ "parentNode",
+].map(function (name) {
+ var func = `
+ return function ${name}(name, element, result) {
+ if (element.${name} !== result)
+ return false;
+ return true;
+ };
+ `;
+ return [ name, Function(func)() ];
+});
+
+for (var [name, func] of tests) {
+ for (var i = 0; i < 1e4; ++i) {
+ for (var j = 0; j < 3; ++j) {
+ shouldBeTrueQuiet(`func("${name}", document.getElementById("target${j}"), document.getElementById("${name}${j}"))`);
+ }
+ }
+}
+
+</script>
+<script src=""
+</body>
+</html>
Modified: trunk/Source/_javascript_Core/ChangeLog (207012 => 207013)
--- trunk/Source/_javascript_Core/ChangeLog 2016-10-10 19:42:51 UTC (rev 207012)
+++ trunk/Source/_javascript_Core/ChangeLog 2016-10-10 19:57:55 UTC (rev 207013)
@@ -1,3 +1,32 @@
+2016-10-10 Yusuke Suzuki <[email protected]>
+
+ [DOMJIT] Implement Node accessors in DOMJIT
+ https://bugs.webkit.org/show_bug.cgi?id=163005
+
+ Reviewed by Filip Pizlo.
+
+ 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:
+
2016-10-09 Filip Pizlo <[email protected]>
Air should expose API for pinning registers
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (207012 => 207013)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2016-10-10 19:42:51 UTC (rev 207012)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2016-10-10 19:57:55 UTC (rev 207013)
@@ -1639,6 +1639,11 @@
m_jit.setupArgumentsWithExecState(arg1, arg2);
return appendCallSetResult(operation, result);
}
+ JITCompiler::Call callOperation(J_JITOperation_EGP operation, GPRReg result, GPRReg arg1, GPRReg arg2)
+ {
+ m_jit.setupArgumentsWithExecState(arg1, arg2);
+ return appendCallSetResult(operation, result);
+ }
JITCompiler::Call callOperation(J_JITOperation_EJJ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
{
m_jit.setupArgumentsWithExecState(arg1, arg2);
@@ -1894,6 +1899,11 @@
m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(pointer));
return appendCallSetResult(operation, result.payloadGPR(), result.tagGPR());
}
+ JITCompiler::Call callOperation(J_JITOperation_EGP operation, JSValueRegs result, GPRReg arg1, GPRReg arg2)
+ {
+ m_jit.setupArgumentsWithExecState(arg1, arg2);
+ return appendCallSetResult(operation, result.payloadGPR(), result.tagGPR());
+ }
JITCompiler::Call callOperation(J_JITOperation_EP operation, JSValueRegs result, GPRReg arg1)
{
m_jit.setupArgumentsWithExecState(arg1);
Modified: trunk/Source/_javascript_Core/domjit/DOMJITSlowPathCalls.h (207012 => 207013)
--- trunk/Source/_javascript_Core/domjit/DOMJITSlowPathCalls.h 2016-10-10 19:42:51 UTC (rev 207012)
+++ trunk/Source/_javascript_Core/domjit/DOMJITSlowPathCalls.h 2016-10-10 19:57:55 UTC (rev 207013)
@@ -30,5 +30,6 @@
// macro(OperationType, ArgType1, ArgType2, ...)
#define DOMJIT_SLOW_PATH_CALLS(macro) \
macro(J_JITOperation_EP, JSValueRegs, GPRReg) \
+ macro(J_JITOperation_EGP, JSValueRegs, GPRReg, GPRReg) \
#endif
Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (207012 => 207013)
--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2016-10-10 19:42:51 UTC (rev 207012)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2016-10-10 19:57:55 UTC (rev 207013)
@@ -8731,6 +8731,8 @@
patchpoint->appendSomeRegister(cell);
patchpoint->numGPScratchRegisters = domJIT->numGPScratchRegisters;
patchpoint->numFPScratchRegisters = domJIT->numFPScratchRegisters;
+ patchpoint->append(m_tagMask, ValueRep::reg(GPRInfo::tagMaskRegister));
+ patchpoint->append(m_tagTypeNumber, ValueRep::reg(GPRInfo::tagTypeNumberRegister));
State* state = &m_ftlState;
Node* node = m_node;
@@ -8774,17 +8776,20 @@
PatchpointValue* patchpoint = m_out.patchpoint(Int64);
patchpoint->appendSomeRegister(globalObject);
patchpoint->appendSomeRegister(cell);
- patchpoint->append(m_tagMask, ValueRep::lateReg(GPRInfo::tagMaskRegister));
- patchpoint->append(m_tagTypeNumber, ValueRep::lateReg(GPRInfo::tagTypeNumberRegister));
+ patchpoint->append(m_tagMask, ValueRep::reg(GPRInfo::tagMaskRegister));
+ patchpoint->append(m_tagTypeNumber, ValueRep::reg(GPRInfo::tagTypeNumberRegister));
RefPtr<PatchpointExceptionHandle> exceptionHandle = preparePatchpointForExceptions(patchpoint);
patchpoint->clobber(RegisterSet::macroScratchRegisters());
patchpoint->numGPScratchRegisters = domJIT->numGPScratchRegisters;
patchpoint->numFPScratchRegisters = domJIT->numFPScratchRegisters;
+ patchpoint->resultConstraint = ValueRep::SomeEarlyRegister;
State* state = &m_ftlState;
Node* node = m_node;
patchpoint->setGenerator(
[=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
+ AllowMacroScratchRegisterUsage allowScratch(jit);
+
Vector<GPRReg> gpScratch;
Vector<FPRReg> fpScratch;
Vector<DOMJIT::Reg> regs;
@@ -8794,8 +8799,6 @@
regs.append(JSValueRegs(params[0].gpr()));
regs.append(params[1].gpr());
regs.append(params[2].gpr());
- regs.append(params[3].gpr());
- regs.append(params[4].gpr());
for (unsigned i = 0; i < domJIT->numGPScratchRegisters; ++i)
gpScratch.append(params.gpScratch(i));
Modified: trunk/Source/_javascript_Core/heap/WeakImpl.h (207012 => 207013)
--- trunk/Source/_javascript_Core/heap/WeakImpl.h 2016-10-10 19:42:51 UTC (rev 207012)
+++ trunk/Source/_javascript_Core/heap/WeakImpl.h 2016-10-10 19:57:55 UTC (rev 207013)
@@ -51,7 +51,9 @@
void setState(State);
const JSValue& jsValue();
+ static ptrdiff_t offsetOfJSValue() { return OBJECT_OFFSETOF(WeakImpl, m_jsValue); }
WeakHandleOwner* weakHandleOwner();
+ static ptrdiff_t offsetOfWeakHandleOwner() { return OBJECT_OFFSETOF(WeakImpl, m_weakHandleOwner); }
void* context();
static WeakImpl* asWeakImpl(JSValue*);
Modified: trunk/Source/_javascript_Core/jit/AssemblyHelpers.h (207012 => 207013)
--- trunk/Source/_javascript_Core/jit/AssemblyHelpers.h 2016-10-10 19:42:51 UTC (rev 207012)
+++ trunk/Source/_javascript_Core/jit/AssemblyHelpers.h 2016-10-10 19:57:55 UTC (rev 207013)
@@ -1204,6 +1204,16 @@
move(TrustedImm32(JSValue::Int32Tag), boxedRegs.tagGPR());
#endif
}
+
+ void boxCell(GPRReg cellGPR, JSValueRegs boxedRegs)
+ {
+#if USE(JSVALUE64)
+ move(cellGPR, boxedRegs.gpr());
+#else
+ move(cellGPR, boxedRegs.payloadGPR());
+ move(TrustedImm32(JSValue::CellTag), boxedRegs.tagGPR());
+#endif
+ }
void callExceptionFuzz();
Modified: trunk/Source/_javascript_Core/jit/JITOperations.h (207012 => 207013)
--- trunk/Source/_javascript_Core/jit/JITOperations.h 2016-10-10 19:42:51 UTC (rev 207012)
+++ trunk/Source/_javascript_Core/jit/JITOperations.h 2016-10-10 19:57:55 UTC (rev 207013)
@@ -155,6 +155,7 @@
typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJssReo)(ExecState*, JSString*, RegExpObject*);
typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJssReoJss)(ExecState*, JSString*, RegExpObject*, JSString*);
typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJP)(ExecState*, EncodedJSValue, void*);
+typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EGP)(ExecState*, JSGlobalObject*, void*);
typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EP)(ExecState*, void*);
typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EPP)(ExecState*, void*, void*);
typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EPS)(ExecState*, void*, size_t);
Modified: trunk/Source/WTF/ChangeLog (207012 => 207013)
--- trunk/Source/WTF/ChangeLog 2016-10-10 19:42:51 UTC (rev 207012)
+++ trunk/Source/WTF/ChangeLog 2016-10-10 19:57:55 UTC (rev 207013)
@@ -1,3 +1,16 @@
+2016-10-10 Yusuke Suzuki <[email protected]>
+
+ [DOMJIT] Implement Node accessors in DOMJIT
+ https://bugs.webkit.org/show_bug.cgi?id=163005
+
+ Reviewed by Filip Pizlo.
+
+ 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:
+
2016-10-07 Chris Dumez <[email protected]>
window.navigator.language incorrectly returns all lowercase string
Modified: trunk/Source/WTF/wtf/StdLibExtras.h (207012 => 207013)
--- trunk/Source/WTF/wtf/StdLibExtras.h 2016-10-10 19:42:51 UTC (rev 207012)
+++ trunk/Source/WTF/wtf/StdLibExtras.h 2016-10-10 19:57:55 UTC (rev 207013)
@@ -68,6 +68,8 @@
// NULL can cause compiler problems, especially in cases of multiple inheritance.
#define OBJECT_OFFSETOF(class, field) (reinterpret_cast<ptrdiff_t>(&(reinterpret_cast<class*>(0x4000)->field)) - 0x4000)
+#define CAST_OFFSET(from, to) (reinterpret_cast<uintptr_t>(static_cast<to>((reinterpret_cast<from>(0x4000)))) - 0x4000)
+
// STRINGIZE: Can convert any value to quoted string, even expandable macros
#define STRINGIZE(exp) #exp
#define STRINGIZE_VALUE_OF(exp) STRINGIZE(exp)
Modified: trunk/Source/WebCore/CMakeLists.txt (207012 => 207013)
--- trunk/Source/WebCore/CMakeLists.txt 2016-10-10 19:42:51 UTC (rev 207012)
+++ trunk/Source/WebCore/CMakeLists.txt 2016-10-10 19:57:55 UTC (rev 207013)
@@ -49,6 +49,7 @@
"${WEBCORE_DIR}/cssjit"
"${WEBCORE_DIR}/dom"
"${WEBCORE_DIR}/dom/default"
+ "${WEBCORE_DIR}/domjit"
"${WEBCORE_DIR}/editing"
"${WEBCORE_DIR}/fileapi"
"${WEBCORE_DIR}/history"
@@ -1529,6 +1530,8 @@
dom/default/PlatformMessagePortChannel.cpp
+ domjit/JSNodeDOMJIT.cpp
+
editing/AlternativeTextController.cpp
editing/AppendNodeCommand.cpp
editing/ApplyBlockElementCommand.cpp
Modified: trunk/Source/WebCore/ChangeLog (207012 => 207013)
--- trunk/Source/WebCore/ChangeLog 2016-10-10 19:42:51 UTC (rev 207012)
+++ trunk/Source/WebCore/ChangeLog 2016-10-10 19:57:55 UTC (rev 207013)
@@ -1,3 +1,132 @@
+2016-10-10 Yusuke Suzuki <[email protected]>
+
+ [DOMJIT] Implement Node accessors in DOMJIT
+ https://bugs.webkit.org/show_bug.cgi?id=163005
+
+ Reviewed by Filip Pizlo.
+
+ 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/_javascript_Core/domjit/DOMJITSlowPathCalls.h.
+ * ForwardingHeaders/domjit/DOMJITPatchpointParams.h: Copied from Source/_javascript_Core/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):
+
2016-10-10 Wenson Hsieh <[email protected]>
Support InputEvent.data for the new InputEvent spec
Modified: trunk/Source/WebCore/ForwardingHeaders/domjit/DOMJITGetterSetter.h (207012 => 207013)
--- trunk/Source/WebCore/ForwardingHeaders/domjit/DOMJITGetterSetter.h 2016-10-10 19:42:51 UTC (rev 207012)
+++ trunk/Source/WebCore/ForwardingHeaders/domjit/DOMJITGetterSetter.h 2016-10-10 19:57:55 UTC (rev 207013)
@@ -1,3 +1,28 @@
+/*
+ * 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.
+ */
+
#ifndef WebCore_FWD_DOMJITGetterSetter_h
#define WebCore_FWD_DOMJITGetterSetter_h
#include <_javascript_Core/DOMJITGetterSetter.h>
Copied: trunk/Source/WebCore/ForwardingHeaders/domjit/DOMJITPatchpoint.h (from rev 207012, trunk/Source/_javascript_Core/domjit/DOMJITSlowPathCalls.h) (0 => 207013)
--- trunk/Source/WebCore/ForwardingHeaders/domjit/DOMJITPatchpoint.h (rev 0)
+++ trunk/Source/WebCore/ForwardingHeaders/domjit/DOMJITPatchpoint.h 2016-10-10 19:57:55 UTC (rev 207013)
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+#ifndef WebCore_FWD_DOMJITPatchpoint_h
+#define WebCore_FWD_DOMJITPatchpoint_h
+#include <_javascript_Core/DOMJITPatchpoint.h>
+#endif
Copied: trunk/Source/WebCore/ForwardingHeaders/domjit/DOMJITPatchpointParams.h (from rev 207012, trunk/Source/_javascript_Core/domjit/DOMJITSlowPathCalls.h) (0 => 207013)
--- trunk/Source/WebCore/ForwardingHeaders/domjit/DOMJITPatchpointParams.h (rev 0)
+++ trunk/Source/WebCore/ForwardingHeaders/domjit/DOMJITPatchpointParams.h 2016-10-10 19:57:55 UTC (rev 207013)
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+#ifndef WebCore_FWD_DOMJITPatchpointParams_h
+#define WebCore_FWD_DOMJITPatchpointParams_h
+#include <_javascript_Core/DOMJITPatchpointParams.h>
+#endif
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (207012 => 207013)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2016-10-10 19:42:51 UTC (rev 207012)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2016-10-10 19:57:55 UTC (rev 207013)
@@ -6142,6 +6142,8 @@
E1FF57A60F01256B00891EBB /* ThreadGlobalData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E1FF57A50F01256B00891EBB /* ThreadGlobalData.cpp */; };
E1FF8F6C180DB5BE00132674 /* CryptoAlgorithmRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E1FF8F6A180DB5BE00132674 /* CryptoAlgorithmRegistry.cpp */; };
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 */; };
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 */; };
@@ -13774,8 +13776,10 @@
E1FF8F661807460800132674 /* JSWebKitSubtleCryptoCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSWebKitSubtleCryptoCustom.cpp; sourceTree = "<group>"; };
E1FF8F6A180DB5BE00132674 /* CryptoAlgorithmRegistry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CryptoAlgorithmRegistry.cpp; sourceTree = "<group>"; };
E1FF8F6B180DB5BE00132674 /* CryptoAlgorithmRegistry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CryptoAlgorithmRegistry.h; sourceTree = "<group>"; };
+ E3150EA51DA7218D00194012 /* DOMJITHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMJITHelpers.h; sourceTree = "<group>"; };
E38838941BAD145F00D62EE3 /* ScriptModuleLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScriptModuleLoader.cpp; sourceTree = "<group>"; };
E38838951BAD145F00D62EE3 /* ScriptModuleLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScriptModuleLoader.h; sourceTree = "<group>"; };
+ E3AFA9641DA6E908002861BD /* JSNodeDOMJIT.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSNodeDOMJIT.cpp; sourceTree = "<group>"; };
E3B2F0E31D7F35EC00B0C9D1 /* LoadableClassicScript.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LoadableClassicScript.cpp; sourceTree = "<group>"; };
E3B2F0E41D7F35EC00B0C9D1 /* LoadableClassicScript.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LoadableClassicScript.h; sourceTree = "<group>"; };
E3B2F0E71D7F35EC00B0C9D1 /* LoadableScript.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LoadableScript.h; sourceTree = "<group>"; };
@@ -14882,6 +14886,7 @@
F523D18402DE42E8018635CA /* css */,
26B9998D1803ADFA00D01121 /* cssjit */,
F523D32402DE4478018635CA /* dom */,
+ E3AFA9631DA6E8AF002861BD /* domjit */,
93309D86099E64910056E581 /* editing */,
976D6C57122B8A18001FD1F7 /* fileapi */,
51741D080B07257000ED442C /* history */,
@@ -22318,6 +22323,15 @@
name = Crypto;
sourceTree = "<group>";
};
+ E3AFA9631DA6E8AF002861BD /* domjit */ = {
+ isa = PBXGroup;
+ children = (
+ E3150EA51DA7218D00194012 /* DOMJITHelpers.h */,
+ E3AFA9641DA6E908002861BD /* JSNodeDOMJIT.cpp */,
+ );
+ path = domjit;
+ sourceTree = "<group>";
+ };
E46E97860DAAD61B0071E894 /* animation */ = {
isa = PBXGroup;
children = (
@@ -24787,6 +24801,7 @@
A871DC240A15205700B12A68 /* HTMLMetaElement.h in Headers */,
A454424B119B3661009BE912 /* HTMLMeterElement.h in Headers */,
A8CFF7A70A156978000A4234 /* HTMLModElement.h in Headers */,
+ E3150EA71DA7219300194012 /* DOMJITHelpers.h in Headers */,
A8DF3FD4097FA0FC0052981B /* HTMLNameCollection.h in Headers */,
A871D45A0A127CBC00B12A68 /* HTMLObjectElement.h in Headers */,
A8EA79F10A1916DF00A8EF5F /* HTMLOListElement.h in Headers */,
@@ -28698,6 +28713,7 @@
BCC065870F3CE2A700CD2D87 /* JSClientRect.cpp in Sources */,
46A58AC51D46B3FA00432036 /* JSClientRectCustom.cpp in Sources */,
BCC065890F3CE2A700CD2D87 /* JSClientRectList.cpp in Sources */,
+ E3150EA61DA7219000194012 /* JSNodeDOMJIT.cpp in Sources */,
51FB5505113E3E9100821176 /* JSCloseEvent.cpp in Sources */,
A584FE3B1864E2D800843B10 /* JSCommandLineAPIHost.cpp in Sources */,
A584FE381864DAC100843B10 /* JSCommandLineAPIHostCustom.cpp in Sources */,
Modified: trunk/Source/WebCore/bindings/js/JSDOMGlobalObject.h (207012 => 207013)
--- trunk/Source/WebCore/bindings/js/JSDOMGlobalObject.h 2016-10-10 19:42:51 UTC (rev 207012)
+++ trunk/Source/WebCore/bindings/js/JSDOMGlobalObject.h 2016-10-10 19:57:55 UTC (rev 207013)
@@ -72,6 +72,7 @@
DOMWrapperWorld& world() { return m_world.get(); }
bool worldIsNormal() const { return m_worldIsNormal; }
+ static ptrdiff_t offsetOfWorldIsNormal() { return OBJECT_OFFSETOF(JSDOMGlobalObject, m_worldIsNormal); }
JSBuiltinInternalFunctions& builtinInternalFunctions() { return m_builtinInternalFunctions; }
@@ -95,7 +96,7 @@
Event* m_currentEvent;
Ref<DOMWrapperWorld> m_world;
- bool m_worldIsNormal;
+ uint8_t m_worldIsNormal;
private:
void addBuiltinGlobals(JSC::VM&);
Modified: trunk/Source/WebCore/bindings/js/JSDOMWrapper.h (207012 => 207013)
--- trunk/Source/WebCore/bindings/js/JSDOMWrapper.h 2016-10-10 19:42:51 UTC (rev 207012)
+++ trunk/Source/WebCore/bindings/js/JSDOMWrapper.h 2016-10-10 19:57:55 UTC (rev 207013)
@@ -59,6 +59,7 @@
static constexpr bool isDOMWrapper = true;
ImplementationClass& wrapped() const { return const_cast<ImplementationClass&>(m_wrapped.get()); }
+ static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSDOMWrapper<ImplementationClass>, m_wrapped); }
protected:
JSDOMWrapper(JSC::Structure* structure, JSC::JSGlobalObject& globalObject, Ref<ImplementationClass>&& impl)
Modified: trunk/Source/WebCore/bindings/js/ScriptWrappable.h (207012 => 207013)
--- trunk/Source/WebCore/bindings/js/ScriptWrappable.h 2016-10-10 19:42:51 UTC (rev 207012)
+++ trunk/Source/WebCore/bindings/js/ScriptWrappable.h 2016-10-10 19:57:55 UTC (rev 207013)
@@ -48,6 +48,9 @@
void setWrapper(JSDOMObject*, JSC::WeakHandleOwner*, void*);
void clearWrapper(JSDOMObject*);
+ template<typename Derived>
+ static ptrdiff_t offsetOfWrapper() { return CAST_OFFSET(Derived*, ScriptWrappable*) + OBJECT_OFFSETOF(ScriptWrappable, m_wrapper); }
+
protected:
~ScriptWrappable() { }
Modified: trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm (207012 => 207013)
--- trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm 2016-10-10 19:42:51 UTC (rev 207012)
+++ trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm 2016-10-10 19:57:55 UTC (rev 207013)
@@ -641,6 +641,7 @@
push(@specials, "DontEnum") if ($attribute->signature->extendedAttributes->{NotEnumerable} || $is_global_constructor);
push(@specials, "ReadOnly") if IsReadonly($attribute);
push(@specials, "CustomAccessor") unless $is_global_constructor or IsJSBuiltin($interface, $attribute);
+ push(@specials, "DOMJITAttribute") if $attribute->signature->extendedAttributes->{"DOMJIT"};
push(@specials, "Accessor | Builtin") if IsJSBuiltin($interface, $attribute);
return (@specials > 0) ? join(" | ", @specials) : "0";
}
@@ -1418,6 +1419,8 @@
my $hasForwardDeclaringFunctions = 0;
my $hasForwardDeclaringAttributes = 0;
+ my $hasDOMJITAttributes = 0;
+
# Attribute and function enums
if ($numAttributes > 0) {
push(@headerContent, " static ${className}* castForAttribute(JSC::ExecState*, JSC::EncodedJSValue);\n");
@@ -1434,6 +1437,7 @@
$needsVisitChildren = 1;
push(@headerContent, "#endif\n") if $conditionalString;
}
+ $hasDOMJITAttributes = 1 if $attribute->signature->extendedAttributes->{"DOMJIT"};
$hasForwardDeclaringAttributes = 1 if $attribute->signature->extendedAttributes->{ForwardDeclareInHeader};
}
@@ -1641,6 +1645,29 @@
}
}
+ if ($hasDOMJITAttributes) {
+ $headerIncludes{"<domjit/DOMJITGetterSetter.h>"} = 1;
+ push(@headerContent,"// DOMJIT emitters for attributes\n\n");
+ foreach my $attribute (@{$interface->attributes}) {
+ next unless $attribute->signature->extendedAttributes->{"DOMJIT"};
+
+ my $interfaceName = $interface->name;
+ my $className = $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name);
+ my $domJITClassName = $className . "DOMJIT";
+
+ push(@headerContent, "JSC::DOMJIT::GetterSetter* domJITGetterSetterFor$className(void);\n");
+
+ push(@headerContent, "class $domJITClassName : public JSC::DOMJIT::GetterSetter {\n");
+ push(@headerContent, "public:\n");
+ 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, "#endif\n");
+ push(@headerContent, "};\n\n");
+ }
+ }
+
if (HasCustomConstructor($interface)) {
push(@headerContent, "// Custom constructor\n");
push(@headerContent, "JSC::EncodedJSValue JSC_HOST_CALL construct${className}(JSC::ExecState&);\n\n");
@@ -1720,14 +1747,19 @@
my $special = GetJSCAttributesForAttribute($interface, $attribute);
push(@$hashSpecials, $special);
- my $getter = GetAttributeGetterName($interface, $className, $attribute);
- push(@$hashValue1, $getter);
-
- if (IsReadonly($attribute)) {
+ if ($attribute->signature->extendedAttributes->{"DOMJIT"}) {
+ push(@$hashValue1, "domJITGetterSetterFor" . $interface->name . $codeGenerator->WK_ucfirst($attribute->signature->name));
push(@$hashValue2, "0");
} else {
- my $setter = GetAttributeSetterName($interface, $className, $attribute);
- push(@$hashValue2, $setter);
+ my $getter = GetAttributeGetterName($interface, $className, $attribute);
+ push(@$hashValue1, $getter);
+
+ if (IsReadonly($attribute)) {
+ push(@$hashValue2, "0");
+ } else {
+ my $setter = GetAttributeSetterName($interface, $className, $attribute);
+ push(@$hashValue2, $setter);
+ }
}
my $conditional = $attribute->signature->extendedAttributes->{Conditional};
@@ -2506,17 +2538,23 @@
my @specials = ();
push(@specials, "DontDelete") unless $attribute->signature->extendedAttributes->{Deletable};
push(@specials, "ReadOnly") if IsReadonly($attribute);
+ push(@specials, "DOMJITAttribute") if $attribute->signature->extendedAttributes->{"DOMJIT"};
my $special = (@specials > 0) ? join(" | ", @specials) : "0";
push(@hashSpecials, $special);
- my $getter = GetAttributeGetterName($interface, $className, $attribute);
- push(@hashValue1, $getter);
-
- if (IsReadonly($attribute)) {
+ if ($attribute->signature->extendedAttributes->{"DOMJIT"}) {
+ push(@hashValue1, "domJITGetterSetterFor" . $interface->name . $codeGenerator->WK_ucfirst($attribute->signature->name));
push(@hashValue2, "0");
} else {
- my $setter = GetAttributeSetterName($interface, $className, $attribute);
- push(@hashValue2, $setter);
+ my $getter = GetAttributeGetterName($interface, $className, $attribute);
+ push(@hashValue1, $getter);
+
+ if (IsReadonly($attribute)) {
+ push(@hashValue2, "0");
+ } else {
+ my $setter = GetAttributeSetterName($interface, $className, $attribute);
+ push(@hashValue2, $setter);
+ }
}
my $conditional = $attribute->signature->extendedAttributes->{Conditional};
@@ -3094,6 +3132,26 @@
push(@implContent, "}\n\n");
+ if ($attribute->signature->extendedAttributes->{"DOMJIT"}) {
+ $implIncludes{"<wtf/NeverDestroyed.h>"} = 1;
+ my $interfaceName = $interface->name;
+ my $attributeName = $attribute->signature->name;
+ my $generatorName = $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name);
+ my $domJITClassName = $generatorName . "DOMJIT";
+ my $getter = GetAttributeGetterName($interface, $generatorName, $attribute);
+ my $setter = IsReadonly($attribute) ? "nullptr" : GetAttributeSetterName($interface, $generatorName, $attribute);
+ push(@implContent, "$domJITClassName::$domJITClassName()\n");
+ push(@implContent, " : JSC::DOMJIT::GetterSetter($getter, $setter, ${className}::info())\n");
+ push(@implContent, "{\n");
+ push(@implContent, "}\n\n");
+
+ push(@implContent, "JSC::DOMJIT::GetterSetter* domJITGetterSetterFor" . $generatorName . "()\n");
+ push(@implContent, "{\n");
+ push(@implContent, " static NeverDestroyed<$domJITClassName> compiler;\n");
+ push(@implContent, " return &compiler.get();\n");
+ push(@implContent, "}\n\n");
+ }
+
push(@implContent, "#endif\n\n") if $attributeConditionalString;
}
@@ -5094,6 +5152,8 @@
$firstTargetType = "static_cast<BuiltinGenerator>";
} elsif ("@$specials[$i]" =~ m/ConstantInteger/) {
$firstTargetType = "";
+ } elsif ("@$specials[$i]" =~ m/DOMJITAttribute/) {
+ $firstTargetType = "static_cast<DOMJITGetterSetterGenerator>";
} else {
$firstTargetType = "static_cast<PropertySlot::GetValueFunc>";
$secondTargetType = "static_cast<PutPropertySlot::PutValueFunc>";
Modified: trunk/Source/WebCore/bindings/scripts/IDLAttributes.txt (207012 => 207013)
--- trunk/Source/WebCore/bindings/scripts/IDLAttributes.txt 2016-10-10 19:42:51 UTC (rev 207012)
+++ trunk/Source/WebCore/bindings/scripts/IDLAttributes.txt 2016-10-10 19:57:55 UTC (rev 207013)
@@ -55,6 +55,7 @@
CustomSetPrototype
CustomSetter
CustomToJSObject
+DOMJIT
Deletable
DoNotCheckConstants
DoNotCheckSecurity
Modified: trunk/Source/WebCore/dom/ContainerNode.h (207012 => 207013)
--- trunk/Source/WebCore/dom/ContainerNode.h 2016-10-10 19:42:51 UTC (rev 207012)
+++ trunk/Source/WebCore/dom/ContainerNode.h 2016-10-10 19:57:55 UTC (rev 207013)
@@ -41,6 +41,7 @@
Node* firstChild() const { return m_firstChild; }
static ptrdiff_t firstChildMemoryOffset() { return OBJECT_OFFSETOF(ContainerNode, m_firstChild); }
Node* lastChild() const { return m_lastChild; }
+ static ptrdiff_t lastChildMemoryOffset() { return OBJECT_OFFSETOF(ContainerNode, m_lastChild); }
bool hasChildNodes() const { return m_firstChild; }
bool hasOneChild() const { return m_firstChild && !m_firstChild->nextSibling(); }
Modified: trunk/Source/WebCore/dom/Node.h (207012 => 207013)
--- trunk/Source/WebCore/dom/Node.h 2016-10-10 19:42:51 UTC (rev 207012)
+++ trunk/Source/WebCore/dom/Node.h 2016-10-10 19:57:55 UTC (rev 207013)
@@ -559,10 +559,11 @@
void updateAncestorConnectedSubframeCountForRemoval() const;
void updateAncestorConnectedSubframeCountForInsertion() const;
-#if ENABLE(CSS_SELECTOR_JIT)
+#if ENABLE(JIT)
static ptrdiff_t nodeFlagsMemoryOffset() { return OBJECT_OFFSETOF(Node, m_nodeFlags); }
static ptrdiff_t rareDataMemoryOffset() { return OBJECT_OFFSETOF(Node, m_data.m_rareData); }
static int32_t flagIsText() { return IsTextFlag; }
+ static int32_t flagIsContainer() { return IsContainerFlag; }
static int32_t flagIsElement() { return IsElementFlag; }
static int32_t flagIsHTML() { return IsHTMLFlag; }
static int32_t flagIsLink() { return IsLinkFlag; }
@@ -574,7 +575,7 @@
static int32_t flagAffectsNextSiblingElementStyle() { return AffectsNextSiblingElementStyle; }
static int32_t flagStyleIsAffectedByPreviousSibling() { return StyleIsAffectedByPreviousSibling; }
-#endif // ENABLE(CSS_SELECTOR_JIT)
+#endif // ENABLE(JIT)
protected:
enum NodeFlags {
Modified: trunk/Source/WebCore/dom/Node.idl (207012 => 207013)
--- trunk/Source/WebCore/dom/Node.idl 2016-10-10 19:42:51 UTC (rev 207012)
+++ trunk/Source/WebCore/dom/Node.idl 2016-10-10 19:57:55 UTC (rev 207013)
@@ -47,12 +47,12 @@
[SetterMayThrowLegacyException] attribute DOMString? nodeValue;
readonly attribute unsigned short nodeType;
- readonly attribute Node? parentNode;
+ [DOMJIT] readonly attribute Node? parentNode;
readonly attribute NodeList childNodes;
- readonly attribute Node? firstChild;
- readonly attribute Node? lastChild;
- readonly attribute Node? previousSibling;
- readonly attribute Node? nextSibling;
+ [DOMJIT] readonly attribute Node? firstChild;
+ [DOMJIT] readonly attribute Node? lastChild;
+ [DOMJIT] readonly attribute Node? previousSibling;
+ [DOMJIT] readonly attribute Node? nextSibling;
readonly attribute Document? ownerDocument;
[Custom, MayThrowLegacyException] Node insertBefore([CustomReturn] Node newChild, Node? refChild);
Added: trunk/Source/WebCore/domjit/DOMJITHelpers.h (0 => 207013)
--- trunk/Source/WebCore/domjit/DOMJITHelpers.h (rev 0)
+++ trunk/Source/WebCore/domjit/DOMJITHelpers.h 2016-10-10 19:57:55 UTC (rev 207013)
@@ -0,0 +1,134 @@
+/*
+ * 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
+
+#include "JSDOMWrapper.h"
+#include <domjit/DOMJITPatchpoint.h>
+#include <domjit/DOMJITPatchpointParams.h>
+
+#if ENABLE(JIT)
+
+namespace WebCore {
+namespace DOMJITHelpers {
+
+using JSC::CCallHelpers;
+using JSC::GPRReg;
+using JSC::JSValueRegs;
+
+inline CCallHelpers::Jump branchIfNotWorldIsNormal(CCallHelpers& jit, GPRReg globalObject)
+{
+ return jit.branchTest8(CCallHelpers::Zero, CCallHelpers::Address(globalObject, JSDOMGlobalObject::offsetOfWorldIsNormal()));
+}
+
+inline CCallHelpers::Jump branchIfNotWeakIsLive(CCallHelpers& jit, GPRReg weakImpl)
+{
+ return jit.branchTestPtr(CCallHelpers::NonZero, CCallHelpers::Address(weakImpl, JSC::WeakImpl::offsetOfWeakHandleOwner()), CCallHelpers::TrustedImm32(JSC::WeakImpl::StateMask));
+}
+
+template<typename WrappedType>
+void tryLookUpWrapperCache(CCallHelpers& jit, CCallHelpers::JumpList& failureCases, GPRReg wrapped, GPRReg resultGPR)
+{
+ jit.loadPtr(CCallHelpers::Address(wrapped, ScriptWrappable::offsetOfWrapper<WrappedType>()), resultGPR);
+ failureCases.append(jit.branchTestPtr(CCallHelpers::Zero, resultGPR));
+ failureCases.append(branchIfNotWeakIsLive(jit, resultGPR));
+ jit.loadPtr(CCallHelpers::Address(resultGPR, JSC::WeakImpl::offsetOfJSValue() + JSC::JSValue::offsetOfPayload()), resultGPR);
+}
+
+template<typename WrappedType, typename ToJSFunction>
+void toWrapper(CCallHelpers& jit, const JSC::DOMJIT::PatchpointParams& params, GPRReg wrapped, GPRReg globalObject, JSValueRegs result, ToJSFunction function)
+{
+ ASSERT(wrapped != result.payloadGPR());
+ ASSERT(globalObject != result.payloadGPR());
+ GPRReg payloadGPR = result.payloadGPR();
+ CCallHelpers::JumpList slowCases;
+ slowCases.append(branchIfNotWorldIsNormal(jit, globalObject));
+ tryLookUpWrapperCache<WrappedType>(jit, slowCases, wrapped, payloadGPR);
+ jit.boxCell(payloadGPR, result);
+ params.addSlowPathCall(slowCases, jit, function, result, globalObject, wrapped);
+}
+
+inline CCallHelpers::Jump branchIfDOMWrapper(CCallHelpers& jit, GPRReg target)
+{
+ return jit.branch8(
+ CCallHelpers::AboveOrEqual,
+ CCallHelpers::Address(target, JSC::JSCell::typeInfoTypeOffset()),
+ CCallHelpers::TrustedImm32(JSC::JSType(JSDOMWrapperType)));
+}
+
+inline CCallHelpers::Jump branchIfNotDOMWrapper(CCallHelpers& jit, GPRReg target)
+{
+ return jit.branch8(
+ CCallHelpers::Below,
+ CCallHelpers::Address(target, JSC::JSCell::typeInfoTypeOffset()),
+ CCallHelpers::TrustedImm32(JSC::JSType(JSDOMWrapperType)));
+}
+
+inline CCallHelpers::Jump branchIfNode(CCallHelpers& jit, GPRReg target)
+{
+ return jit.branch8(
+ CCallHelpers::AboveOrEqual,
+ CCallHelpers::Address(target, JSC::JSCell::typeInfoTypeOffset()),
+ CCallHelpers::TrustedImm32(JSC::JSType(JSNodeType)));
+}
+
+inline CCallHelpers::Jump branchIfNotNode(CCallHelpers& jit, GPRReg target)
+{
+ return jit.branch8(
+ CCallHelpers::Below,
+ CCallHelpers::Address(target, JSC::JSCell::typeInfoTypeOffset()),
+ CCallHelpers::TrustedImm32(JSC::JSType(JSNodeType)));
+}
+
+inline CCallHelpers::Jump branchIfElement(CCallHelpers& jit, GPRReg target)
+{
+ return jit.branch8(
+ CCallHelpers::AboveOrEqual,
+ CCallHelpers::Address(target, JSC::JSCell::typeInfoTypeOffset()),
+ CCallHelpers::TrustedImm32(JSC::JSType(JSElementType)));
+}
+
+inline CCallHelpers::Jump branchIfNotElement(CCallHelpers& jit, GPRReg target)
+{
+ return jit.branch8(
+ CCallHelpers::Below,
+ CCallHelpers::Address(target, JSC::JSCell::typeInfoTypeOffset()),
+ CCallHelpers::TrustedImm32(JSC::JSType(JSElementType)));
+}
+
+inline CCallHelpers::Jump branchIfDocumentWrapper(CCallHelpers& jit, GPRReg target)
+{
+ return jit.branchIfType(target, JSC::JSType(JSDocumentWrapperType));
+}
+
+inline CCallHelpers::Jump branchIfNotDocumentWrapper(CCallHelpers& jit, GPRReg target)
+{
+ return jit.branchIfNotType(target, JSC::JSType(JSDocumentWrapperType));
+}
+
+} }
+
+#endif
Added: trunk/Source/WebCore/domjit/JSNodeDOMJIT.cpp (0 => 207013)
--- trunk/Source/WebCore/domjit/JSNodeDOMJIT.cpp (rev 0)
+++ trunk/Source/WebCore/domjit/JSNodeDOMJIT.cpp 2016-10-10 19:57:55 UTC (rev 207013)
@@ -0,0 +1,152 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+#include "JSNode.h"
+
+#if ENABLE(JIT)
+
+#include "DOMJITHelpers.h"
+#include "JSDOMWrapper.h"
+#include "Node.h"
+#include <domjit/DOMJITPatchpoint.h>
+#include <domjit/DOMJITPatchpointParams.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+enum class IsContainerGuardRequirement { Required, NotRequired };
+
+template<typename WrappedNode>
+EncodedJSValue toWrapperSlow(JSC::ExecState* exec, JSC::JSGlobalObject* globalObject, void* result)
+{
+ ASSERT(exec);
+ ASSERT(result);
+ ASSERT(globalObject);
+ return JSValue::encode(toJS(exec, static_cast<JSDOMGlobalObject*>(globalObject), *static_cast<WrappedNode*>(result)));
+}
+
+template<typename WrappedNode>
+static Ref<DOMJIT::Patchpoint> createCallDOMForOffsetAccess(ptrdiff_t offset, IsContainerGuardRequirement isContainerGuardRequirement)
+{
+ Ref<DOMJIT::Patchpoint> patchpoint = DOMJIT::Patchpoint::create();
+ patchpoint->numGPScratchRegisters = 1;
+ patchpoint->setGenerator([=](CCallHelpers& jit, const DOMJIT::PatchpointParams& params) {
+ JSValueRegs result = params[0].jsValueRegs();
+ GPRReg globalObject = params[1].gpr();
+ GPRReg node = params[2].gpr();
+ GPRReg scratch = params.gpScratch(0);
+
+ CCallHelpers::JumpList nullCases;
+ // Load a wrapped object. "node" should be already type checked by CheckDOM.
+ jit.loadPtr(CCallHelpers::Address(node, JSNode::offsetOfWrapped()), scratch);
+
+ if (isContainerGuardRequirement == IsContainerGuardRequirement::Required)
+ nullCases.append(jit.branchTest32(CCallHelpers::Zero, CCallHelpers::Address(scratch, Node::nodeFlagsMemoryOffset()), CCallHelpers::TrustedImm32(Node::flagIsContainer())));
+
+ jit.loadPtr(CCallHelpers::Address(scratch, offset), scratch);
+ nullCases.append(jit.branchTestPtr(CCallHelpers::Zero, scratch));
+
+ DOMJITHelpers::toWrapper<WrappedNode>(jit, params, scratch, globalObject, result, toWrapperSlow<WrappedNode>);
+ CCallHelpers::Jump done = jit.jump();
+
+ nullCases.link(&jit);
+ jit.moveValue(jsNull(), result);
+ done.link(&jit);
+ return CCallHelpers::JumpList();
+ });
+ return patchpoint;
+}
+
+static Ref<DOMJIT::Patchpoint> checkNode()
+{
+ Ref<DOMJIT::Patchpoint> patchpoint = DOMJIT::Patchpoint::create();
+ patchpoint->setGenerator([=](CCallHelpers& jit, const DOMJIT::PatchpointParams& params) {
+ CCallHelpers::JumpList failureCases;
+ failureCases.append(DOMJITHelpers::branchIfNotNode(jit, params[0].gpr()));
+ return failureCases;
+ });
+ return patchpoint;
+}
+
+// Node#firstChild.
+Ref<DOMJIT::Patchpoint> NodeFirstChildDOMJIT::checkDOM()
+{
+ return checkNode();
+}
+
+Ref<DOMJIT::Patchpoint> NodeFirstChildDOMJIT::callDOM()
+{
+ return createCallDOMForOffsetAccess<Node>(CAST_OFFSET(Node*, ContainerNode*) + ContainerNode::firstChildMemoryOffset(), IsContainerGuardRequirement::Required);
+}
+
+// Node#lastChild.
+Ref<DOMJIT::Patchpoint> NodeLastChildDOMJIT::checkDOM()
+{
+ return checkNode();
+}
+
+Ref<DOMJIT::Patchpoint> NodeLastChildDOMJIT::callDOM()
+{
+ return createCallDOMForOffsetAccess<Node>(CAST_OFFSET(Node*, ContainerNode*) + ContainerNode::lastChildMemoryOffset(), IsContainerGuardRequirement::Required);
+}
+
+// Node#nextSibling.
+Ref<DOMJIT::Patchpoint> NodeNextSiblingDOMJIT::checkDOM()
+{
+ return checkNode();
+}
+
+Ref<DOMJIT::Patchpoint> NodeNextSiblingDOMJIT::callDOM()
+{
+ return createCallDOMForOffsetAccess<Node>(Node::nextSiblingMemoryOffset(), IsContainerGuardRequirement::NotRequired);
+}
+
+// Node#previousSibling.
+Ref<DOMJIT::Patchpoint> NodePreviousSiblingDOMJIT::checkDOM()
+{
+ return checkNode();
+}
+
+Ref<DOMJIT::Patchpoint> NodePreviousSiblingDOMJIT::callDOM()
+{
+ return createCallDOMForOffsetAccess<Node>(Node::previousSiblingMemoryOffset(), IsContainerGuardRequirement::NotRequired);
+}
+
+// Node#parentNode.
+Ref<DOMJIT::Patchpoint> NodeParentNodeDOMJIT::checkDOM()
+{
+ return checkNode();
+}
+
+Ref<DOMJIT::Patchpoint> NodeParentNodeDOMJIT::callDOM()
+{
+ return createCallDOMForOffsetAccess<ContainerNode>(Node::parentNodeMemoryOffset(), IsContainerGuardRequirement::NotRequired);
+}
+
+}
+
+#endif