summaryrefslogtreecommitdiff
path: root/Source/WebCore/domjit/JSNodeDOMJIT.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/domjit/JSNodeDOMJIT.cpp')
-rw-r--r--Source/WebCore/domjit/JSNodeDOMJIT.cpp199
1 files changed, 199 insertions, 0 deletions
diff --git a/Source/WebCore/domjit/JSNodeDOMJIT.cpp b/Source/WebCore/domjit/JSNodeDOMJIT.cpp
new file mode 100644
index 000000000..29f8b384e
--- /dev/null
+++ b/Source/WebCore/domjit/JSNodeDOMJIT.cpp
@@ -0,0 +1,199 @@
+/*
+ * 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 "DOMJITAbstractHeapRepository.h"
+#include "DOMJITCheckDOM.h"
+#include "DOMJITHelpers.h"
+#include "JSDOMWrapper.h"
+#include "Node.h"
+#include <domjit/DOMJITPatchpoint.h>
+#include <domjit/DOMJITPatchpointParams.h>
+#include <interpreter/FrameTracers.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+enum class IsContainerGuardRequirement { Required, NotRequired };
+
+template<typename WrappedNode>
+static Ref<JSC::DOMJIT::CallDOMGetterPatchpoint> createCallDOMGetterForOffsetAccess(ptrdiff_t offset, IsContainerGuardRequirement isContainerGuardRequirement)
+{
+ Ref<JSC::DOMJIT::CallDOMGetterPatchpoint> patchpoint = JSC::DOMJIT::CallDOMGetterPatchpoint::create();
+ patchpoint->numGPScratchRegisters = 1;
+ patchpoint->setGenerator([=](CCallHelpers& jit, JSC::DOMJIT::PatchpointParams& params) {
+ JSValueRegs result = params[0].jsValueRegs();
+ GPRReg node = params[1].gpr();
+ GPRReg globalObject = params[2].gpr();
+ GPRReg scratch = params.gpScratch(0);
+ JSValue globalObjectValue = params[2].value();
+
+ 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));
+
+ DOMJIT::toWrapper<WrappedNode>(jit, params, scratch, globalObject, result, DOMJIT::toWrapperSlow<WrappedNode>, globalObjectValue);
+ CCallHelpers::Jump done = jit.jump();
+
+ nullCases.link(&jit);
+ jit.moveValue(jsNull(), result);
+ done.link(&jit);
+ return CCallHelpers::JumpList();
+ });
+ return patchpoint;
+}
+
+Ref<JSC::DOMJIT::Patchpoint> NodeFirstChildDOMJIT::checkDOM()
+{
+ return DOMJIT::checkDOM<Node>();
+}
+
+Ref<JSC::DOMJIT::CallDOMGetterPatchpoint> NodeFirstChildDOMJIT::callDOMGetter()
+{
+ auto patchpoint = createCallDOMGetterForOffsetAccess<Node>(CAST_OFFSET(Node*, ContainerNode*) + ContainerNode::firstChildMemoryOffset(), IsContainerGuardRequirement::Required);
+ patchpoint->effect = JSC::DOMJIT::Effect::forDef(DOMJIT::AbstractHeapRepository::Node_firstChild);
+ return patchpoint;
+}
+
+Ref<JSC::DOMJIT::Patchpoint> NodeLastChildDOMJIT::checkDOM()
+{
+ return DOMJIT::checkDOM<Node>();
+}
+
+Ref<JSC::DOMJIT::CallDOMGetterPatchpoint> NodeLastChildDOMJIT::callDOMGetter()
+{
+ auto patchpoint = createCallDOMGetterForOffsetAccess<Node>(CAST_OFFSET(Node*, ContainerNode*) + ContainerNode::lastChildMemoryOffset(), IsContainerGuardRequirement::Required);
+ patchpoint->effect = JSC::DOMJIT::Effect::forDef(DOMJIT::AbstractHeapRepository::Node_lastChild);
+ return patchpoint;
+}
+
+Ref<JSC::DOMJIT::Patchpoint> NodeNextSiblingDOMJIT::checkDOM()
+{
+ return DOMJIT::checkDOM<Node>();
+}
+
+Ref<JSC::DOMJIT::CallDOMGetterPatchpoint> NodeNextSiblingDOMJIT::callDOMGetter()
+{
+ auto patchpoint = createCallDOMGetterForOffsetAccess<Node>(Node::nextSiblingMemoryOffset(), IsContainerGuardRequirement::NotRequired);
+ patchpoint->effect = JSC::DOMJIT::Effect::forDef(DOMJIT::AbstractHeapRepository::Node_nextSibling);
+ return patchpoint;
+}
+
+Ref<JSC::DOMJIT::Patchpoint> NodePreviousSiblingDOMJIT::checkDOM()
+{
+ return DOMJIT::checkDOM<Node>();
+}
+
+Ref<JSC::DOMJIT::CallDOMGetterPatchpoint> NodePreviousSiblingDOMJIT::callDOMGetter()
+{
+ auto patchpoint = createCallDOMGetterForOffsetAccess<Node>(Node::previousSiblingMemoryOffset(), IsContainerGuardRequirement::NotRequired);
+ patchpoint->effect = JSC::DOMJIT::Effect::forDef(DOMJIT::AbstractHeapRepository::Node_previousSibling);
+ return patchpoint;
+}
+
+Ref<JSC::DOMJIT::Patchpoint> NodeParentNodeDOMJIT::checkDOM()
+{
+ return DOMJIT::checkDOM<Node>();
+}
+
+Ref<JSC::DOMJIT::CallDOMGetterPatchpoint> NodeParentNodeDOMJIT::callDOMGetter()
+{
+ auto patchpoint = createCallDOMGetterForOffsetAccess<ContainerNode>(Node::parentNodeMemoryOffset(), IsContainerGuardRequirement::NotRequired);
+ patchpoint->effect = JSC::DOMJIT::Effect::forDef(DOMJIT::AbstractHeapRepository::Node_parentNode);
+ return patchpoint;
+}
+
+Ref<JSC::DOMJIT::Patchpoint> NodeNodeTypeDOMJIT::checkDOM()
+{
+ return DOMJIT::checkDOM<Node>();
+}
+
+Ref<JSC::DOMJIT::CallDOMGetterPatchpoint> NodeNodeTypeDOMJIT::callDOMGetter()
+{
+ Ref<JSC::DOMJIT::CallDOMGetterPatchpoint> patchpoint = JSC::DOMJIT::CallDOMGetterPatchpoint::create();
+ patchpoint->effect = JSC::DOMJIT::Effect::forPure();
+ patchpoint->requireGlobalObject = false;
+ patchpoint->setGenerator([=](CCallHelpers& jit, JSC::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;
+}
+
+Ref<JSC::DOMJIT::Patchpoint> NodeOwnerDocumentDOMJIT::checkDOM()
+{
+ return DOMJIT::checkDOM<Node>();
+}
+
+Ref<JSC::DOMJIT::CallDOMGetterPatchpoint> NodeOwnerDocumentDOMJIT::callDOMGetter()
+{
+ Ref<JSC::DOMJIT::CallDOMGetterPatchpoint> patchpoint = JSC::DOMJIT::CallDOMGetterPatchpoint::create();
+ patchpoint->numGPScratchRegisters = 2;
+ patchpoint->setGenerator([=](CCallHelpers& jit, JSC::DOMJIT::PatchpointParams& params) {
+ JSValueRegs result = params[0].jsValueRegs();
+ GPRReg node = params[1].gpr();
+ GPRReg globalObject = params[2].gpr();
+ JSValue globalObjectValue = params[2].value();
+ GPRReg wrapped = params.gpScratch(0);
+ GPRReg document = params.gpScratch(1);
+
+ jit.loadPtr(CCallHelpers::Address(node, JSNode::offsetOfWrapped()), wrapped);
+ DOMJIT::loadDocument(jit, wrapped, document);
+ RELEASE_ASSERT(!CAST_OFFSET(EventTarget*, Node*));
+ RELEASE_ASSERT(!CAST_OFFSET(Node*, Document*));
+
+ CCallHelpers::JumpList nullCases;
+ // If the |this| is the document itself, ownerDocument will return null.
+ nullCases.append(jit.branchPtr(CCallHelpers::Equal, wrapped, document));
+ DOMJIT::toWrapper<Document>(jit, params, document, globalObject, result, DOMJIT::toWrapperSlow<Document>, globalObjectValue);
+ auto done = jit.jump();
+
+ nullCases.link(&jit);
+ jit.moveValue(jsNull(), result);
+ done.link(&jit);
+ return CCallHelpers::JumpList();
+ });
+ patchpoint->effect = JSC::DOMJIT::Effect::forDef(DOMJIT::AbstractHeapRepository::Node_ownerDocument);
+ return patchpoint;
+}
+
+}
+
+#endif