blob: fefa18c2ba3f0e886237f9727aece4ae16acf0ec [file] [log] [blame]
/*
* Copyright (C) 2016-2019 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 "Node.h"
#include <JavaScriptCore/FrameTracers.h>
#include <JavaScriptCore/SnippetParams.h>
#if ENABLE(JIT)
namespace WebCore { namespace DOMJIT {
using JSC::CCallHelpers;
using JSC::GPRReg;
using JSC::JSValueRegs;
using JSC::MacroAssembler;
static_assert(std::is_same<GPRReg, MacroAssembler::RegisterID>::value, "GPRReg is the alias to the MacroAssembler::RegisterID");
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 WrappedNode>
JSC::EncodedJSValue JIT_OPERATION toWrapperSlow(JSC::ExecState* exec, JSC::JSGlobalObject* globalObject, void* result)
{
ASSERT(exec);
ASSERT(result);
ASSERT(globalObject);
JSC::NativeCallFrameTracer tracer(globalObject->vm(), exec);
return JSC::JSValue::encode(toJS(exec, static_cast<JSDOMGlobalObject*>(globalObject), *static_cast<WrappedNode*>(result)));
}
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, JSC::SnippetParams& params, GPRReg wrapped, GPRReg globalObject, JSValueRegs result, ToJSFunction function, JSC::JSValue globalObjectConstant)
{
ASSERT(wrapped != result.payloadGPR());
ASSERT(globalObject != result.payloadGPR());
GPRReg payloadGPR = result.payloadGPR();
CCallHelpers::JumpList slowCases;
if (globalObjectConstant) {
if (!JSC::jsCast<JSDOMGlobalObject*>(globalObjectConstant)->worldIsNormal()) {
slowCases.append(jit.jump());
params.addSlowPathCall(slowCases, jit, function, result, globalObject, wrapped);
return;
}
} else
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 branchIfEvent(CCallHelpers& jit, GPRReg target)
{
return jit.branchIfType(target, JSC::JSType(JSEventType));
}
inline CCallHelpers::Jump branchIfNotEvent(CCallHelpers& jit, GPRReg target)
{
return jit.branchIfNotType(target, JSC::JSType(JSEventType));
}
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 branchIfDocumentFragment(CCallHelpers& jit, GPRReg target)
{
return jit.branchIfType(target, JSC::JSType(JSDocumentFragmentNodeType));
}
inline CCallHelpers::Jump branchIfNotDocumentFragment(CCallHelpers& jit, GPRReg target)
{
return jit.branchIfNotType(target, JSC::JSType(JSDocumentFragmentNodeType));
}
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));
}
void loadDocument(MacroAssembler&, GPRReg node, GPRReg output);
void loadDocumentElement(MacroAssembler&, GPRReg document, GPRReg output);
inline CCallHelpers::Jump branchTestIsElementFlagOnNode(MacroAssembler& jit, CCallHelpers::ResultCondition condition, GPRReg nodeAddress)
{
return jit.branchTest32(condition, CCallHelpers::Address(nodeAddress, Node::nodeFlagsMemoryOffset()), CCallHelpers::TrustedImm32(Node::flagIsElement()));
}
inline CCallHelpers::Jump branchTestIsShadowRootFlagOnNode(MacroAssembler& jit, CCallHelpers::ResultCondition condition, GPRReg nodeAddress)
{
return jit.branchTest32(condition, CCallHelpers::Address(nodeAddress, Node::nodeFlagsMemoryOffset()), CCallHelpers::TrustedImm32(Node::flagIsShadowRoot()));
}
inline CCallHelpers::Jump branchTestIsElementOrShadowRootFlagOnNode(MacroAssembler& jit, CCallHelpers::ResultCondition condition, GPRReg nodeAddress)
{
return jit.branchTest32(condition, CCallHelpers::Address(nodeAddress, Node::nodeFlagsMemoryOffset()),
CCallHelpers::TrustedImm32(Node::flagIsShadowRoot() | Node::flagIsElement()));
}
inline CCallHelpers::Jump branchTestIsHTMLFlagOnNode(MacroAssembler& jit, CCallHelpers::ResultCondition condition, GPRReg nodeAddress)
{
return jit.branchTest32(condition, CCallHelpers::Address(nodeAddress, Node::nodeFlagsMemoryOffset()), CCallHelpers::TrustedImm32(Node::flagIsHTML()));
}
} }
#endif