V4: Split PlatformAssemblerCommon (and base classes) in its own file
This makes it easier to re-use them later on, without inheriting all extra stuff that the baseline JIT needs. Change-Id: I9368b16017b8b9d99f8c005a5b47ec9f9ed09fb0 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
This commit is contained in:
parent
83ded6108a
commit
bf13637952
|
@ -4,9 +4,11 @@ INCLUDEPATH += $$OUT_PWD
|
|||
SOURCES += \
|
||||
$$PWD/qv4jithelpers.cpp \
|
||||
$$PWD/qv4baselinejit.cpp \
|
||||
$$PWD/qv4assembler.cpp
|
||||
$$PWD/qv4baselineassembler.cpp \
|
||||
$$PWD/qv4assemblercommon.cpp
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/qv4jithelpers_p.h \
|
||||
$$PWD/qv4baselinejit_p.h \
|
||||
$$PWD/qv4assembler_p.h
|
||||
$$PWD/qv4baselineassembler_p.h \
|
||||
$$PWD/qv4assemblercommon_p.h
|
||||
|
|
|
@ -0,0 +1,343 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2017 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtQml module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <QBuffer>
|
||||
#include <QFile>
|
||||
|
||||
#include "qv4engine_p.h"
|
||||
#include "qv4assemblercommon_p.h"
|
||||
#include <private/qv4function_p.h>
|
||||
#include <private/qv4runtime_p.h>
|
||||
|
||||
#include <assembler/MacroAssemblerCodeRef.h>
|
||||
#include <assembler/LinkBuffer.h>
|
||||
#include <WTFStubs.h>
|
||||
|
||||
#undef ENABLE_ALL_ASSEMBLERS_FOR_REFACTORING_PURPOSES
|
||||
|
||||
#ifdef V4_ENABLE_JIT
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace QV4 {
|
||||
namespace JIT {
|
||||
|
||||
namespace {
|
||||
class QIODevicePrintStream: public FilePrintStream
|
||||
{
|
||||
Q_DISABLE_COPY(QIODevicePrintStream)
|
||||
|
||||
public:
|
||||
explicit QIODevicePrintStream(QIODevice *dest)
|
||||
: FilePrintStream(nullptr)
|
||||
, dest(dest)
|
||||
, buf(4096, '0')
|
||||
{
|
||||
Q_ASSERT(dest);
|
||||
}
|
||||
|
||||
~QIODevicePrintStream()
|
||||
{}
|
||||
|
||||
void vprintf(const char* format, va_list argList) WTF_ATTRIBUTE_PRINTF(2, 0)
|
||||
{
|
||||
const int written = qvsnprintf(buf.data(), buf.size(), format, argList);
|
||||
if (written > 0)
|
||||
dest->write(buf.constData(), written);
|
||||
memset(buf.data(), 0, qMin(written, buf.size()));
|
||||
}
|
||||
|
||||
void flush()
|
||||
{}
|
||||
|
||||
private:
|
||||
QIODevice *dest;
|
||||
QByteArray buf;
|
||||
};
|
||||
} // anonymous namespace
|
||||
|
||||
static void printDisassembledOutputWithCalls(QByteArray processedOutput,
|
||||
const QHash<const void*, const char*>& functions)
|
||||
{
|
||||
for (QHash<const void*, const char*>::ConstIterator it = functions.begin(), end = functions.end();
|
||||
it != end; ++it) {
|
||||
const QByteArray ptrString = "0x" + QByteArray::number(quintptr(it.key()), 16);
|
||||
int idx = 0;
|
||||
while (idx >= 0) {
|
||||
idx = processedOutput.indexOf(ptrString, idx);
|
||||
if (idx < 0)
|
||||
break;
|
||||
idx = processedOutput.indexOf('\n', idx);
|
||||
if (idx < 0)
|
||||
break;
|
||||
processedOutput = processedOutput.insert(idx, QByteArrayLiteral(" ; ") + it.value());
|
||||
}
|
||||
}
|
||||
|
||||
qDebug("%s", processedOutput.constData());
|
||||
}
|
||||
|
||||
static QByteArray functionName(Function *function)
|
||||
{
|
||||
QByteArray name = function->name()->toQString().toUtf8();
|
||||
if (name.isEmpty()) {
|
||||
name = QByteArray::number(reinterpret_cast<quintptr>(function), 16);
|
||||
name.prepend("QV4::Function(0x");
|
||||
name.append(')');
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
JIT::PlatformAssemblerCommon::~PlatformAssemblerCommon()
|
||||
{}
|
||||
|
||||
void PlatformAssemblerCommon::link(Function *function)
|
||||
{
|
||||
for (const auto &jumpTarget : jumpsToLink)
|
||||
jumpTarget.jump.linkTo(labelForOffset[jumpTarget.offset], this);
|
||||
|
||||
JSC::JSGlobalData dummy(function->internalClass->engine->executableAllocator);
|
||||
JSC::LinkBuffer<MacroAssembler> linkBuffer(dummy, this, nullptr);
|
||||
|
||||
for (const auto &ehTarget : ehTargets) {
|
||||
auto targetLabel = labelForOffset.value(ehTarget.offset);
|
||||
linkBuffer.patch(ehTarget.label, linkBuffer.locationOf(targetLabel));
|
||||
}
|
||||
|
||||
JSC::MacroAssemblerCodeRef codeRef;
|
||||
|
||||
static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_ASM");
|
||||
if (showCode) {
|
||||
QBuffer buf;
|
||||
buf.open(QIODevice::WriteOnly);
|
||||
WTF::setDataFile(new QIODevicePrintStream(&buf));
|
||||
|
||||
QByteArray name = functionName(function);
|
||||
codeRef = linkBuffer.finalizeCodeWithDisassembly("%s", name.constData());
|
||||
|
||||
WTF::setDataFile(stderr);
|
||||
printDisassembledOutputWithCalls(buf.data(), functions);
|
||||
} else {
|
||||
codeRef = linkBuffer.finalizeCodeWithoutDisassembly();
|
||||
}
|
||||
|
||||
function->codeRef = new JSC::MacroAssemblerCodeRef(codeRef);
|
||||
function->jittedCode = reinterpret_cast<Function::JittedCode>(function->codeRef->code().executableAddress());
|
||||
|
||||
// This implements writing of JIT'd addresses so that perf can find the
|
||||
// symbol names.
|
||||
//
|
||||
// Perf expects the mapping to be in a certain place and have certain
|
||||
// content, for more information, see:
|
||||
// https://github.com/torvalds/linux/blob/master/tools/perf/Documentation/jit-interface.txt
|
||||
static bool doProfile = !qEnvironmentVariableIsEmpty("QV4_PROFILE_WRITE_PERF_MAP");
|
||||
if (Q_UNLIKELY(doProfile)) {
|
||||
static QFile perfMapFile(QString::fromLatin1("/tmp/perf-%1.map")
|
||||
.arg(QCoreApplication::applicationPid()));
|
||||
static const bool isOpen = perfMapFile.open(QIODevice::WriteOnly);
|
||||
if (!isOpen) {
|
||||
qWarning("QV4::JIT::Assembler: Cannot write perf map file.");
|
||||
doProfile = false;
|
||||
} else {
|
||||
perfMapFile.write(QByteArray::number(reinterpret_cast<quintptr>(
|
||||
codeRef.code().executableAddress()), 16));
|
||||
perfMapFile.putChar(' ');
|
||||
perfMapFile.write(QByteArray::number(static_cast<qsizetype>(codeRef.size()), 16));
|
||||
perfMapFile.putChar(' ');
|
||||
perfMapFile.write(functionName(function));
|
||||
perfMapFile.putChar('\n');
|
||||
perfMapFile.flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PlatformAssemblerCommon::prepareCallWithArgCount(int argc)
|
||||
{
|
||||
#ifndef QT_NO_DEBUG
|
||||
Q_ASSERT(remainingArgcForCall == NoCall);
|
||||
remainingArgcForCall = argc;
|
||||
#endif
|
||||
|
||||
if (argc > ArgInRegCount) {
|
||||
argcOnStackForCall = int(WTF::roundUpToMultipleOf(16, size_t(argc - ArgInRegCount) * PointerSize));
|
||||
subPtr(TrustedImm32(argcOnStackForCall), StackPointerRegister);
|
||||
}
|
||||
}
|
||||
|
||||
void PlatformAssemblerCommon::storeInstructionPointer(int instructionOffset)
|
||||
{
|
||||
Address addr(CppStackFrameRegister, offsetof(QV4::CppStackFrame, instructionPointer));
|
||||
store32(TrustedImm32(instructionOffset), addr);
|
||||
}
|
||||
|
||||
PlatformAssemblerCommon::Address PlatformAssemblerCommon::argStackAddress(int arg)
|
||||
{
|
||||
int offset = arg - ArgInRegCount;
|
||||
Q_ASSERT(offset >= 0);
|
||||
return Address(StackPointerRegister, offset * PointerSize);
|
||||
}
|
||||
|
||||
void PlatformAssemblerCommon::passAccumulatorAsArg(int arg)
|
||||
{
|
||||
#ifndef QT_NO_DEBUG
|
||||
Q_ASSERT(arg < remainingArgcForCall);
|
||||
--remainingArgcForCall;
|
||||
#endif
|
||||
|
||||
passAccumulatorAsArg_internal(arg, false);
|
||||
}
|
||||
|
||||
void JIT::PlatformAssemblerCommon::pushAccumulatorAsArg(int arg)
|
||||
{
|
||||
passAccumulatorAsArg_internal(arg, true);
|
||||
}
|
||||
|
||||
void PlatformAssemblerCommon::passAccumulatorAsArg_internal(int arg, bool doPush)
|
||||
{
|
||||
if (arg < ArgInRegCount) {
|
||||
addPtr(TrustedImm32(offsetof(CallData, accumulator)), JSStackFrameRegister, registerForArg(arg));
|
||||
} else {
|
||||
addPtr(TrustedImm32(offsetof(CallData, accumulator)), JSStackFrameRegister, ScratchRegister);
|
||||
if (doPush)
|
||||
push(ScratchRegister);
|
||||
else
|
||||
storePtr(ScratchRegister, argStackAddress(arg));
|
||||
}
|
||||
}
|
||||
|
||||
void PlatformAssemblerCommon::passFunctionAsArg(int arg)
|
||||
{
|
||||
#ifndef QT_NO_DEBUG
|
||||
Q_ASSERT(arg < remainingArgcForCall);
|
||||
--remainingArgcForCall;
|
||||
#endif
|
||||
|
||||
if (arg < ArgInRegCount) {
|
||||
loadFunctionPtr(registerForArg(arg));
|
||||
} else {
|
||||
loadFunctionPtr(ScratchRegister);
|
||||
storePtr(ScratchRegister, argStackAddress(arg));
|
||||
}
|
||||
}
|
||||
|
||||
void PlatformAssemblerCommon::passEngineAsArg(int arg)
|
||||
{
|
||||
#ifndef QT_NO_DEBUG
|
||||
Q_ASSERT(arg < remainingArgcForCall);
|
||||
--remainingArgcForCall;
|
||||
#endif
|
||||
|
||||
if (arg < ArgInRegCount) {
|
||||
move(EngineRegister, registerForArg(arg));
|
||||
} else {
|
||||
storePtr(EngineRegister, argStackAddress(arg));
|
||||
}
|
||||
}
|
||||
|
||||
void PlatformAssemblerCommon::passJSSlotAsArg(int reg, int arg)
|
||||
{
|
||||
Address addr(JSStackFrameRegister, reg * int(sizeof(QV4::Value)));
|
||||
passAddressAsArg(addr, arg);
|
||||
}
|
||||
|
||||
void JIT::PlatformAssemblerCommon::passAddressAsArg(Address addr, int arg)
|
||||
{
|
||||
#ifndef QT_NO_DEBUG
|
||||
Q_ASSERT(arg < remainingArgcForCall);
|
||||
--remainingArgcForCall;
|
||||
#endif
|
||||
|
||||
if (arg < ArgInRegCount) {
|
||||
addPtr(TrustedImm32(addr.offset), addr.base, registerForArg(arg));
|
||||
} else {
|
||||
addPtr(TrustedImm32(addr.offset), addr.base, ScratchRegister);
|
||||
storePtr(ScratchRegister, argStackAddress(arg));
|
||||
}
|
||||
}
|
||||
|
||||
void PlatformAssemblerCommon::passCppFrameAsArg(int arg)
|
||||
{
|
||||
#ifndef QT_NO_DEBUG
|
||||
Q_ASSERT(arg < remainingArgcForCall);
|
||||
--remainingArgcForCall;
|
||||
#endif
|
||||
|
||||
if (arg < ArgInRegCount)
|
||||
move(CppStackFrameRegister, registerForArg(arg));
|
||||
else
|
||||
store32(CppStackFrameRegister, argStackAddress(arg));
|
||||
}
|
||||
|
||||
void PlatformAssemblerCommon::passInt32AsArg(int value, int arg)
|
||||
{
|
||||
#ifndef QT_NO_DEBUG
|
||||
Q_ASSERT(arg < remainingArgcForCall);
|
||||
--remainingArgcForCall;
|
||||
#endif
|
||||
|
||||
if (arg < ArgInRegCount)
|
||||
move(TrustedImm32(value), registerForArg(arg));
|
||||
else
|
||||
store32(TrustedImm32(value), argStackAddress(arg));
|
||||
}
|
||||
|
||||
void PlatformAssemblerCommon::callRuntime(const char *functionName, const void *funcPtr)
|
||||
{
|
||||
#ifndef QT_NO_DEBUG
|
||||
Q_ASSERT(remainingArgcForCall == 0);
|
||||
remainingArgcForCall = NoCall;
|
||||
#endif
|
||||
callRuntimeUnchecked(functionName, funcPtr);
|
||||
if (argcOnStackForCall > 0) {
|
||||
addPtr(TrustedImm32(argcOnStackForCall), StackPointerRegister);
|
||||
argcOnStackForCall = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void JIT::PlatformAssemblerCommon::callRuntimeUnchecked(const char *functionName, const void *funcPtr)
|
||||
{
|
||||
functions.insert(funcPtr, functionName);
|
||||
callAbsolute(funcPtr);
|
||||
}
|
||||
|
||||
} // JIT namespace
|
||||
} // QV4 namepsace
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // V4_ENABLE_JIT
|
|
@ -0,0 +1,697 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtQml module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QV4PLATFORMASSEMBLER_P_H
|
||||
#define QV4PLATFORMASSEMBLER_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include <private/qv4engine_p.h>
|
||||
#include <private/qv4global_p.h>
|
||||
#include <private/qv4function_p.h>
|
||||
#include <QHash>
|
||||
#include <wtf/Vector.h>
|
||||
#include <assembler/MacroAssembler.h>
|
||||
|
||||
#ifdef V4_ENABLE_JIT
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
namespace QV4 {
|
||||
namespace JIT {
|
||||
|
||||
#if defined(Q_PROCESSOR_X86_64) || defined(ENABLE_ALL_ASSEMBLERS_FOR_REFACTORING_PURPOSES)
|
||||
#if defined(Q_OS_LINUX) || defined(Q_OS_QNX) || defined(Q_OS_FREEBSD) || defined(Q_OS_DARWIN)
|
||||
|
||||
class PlatformAssembler_X86_64_SysV : public JSC::MacroAssembler<JSC::MacroAssemblerX86_64>
|
||||
{
|
||||
public:
|
||||
static constexpr int NativeStackAlignment = 16;
|
||||
|
||||
static const RegisterID NoRegister = RegisterID(-1);
|
||||
|
||||
static const RegisterID ReturnValueRegister = RegisterID::eax;
|
||||
static const RegisterID ReturnValueRegisterValue = ReturnValueRegister;
|
||||
static const RegisterID AccumulatorRegister = RegisterID::eax;
|
||||
static const RegisterID AccumulatorRegisterValue = AccumulatorRegister;
|
||||
static const RegisterID ScratchRegister = RegisterID::r10;
|
||||
static const RegisterID ScratchRegister2 = RegisterID::r9; // Note: overlaps with Arg5Reg, so do not use while setting up a call!
|
||||
static const RegisterID JSStackFrameRegister = RegisterID::r12;
|
||||
static const RegisterID CppStackFrameRegister = RegisterID::r13;
|
||||
static const RegisterID EngineRegister = RegisterID::r14;
|
||||
static const RegisterID StackPointerRegister = RegisterID::esp;
|
||||
static const RegisterID FramePointerRegister = RegisterID::ebp;
|
||||
static const FPRegisterID FPScratchRegister = FPRegisterID::xmm1;
|
||||
static const FPRegisterID FPScratchRegister2 = FPRegisterID::xmm2;
|
||||
|
||||
static const RegisterID Arg0Reg = RegisterID::edi;
|
||||
static const RegisterID Arg1Reg = RegisterID::esi;
|
||||
static const RegisterID Arg2Reg = RegisterID::edx;
|
||||
static const RegisterID Arg3Reg = RegisterID::ecx;
|
||||
static const RegisterID Arg4Reg = RegisterID::r8;
|
||||
static const RegisterID Arg5Reg = RegisterID::r9;
|
||||
static const RegisterID Arg6Reg = NoRegister;
|
||||
static const RegisterID Arg7Reg = NoRegister;
|
||||
static const int ArgInRegCount = 6;
|
||||
|
||||
void popValue()
|
||||
{
|
||||
addPtr(TrustedImmPtr(sizeof(ReturnedValue)), StackPointerRegister);
|
||||
}
|
||||
|
||||
void generatePlatformFunctionEntry()
|
||||
{
|
||||
push(FramePointerRegister);
|
||||
move(StackPointerRegister, FramePointerRegister);
|
||||
move(TrustedImmPtr(nullptr), AccumulatorRegister); push(AccumulatorRegister); // exceptionHandler
|
||||
push(JSStackFrameRegister);
|
||||
push(CppStackFrameRegister);
|
||||
push(EngineRegister);
|
||||
move(Arg0Reg, CppStackFrameRegister);
|
||||
move(Arg1Reg, EngineRegister);
|
||||
}
|
||||
|
||||
void generatePlatformFunctionExit()
|
||||
{
|
||||
pop(EngineRegister);
|
||||
pop(CppStackFrameRegister);
|
||||
pop(JSStackFrameRegister);
|
||||
pop(); // exceptionHandler
|
||||
pop(FramePointerRegister);
|
||||
ret();
|
||||
}
|
||||
|
||||
void callAbsolute(const void *funcPtr)
|
||||
{
|
||||
move(TrustedImmPtr(funcPtr), ScratchRegister);
|
||||
call(ScratchRegister);
|
||||
}
|
||||
|
||||
void pushAligned(RegisterID reg)
|
||||
{
|
||||
subPtr(TrustedImm32(PointerSize), StackPointerRegister);
|
||||
push(reg);
|
||||
}
|
||||
|
||||
void popAligned(RegisterID reg)
|
||||
{
|
||||
pop(reg);
|
||||
addPtr(TrustedImm32(PointerSize), StackPointerRegister);
|
||||
}
|
||||
};
|
||||
|
||||
typedef PlatformAssembler_X86_64_SysV PlatformAssemblerBase;
|
||||
|
||||
#endif
|
||||
#if defined(Q_OS_WIN)
|
||||
|
||||
class PlatformAssembler_Win64 : public JSC::MacroAssembler<JSC::MacroAssemblerX86_64>
|
||||
{
|
||||
public:
|
||||
static const RegisterID NoRegister = RegisterID(-1);
|
||||
|
||||
static const RegisterID ReturnValueRegister = RegisterID::eax;
|
||||
static const RegisterID ReturnValueRegisterValue = ReturnValueRegister;
|
||||
static const RegisterID AccumulatorRegister = RegisterID::eax;
|
||||
static const RegisterID AccumulatorRegisterValue = AccumulatorRegister;
|
||||
static const RegisterID ScratchRegister = RegisterID::r10;
|
||||
static const RegisterID ScratchRegister2 = RegisterID::r9; // Note: overlaps with Arg3Reg, so do not use while setting up a call!
|
||||
static const RegisterID JSStackFrameRegister = RegisterID::r12;
|
||||
static const RegisterID CppStackFrameRegister = RegisterID::r13;
|
||||
static const RegisterID EngineRegister = RegisterID::r14;
|
||||
static const RegisterID StackPointerRegister = RegisterID::esp;
|
||||
static const RegisterID FramePointerRegister = RegisterID::ebp;
|
||||
static const FPRegisterID FPScratchRegister = FPRegisterID::xmm1;
|
||||
|
||||
static const RegisterID Arg0Reg = RegisterID::ecx;
|
||||
static const RegisterID Arg1Reg = RegisterID::edx;
|
||||
static const RegisterID Arg2Reg = RegisterID::r8;
|
||||
static const RegisterID Arg3Reg = RegisterID::r9;
|
||||
static const RegisterID Arg4Reg = NoRegister;
|
||||
static const RegisterID Arg5Reg = NoRegister;
|
||||
static const RegisterID Arg6Reg = NoRegister;
|
||||
static const RegisterID Arg7Reg = NoRegister;
|
||||
static const int ArgInRegCount = 4;
|
||||
|
||||
void popValue()
|
||||
{
|
||||
addPtr(TrustedImmPtr(sizeof(ReturnedValue)), StackPointerRegister);
|
||||
}
|
||||
|
||||
void generatePlatformFunctionEntry()
|
||||
{
|
||||
push(FramePointerRegister);
|
||||
move(StackPointerRegister, FramePointerRegister);
|
||||
move(TrustedImmPtr(nullptr), AccumulatorRegister); push(AccumulatorRegister); // exceptionHandler
|
||||
push(JSStackFrameRegister);
|
||||
push(CppStackFrameRegister);
|
||||
push(EngineRegister);
|
||||
move(Arg0Reg, CppStackFrameRegister);
|
||||
move(Arg1Reg, EngineRegister);
|
||||
}
|
||||
|
||||
void generatePlatformFunctionExit()
|
||||
{
|
||||
pop(EngineRegister);
|
||||
pop(CppStackFrameRegister);
|
||||
pop(JSStackFrameRegister);
|
||||
pop(); // exceptionHandler
|
||||
pop(FramePointerRegister);
|
||||
ret();
|
||||
}
|
||||
|
||||
void callAbsolute(const void *funcPtr)
|
||||
{
|
||||
move(TrustedImmPtr(funcPtr), ScratchRegister);
|
||||
subPtr(TrustedImm32(4 * PointerSize), StackPointerRegister);
|
||||
call(ScratchRegister);
|
||||
addPtr(TrustedImm32(4 * PointerSize), StackPointerRegister);
|
||||
}
|
||||
|
||||
void pushAligned(RegisterID reg)
|
||||
{
|
||||
subPtr(TrustedImm32(PointerSize), StackPointerRegister);
|
||||
push(reg);
|
||||
}
|
||||
|
||||
void popAligned(RegisterID reg)
|
||||
{
|
||||
pop(reg);
|
||||
addPtr(TrustedImm32(PointerSize), StackPointerRegister);
|
||||
}
|
||||
};
|
||||
|
||||
typedef PlatformAssembler_Win64 PlatformAssemblerBase;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (defined(Q_PROCESSOR_X86) && !defined(Q_PROCESSOR_X86_64)) || defined(ENABLE_ALL_ASSEMBLERS_FOR_REFACTORING_PURPOSES)
|
||||
|
||||
class PlatformAssembler_X86_All : public JSC::MacroAssembler<JSC::MacroAssemblerX86>
|
||||
{
|
||||
public:
|
||||
static const RegisterID NoRegister = RegisterID(-1);
|
||||
|
||||
static const RegisterID ReturnValueRegisterValue = RegisterID::eax;
|
||||
static const RegisterID ReturnValueRegisterTag = RegisterID::edx;
|
||||
static const RegisterID ScratchRegister = RegisterID::ecx;
|
||||
static const RegisterID AccumulatorRegisterValue = ReturnValueRegisterValue;
|
||||
static const RegisterID AccumulatorRegisterTag = ReturnValueRegisterTag;
|
||||
static const RegisterID JSStackFrameRegister = RegisterID::ebx;
|
||||
static const RegisterID CppStackFrameRegister = RegisterID::esi;
|
||||
static const RegisterID EngineRegister = RegisterID::edi;
|
||||
static const RegisterID StackPointerRegister = RegisterID::esp;
|
||||
static const RegisterID FramePointerRegister = RegisterID::ebp;
|
||||
static const FPRegisterID FPScratchRegister = FPRegisterID::xmm1;
|
||||
|
||||
static const RegisterID Arg0Reg = NoRegister;
|
||||
static const RegisterID Arg1Reg = NoRegister;
|
||||
static const RegisterID Arg2Reg = NoRegister;
|
||||
static const RegisterID Arg3Reg = NoRegister;
|
||||
static const RegisterID Arg4Reg = NoRegister;
|
||||
static const RegisterID Arg5Reg = NoRegister;
|
||||
static const RegisterID Arg6Reg = NoRegister;
|
||||
static const RegisterID Arg7Reg = NoRegister;
|
||||
static const int ArgInRegCount = 0;
|
||||
|
||||
void popValue()
|
||||
{
|
||||
addPtr(TrustedImmPtr(sizeof(ReturnedValue)), StackPointerRegister);
|
||||
}
|
||||
|
||||
void generatePlatformFunctionEntry()
|
||||
{
|
||||
push(RegisterID::ebp);
|
||||
move(RegisterID::esp, RegisterID::ebp);
|
||||
move(TrustedImmPtr(nullptr), AccumulatorRegisterValue); push(AccumulatorRegisterValue); // exceptionHandler
|
||||
push(JSStackFrameRegister);
|
||||
push(CppStackFrameRegister);
|
||||
push(EngineRegister);
|
||||
// Ensure the stack is 16-byte aligned in order for compiler generated aligned SSE2
|
||||
// instructions to be able to target the stack.
|
||||
subPtr(TrustedImm32(8), StackPointerRegister);
|
||||
loadPtr(Address(FramePointerRegister, 2 * PointerSize), CppStackFrameRegister);
|
||||
loadPtr(Address(FramePointerRegister, 3 * PointerSize), EngineRegister);
|
||||
}
|
||||
|
||||
void generatePlatformFunctionExit()
|
||||
{
|
||||
addPtr(TrustedImm32(8), StackPointerRegister);
|
||||
pop(EngineRegister);
|
||||
pop(CppStackFrameRegister);
|
||||
pop(JSStackFrameRegister);
|
||||
pop(); // exceptionHandler
|
||||
pop(RegisterID::ebp);
|
||||
ret();
|
||||
}
|
||||
|
||||
void callAbsolute(const void *funcPtr)
|
||||
{
|
||||
move(TrustedImmPtr(funcPtr), ScratchRegister);
|
||||
call(ScratchRegister);
|
||||
}
|
||||
|
||||
void pushAligned(RegisterID reg)
|
||||
{
|
||||
subPtr(TrustedImm32(PointerSize), StackPointerRegister);
|
||||
push(reg);
|
||||
}
|
||||
|
||||
void popAligned(RegisterID reg)
|
||||
{
|
||||
pop(reg);
|
||||
addPtr(TrustedImm32(PointerSize), StackPointerRegister);
|
||||
}
|
||||
};
|
||||
|
||||
typedef PlatformAssembler_X86_All PlatformAssemblerBase;
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(Q_PROCESSOR_ARM_64) || defined(ENABLE_ALL_ASSEMBLERS_FOR_REFACTORING_PURPOSES)
|
||||
|
||||
class PlatformAssembler_ARM64 : public JSC::MacroAssembler<JSC::MacroAssemblerARM64>
|
||||
{
|
||||
public:
|
||||
static const RegisterID NoRegister = RegisterID(-1);
|
||||
|
||||
static const RegisterID ReturnValueRegister = JSC::ARM64Registers::x0;
|
||||
static const RegisterID ReturnValueRegisterValue = ReturnValueRegister;
|
||||
static const RegisterID AccumulatorRegister = JSC::ARM64Registers::x9;
|
||||
static const RegisterID AccumulatorRegisterValue = AccumulatorRegister;
|
||||
static const RegisterID ScratchRegister = JSC::ARM64Registers::x10;
|
||||
static const RegisterID ScratchRegister2 = JSC::ARM64Registers::x7; // Note: overlaps with Arg7Reg, so do not use while setting up a call!
|
||||
static const RegisterID JSStackFrameRegister = JSC::ARM64Registers::x19;
|
||||
static const RegisterID CppStackFrameRegister = JSC::ARM64Registers::x20;
|
||||
static const RegisterID EngineRegister = JSC::ARM64Registers::x21;
|
||||
static const RegisterID StackPointerRegister = JSC::ARM64Registers::sp;
|
||||
static const RegisterID FramePointerRegister = JSC::ARM64Registers::fp;
|
||||
static const FPRegisterID FPScratchRegister = JSC::ARM64Registers::q1;
|
||||
|
||||
static const RegisterID Arg0Reg = JSC::ARM64Registers::x0;
|
||||
static const RegisterID Arg1Reg = JSC::ARM64Registers::x1;
|
||||
static const RegisterID Arg2Reg = JSC::ARM64Registers::x2;
|
||||
static const RegisterID Arg3Reg = JSC::ARM64Registers::x3;
|
||||
static const RegisterID Arg4Reg = JSC::ARM64Registers::x4;
|
||||
static const RegisterID Arg5Reg = JSC::ARM64Registers::x5;
|
||||
static const RegisterID Arg6Reg = JSC::ARM64Registers::x6;
|
||||
static const RegisterID Arg7Reg = JSC::ARM64Registers::x7;
|
||||
static const int ArgInRegCount = 8;
|
||||
|
||||
void push(RegisterID src)
|
||||
{
|
||||
pushToSave(src);
|
||||
}
|
||||
|
||||
void pop(RegisterID dest)
|
||||
{
|
||||
popToRestore(dest);
|
||||
}
|
||||
|
||||
void pop()
|
||||
{
|
||||
add64(TrustedImm32(16), stackPointerRegister);
|
||||
}
|
||||
|
||||
void popValue()
|
||||
{
|
||||
pop();
|
||||
}
|
||||
|
||||
void generatePlatformFunctionEntry()
|
||||
{
|
||||
pushPair(JSC::ARM64Registers::fp, JSC::ARM64Registers::lr);
|
||||
move(RegisterID::sp, RegisterID::fp);
|
||||
move(TrustedImmPtr(nullptr), AccumulatorRegister); // exceptionHandler
|
||||
pushPair(JSStackFrameRegister, AccumulatorRegister);
|
||||
pushPair(EngineRegister, CppStackFrameRegister);
|
||||
move(Arg0Reg, CppStackFrameRegister);
|
||||
move(Arg1Reg, EngineRegister);
|
||||
}
|
||||
|
||||
void generatePlatformFunctionExit()
|
||||
{
|
||||
move(AccumulatorRegister, ReturnValueRegister);
|
||||
popPair(EngineRegister, CppStackFrameRegister);
|
||||
popPair(JSStackFrameRegister, AccumulatorRegister);
|
||||
popPair(JSC::ARM64Registers::fp, JSC::ARM64Registers::lr);
|
||||
ret();
|
||||
}
|
||||
|
||||
void callAbsolute(const void *funcPtr)
|
||||
{
|
||||
move(TrustedImmPtr(funcPtr), ScratchRegister);
|
||||
call(ScratchRegister);
|
||||
}
|
||||
|
||||
void pushAligned(RegisterID reg)
|
||||
{
|
||||
pushToSave(reg);
|
||||
}
|
||||
|
||||
void popAligned(RegisterID reg)
|
||||
{
|
||||
popToRestore(reg);
|
||||
}
|
||||
};
|
||||
|
||||
typedef PlatformAssembler_ARM64 PlatformAssemblerBase;
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(Q_PROCESSOR_ARM_32) || defined(ENABLE_ALL_ASSEMBLERS_FOR_REFACTORING_PURPOSES)
|
||||
|
||||
class PlatformAssembler_ARM32 : public JSC::MacroAssembler<JSC::MacroAssemblerARMv7>
|
||||
{
|
||||
public:
|
||||
static const RegisterID NoRegister = RegisterID(-1);
|
||||
|
||||
static const RegisterID ReturnValueRegisterValue = JSC::ARMRegisters::r0;
|
||||
static const RegisterID ReturnValueRegisterTag = JSC::ARMRegisters::r1;
|
||||
static const RegisterID ScratchRegister = JSC::ARMRegisters::r2;
|
||||
static const RegisterID AccumulatorRegisterValue = JSC::ARMRegisters::r4;
|
||||
static const RegisterID AccumulatorRegisterTag = JSC::ARMRegisters::r5;
|
||||
// r6 is used by MacroAssemblerARMv7
|
||||
static const RegisterID JSStackFrameRegister = JSC::ARMRegisters::r8;
|
||||
static const RegisterID CppStackFrameRegister = JSC::ARMRegisters::r10;
|
||||
#if CPU(ARM_THUMB2) || defined(V4_BOOTSTRAP)
|
||||
static const RegisterID FramePointerRegister = JSC::ARMRegisters::r7;
|
||||
static const RegisterID EngineRegister = JSC::ARMRegisters::r11;
|
||||
#else // Thumbs down
|
||||
static const RegisterID FramePointerRegister = JSC::ARMRegisters::r11;
|
||||
static const RegisterID EngineRegister = JSC::ARMRegisters::r7;
|
||||
#endif
|
||||
static const RegisterID StackPointerRegister = JSC::ARMRegisters::r13;
|
||||
static const FPRegisterID FPScratchRegister = JSC::ARMRegisters::d1;
|
||||
|
||||
static const RegisterID Arg0Reg = JSC::ARMRegisters::r0;
|
||||
static const RegisterID Arg1Reg = JSC::ARMRegisters::r1;
|
||||
static const RegisterID Arg2Reg = JSC::ARMRegisters::r2;
|
||||
static const RegisterID Arg3Reg = JSC::ARMRegisters::r3;
|
||||
static const RegisterID Arg4Reg = NoRegister;
|
||||
static const RegisterID Arg5Reg = NoRegister;
|
||||
static const RegisterID Arg6Reg = NoRegister;
|
||||
static const RegisterID Arg7Reg = NoRegister;
|
||||
static const int ArgInRegCount = 4;
|
||||
|
||||
void popValue()
|
||||
{
|
||||
addPtr(TrustedImm32(sizeof(ReturnedValue)), StackPointerRegister);
|
||||
}
|
||||
|
||||
void generatePlatformFunctionEntry()
|
||||
{
|
||||
push(JSC::ARMRegisters::lr);
|
||||
push(FramePointerRegister);
|
||||
move(StackPointerRegister, FramePointerRegister);
|
||||
push(TrustedImm32(0)); // exceptionHandler
|
||||
push(AccumulatorRegisterValue);
|
||||
push(AccumulatorRegisterTag);
|
||||
push(addressTempRegister);
|
||||
push(JSStackFrameRegister);
|
||||
push(CppStackFrameRegister);
|
||||
push(EngineRegister);
|
||||
subPtr(TrustedImm32(4), StackPointerRegister); // stack alignment
|
||||
move(Arg0Reg, CppStackFrameRegister);
|
||||
move(Arg1Reg, EngineRegister);
|
||||
}
|
||||
|
||||
void generatePlatformFunctionExit()
|
||||
{
|
||||
move(AccumulatorRegisterValue, ReturnValueRegisterValue);
|
||||
move(AccumulatorRegisterTag, ReturnValueRegisterTag);
|
||||
addPtr(TrustedImm32(4), StackPointerRegister); // stack alignment
|
||||
pop(EngineRegister);
|
||||
pop(CppStackFrameRegister);
|
||||
pop(JSStackFrameRegister);
|
||||
pop(addressTempRegister);
|
||||
pop(AccumulatorRegisterTag);
|
||||
pop(AccumulatorRegisterValue);
|
||||
pop(); // exceptionHandler
|
||||
pop(FramePointerRegister);
|
||||
pop(JSC::ARMRegisters::lr);
|
||||
ret();
|
||||
}
|
||||
|
||||
void callAbsolute(const void *funcPtr)
|
||||
{
|
||||
move(TrustedImmPtr(funcPtr), dataTempRegister);
|
||||
call(dataTempRegister);
|
||||
}
|
||||
|
||||
void pushAligned(RegisterID reg)
|
||||
{
|
||||
subPtr(TrustedImm32(PointerSize), StackPointerRegister);
|
||||
push(reg);
|
||||
}
|
||||
|
||||
void popAligned(RegisterID reg)
|
||||
{
|
||||
pop(reg);
|
||||
addPtr(TrustedImm32(PointerSize), StackPointerRegister);
|
||||
}
|
||||
};
|
||||
|
||||
typedef PlatformAssembler_ARM32 PlatformAssemblerBase;
|
||||
#endif
|
||||
|
||||
class PlatformAssemblerCommon : public JIT::PlatformAssemblerBase
|
||||
{
|
||||
public:
|
||||
PlatformAssemblerCommon(const Value *constantTable)
|
||||
: constantTable(constantTable)
|
||||
{}
|
||||
|
||||
virtual ~PlatformAssemblerCommon();
|
||||
|
||||
Address exceptionHandlerAddress() const
|
||||
{
|
||||
return Address(FramePointerRegister, -1 * PointerSize);
|
||||
}
|
||||
|
||||
Address contextAddress() const
|
||||
{
|
||||
return Address(JSStackFrameRegister, offsetof(CallData, context));
|
||||
}
|
||||
|
||||
RegisterID registerForArg(int arg) const
|
||||
{
|
||||
Q_ASSERT(arg >= 0);
|
||||
Q_ASSERT(arg < ArgInRegCount);
|
||||
switch (arg) {
|
||||
case 0: return Arg0Reg;
|
||||
case 1: return Arg1Reg;
|
||||
case 2: return Arg2Reg;
|
||||
case 3: return Arg3Reg;
|
||||
case 4: return Arg4Reg;
|
||||
case 5: return Arg5Reg;
|
||||
case 6: return Arg6Reg;
|
||||
case 7: return Arg7Reg;
|
||||
default:
|
||||
Q_UNIMPLEMENTED();
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
Address loadFunctionPtr(RegisterID target)
|
||||
{
|
||||
Address addr(CppStackFrameRegister, offsetof(CppStackFrame, v4Function));
|
||||
loadPtr(addr, target);
|
||||
return Address(target);
|
||||
}
|
||||
|
||||
Address loadCompilationUnitPtr(RegisterID target)
|
||||
{
|
||||
Address addr = loadFunctionPtr(target);
|
||||
addr.offset = offsetof(QV4::Function, compilationUnit);
|
||||
loadPtr(addr, target);
|
||||
return Address(target);
|
||||
}
|
||||
|
||||
Address loadConstAddress(int constIndex, RegisterID baseReg = ScratchRegister)
|
||||
{
|
||||
Address addr = loadCompilationUnitPtr(baseReg);
|
||||
addr.offset = offsetof(QV4::CompiledData::CompilationUnitBase, constants);
|
||||
loadPtr(addr, baseReg);
|
||||
addr.offset = constIndex * int(sizeof(QV4::Value));
|
||||
return addr;
|
||||
}
|
||||
|
||||
Address loadStringAddress(int stringId)
|
||||
{
|
||||
Address addr = loadCompilationUnitPtr(ScratchRegister);
|
||||
addr.offset = offsetof(QV4::CompiledData::CompilationUnitBase, runtimeStrings);
|
||||
loadPtr(addr, ScratchRegister);
|
||||
return Address(ScratchRegister, stringId * PointerSize);
|
||||
}
|
||||
|
||||
void passAsArg(RegisterID src, int arg)
|
||||
{
|
||||
move(src, registerForArg(arg));
|
||||
}
|
||||
|
||||
void generateCatchTrampoline(std::function<void()> loadUndefined)
|
||||
{
|
||||
for (Jump j : catchyJumps)
|
||||
j.link(this);
|
||||
|
||||
loadPtr(exceptionHandlerAddress(), ScratchRegister);
|
||||
Jump exitFunction = branchPtr(Equal, ScratchRegister, TrustedImmPtr(0));
|
||||
jump(ScratchRegister);
|
||||
exitFunction.link(this);
|
||||
loadUndefined();
|
||||
|
||||
if (functionExit.isSet())
|
||||
jump(functionExit);
|
||||
else
|
||||
generateFunctionExit();
|
||||
}
|
||||
|
||||
void checkException()
|
||||
{
|
||||
addCatchyJump(
|
||||
branch32(NotEqual,
|
||||
Address(EngineRegister, offsetof(EngineBase, hasException)),
|
||||
TrustedImm32(0)));
|
||||
}
|
||||
|
||||
void addCatchyJump(Jump j)
|
||||
{
|
||||
Q_ASSERT(j.isSet());
|
||||
catchyJumps.push_back(j);
|
||||
}
|
||||
|
||||
void generateFunctionEntry()
|
||||
{
|
||||
generatePlatformFunctionEntry();
|
||||
loadPtr(Address(CppStackFrameRegister, offsetof(CppStackFrame, jsFrame)), JSStackFrameRegister);
|
||||
allocateStackSpace();
|
||||
}
|
||||
|
||||
virtual void allocateStackSpace() {}
|
||||
|
||||
void generateFunctionExit()
|
||||
{
|
||||
if (functionExit.isSet()) {
|
||||
jump(functionExit);
|
||||
return;
|
||||
}
|
||||
|
||||
functionExit = label();
|
||||
freeStackSpace();
|
||||
generatePlatformFunctionExit();
|
||||
}
|
||||
|
||||
virtual void freeStackSpace() {}
|
||||
|
||||
void addLabelForOffset(int offset)
|
||||
{
|
||||
labelForOffset.insert(offset, label());
|
||||
}
|
||||
|
||||
void addJumpToOffset(const Jump &jump, int offset)
|
||||
{
|
||||
jumpsToLink.push_back({ jump, offset });
|
||||
}
|
||||
|
||||
void addEHTarget(const DataLabelPtr &label, int offset)
|
||||
{
|
||||
ehTargets.push_back({ label, offset });
|
||||
}
|
||||
|
||||
void link(Function *function);
|
||||
|
||||
Value constant(int idx) const
|
||||
{ return constantTable[idx]; }
|
||||
|
||||
// stuff for runtime calls
|
||||
void prepareCallWithArgCount(int argc);
|
||||
void storeInstructionPointer(int instructionOffset);
|
||||
void passAccumulatorAsArg(int arg);
|
||||
void pushAccumulatorAsArg(int arg);
|
||||
void passFunctionAsArg(int arg);
|
||||
void passEngineAsArg(int arg);
|
||||
void passJSSlotAsArg(int reg, int arg);
|
||||
void passAddressAsArg(Address addr, int arg);
|
||||
void passCppFrameAsArg(int arg);
|
||||
void passInt32AsArg(int value, int arg);
|
||||
void callRuntime(const char *functionName, const void *funcPtr);
|
||||
void callRuntimeUnchecked(const char *functionName, const void *funcPtr);
|
||||
|
||||
|
||||
private:
|
||||
void passAccumulatorAsArg_internal(int arg, bool doPush);
|
||||
static Address argStackAddress(int arg);
|
||||
|
||||
private:
|
||||
const Value* constantTable;
|
||||
struct JumpTarget { JSC::MacroAssemblerBase::Jump jump; int offset; };
|
||||
std::vector<JumpTarget> jumpsToLink;
|
||||
struct ExceptionHanlderTarget { JSC::MacroAssemblerBase::DataLabelPtr label; int offset; };
|
||||
std::vector<ExceptionHanlderTarget> ehTargets;
|
||||
QHash<int, JSC::MacroAssemblerBase::Label> labelForOffset;
|
||||
QHash<const void *, const char *> functions;
|
||||
std::vector<Jump> catchyJumps;
|
||||
Label functionExit;
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
enum { NoCall = -1 };
|
||||
int remainingArgcForCall = NoCall;
|
||||
#endif
|
||||
int argcOnStackForCall = 0;
|
||||
};
|
||||
|
||||
} // JIT namespace
|
||||
} // QV4 namespace
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // V4_ENABLE_JIT
|
||||
|
||||
#endif // QV4PLATFORMASSEMBLER_P_H
|
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,6 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2017 The Qt Company Ltd.
|
||||
** Copyright (C) 2018 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtQml module of the Qt Toolkit.
|
||||
|
@ -37,8 +37,8 @@
|
|||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QV4ASSEMBLER_P_H
|
||||
#define QV4ASSEMBLER_P_H
|
||||
#ifndef QV4BASELINEASSEMBLER_P_H
|
||||
#define QV4BASELINEASSEMBLER_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
|
@ -63,22 +63,15 @@ namespace JIT {
|
|||
#define JIT_STRINGIFYx(s) #s
|
||||
#define JIT_STRINGIFY(s) JIT_STRINGIFYx(s)
|
||||
|
||||
#define IN_JIT_GENERATE_RUNTIME_CALL(function, destination) \
|
||||
#define GENERATE_RUNTIME_CALL(function, destination) \
|
||||
callRuntime(JIT_STRINGIFY(function), \
|
||||
reinterpret_cast<void *>(&function), \
|
||||
destination)
|
||||
#define JIT_GENERATE_RUNTIME_CALL(function, destination) \
|
||||
as->IN_JIT_GENERATE_RUNTIME_CALL(function, destination)
|
||||
|
||||
class Assembler {
|
||||
class BaselineAssembler {
|
||||
public:
|
||||
enum CallResultDestination {
|
||||
IgnoreResult,
|
||||
ResultInAccumulator,
|
||||
};
|
||||
|
||||
Assembler(const Value* constantTable);
|
||||
~Assembler();
|
||||
BaselineAssembler(const Value* constantTable);
|
||||
~BaselineAssembler();
|
||||
|
||||
// codegen infrastructure
|
||||
void generatePrologue();
|
||||
|
@ -151,10 +144,10 @@ public:
|
|||
void passAccumulatorAsArg(int arg);
|
||||
void passFunctionAsArg(int arg);
|
||||
void passEngineAsArg(int arg);
|
||||
void passRegAsArg(int reg, int arg);
|
||||
void passJSSlotAsArg(int reg, int arg);
|
||||
void passCppFrameAsArg(int arg);
|
||||
void passInt32AsArg(int value, int arg);
|
||||
void callRuntime(const char *functionName, const void *funcPtr, Assembler::CallResultDestination dest);
|
||||
void callRuntime(const char *functionName, const void *funcPtr, CallResultDestination dest);
|
||||
void saveAccumulatorInFrame();
|
||||
|
||||
// exception/context stuff
|
||||
|
@ -175,16 +168,9 @@ public:
|
|||
protected:
|
||||
void *d;
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
enum { NoCall = -1 };
|
||||
int remainingArgcForCall = NoCall;
|
||||
#endif
|
||||
int argcOnStackForCall = 0;
|
||||
|
||||
private:
|
||||
typedef unsigned(*CmpFunc)(const Value&,const Value&);
|
||||
void cmp(int cond, CmpFunc function, const char *functionName, int lhs);
|
||||
void passAccumulatorAsArg_internal(int arg, bool push);
|
||||
};
|
||||
|
||||
} // namespace JIT
|
||||
|
@ -192,4 +178,4 @@ private:
|
|||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QV4ASSEMBLER_P_H
|
||||
#endif // QV4BASELINEASSEMBLER_P_H
|
|
@ -39,7 +39,7 @@
|
|||
|
||||
#include "qv4baselinejit_p.h"
|
||||
#include "qv4jithelpers_p.h"
|
||||
#include "qv4assembler_p.h"
|
||||
#include "qv4baselineassembler_p.h"
|
||||
#include <private/qv4lookup_p.h>
|
||||
#include <private/qv4generatorobject_p.h>
|
||||
|
||||
|
@ -52,7 +52,7 @@ using namespace QV4::Moth;
|
|||
|
||||
BaselineJIT::BaselineJIT(Function *function)
|
||||
: function(function)
|
||||
, as(new Assembler(function->compilationUnit->constants))
|
||||
, as(new BaselineAssembler(function->compilationUnit->constants))
|
||||
{}
|
||||
|
||||
BaselineJIT::~BaselineJIT()
|
||||
|
@ -75,6 +75,8 @@ void BaselineJIT::generate()
|
|||
|
||||
#define STORE_IP() as->storeInstructionPointer(nextInstructionOffset())
|
||||
#define STORE_ACC() as->saveAccumulatorInFrame()
|
||||
#define BASELINEJIT_GENERATE_RUNTIME_CALL(function, destination) \
|
||||
as->GENERATE_RUNTIME_CALL(function, destination)
|
||||
|
||||
void BaselineJIT::generate_Ret()
|
||||
{
|
||||
|
@ -177,7 +179,7 @@ void BaselineJIT::generate_MoveRegExp(int regExpId, int destReg)
|
|||
as->prepareCallWithArgCount(2);
|
||||
as->passInt32AsArg(regExpId, 1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_regexpLiteral, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_regexpLiteral, CallResultDestination::InAccumulator);
|
||||
as->storeReg(destReg);
|
||||
}
|
||||
|
||||
|
@ -186,7 +188,7 @@ void BaselineJIT::generate_LoadClosure(int value)
|
|||
as->prepareCallWithArgCount(2);
|
||||
as->passInt32AsArg(value, 1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_closure, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_closure, CallResultDestination::InAccumulator);
|
||||
}
|
||||
|
||||
void BaselineJIT::generate_LoadName(int name)
|
||||
|
@ -195,7 +197,7 @@ void BaselineJIT::generate_LoadName(int name)
|
|||
as->prepareCallWithArgCount(2);
|
||||
as->passInt32AsArg(name, 1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_loadName, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_loadName, CallResultDestination::InAccumulator);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
|
@ -205,7 +207,7 @@ void BaselineJIT::generate_LoadGlobalLookup(int index)
|
|||
as->passInt32AsArg(index, 2);
|
||||
as->passFunctionAsArg(1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Helpers::loadGlobalLookup, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Helpers::loadGlobalLookup, CallResultDestination::InAccumulator);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
|
@ -217,7 +219,7 @@ void BaselineJIT::generate_StoreNameSloppy(int name)
|
|||
as->passAccumulatorAsArg(2);
|
||||
as->passInt32AsArg(name, 1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_storeNameSloppy, Assembler::IgnoreResult);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_storeNameSloppy, CallResultDestination::Ignore);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
|
@ -229,7 +231,7 @@ void BaselineJIT::generate_StoreNameStrict(int name)
|
|||
as->passAccumulatorAsArg(2);
|
||||
as->passInt32AsArg(name, 1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_storeNameStrict, Assembler::IgnoreResult);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_storeNameStrict, CallResultDestination::Ignore);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
|
@ -239,9 +241,9 @@ void BaselineJIT::generate_LoadElement(int base)
|
|||
STORE_ACC();
|
||||
as->prepareCallWithArgCount(3);
|
||||
as->passAccumulatorAsArg(2);
|
||||
as->passRegAsArg(base, 1);
|
||||
as->passJSSlotAsArg(base, 1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_loadElement, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_loadElement, CallResultDestination::InAccumulator);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
|
@ -251,10 +253,10 @@ void BaselineJIT::generate_StoreElement(int base, int index)
|
|||
STORE_ACC();
|
||||
as->prepareCallWithArgCount(4);
|
||||
as->passAccumulatorAsArg(3);
|
||||
as->passRegAsArg(index, 2);
|
||||
as->passRegAsArg(base, 1);
|
||||
as->passJSSlotAsArg(index, 2);
|
||||
as->passJSSlotAsArg(base, 1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_storeElement, Assembler::IgnoreResult);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_storeElement, CallResultDestination::Ignore);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
|
@ -266,7 +268,7 @@ void BaselineJIT::generate_LoadProperty(int name)
|
|||
as->passInt32AsArg(name, 2);
|
||||
as->passAccumulatorAsArg(1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_loadProperty, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_loadProperty, CallResultDestination::InAccumulator);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
|
@ -279,7 +281,7 @@ void BaselineJIT::generate_GetLookup(int index)
|
|||
as->passInt32AsArg(index, 2);
|
||||
as->passFunctionAsArg(1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Helpers::getLookup, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Helpers::getLookup, CallResultDestination::InAccumulator);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
|
@ -290,9 +292,9 @@ void BaselineJIT::generate_StoreProperty(int name, int base)
|
|||
as->prepareCallWithArgCount(4);
|
||||
as->passAccumulatorAsArg(3);
|
||||
as->passInt32AsArg(name, 2);
|
||||
as->passRegAsArg(base, 1);
|
||||
as->passJSSlotAsArg(base, 1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_storeProperty, Assembler::IgnoreResult);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_storeProperty, CallResultDestination::Ignore);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
|
@ -302,10 +304,10 @@ void BaselineJIT::generate_SetLookup(int index, int base)
|
|||
STORE_ACC();
|
||||
as->prepareCallWithArgCount(4);
|
||||
as->passAccumulatorAsArg(3);
|
||||
as->passRegAsArg(base, 2);
|
||||
as->passJSSlotAsArg(base, 2);
|
||||
as->passInt32AsArg(index, 1);
|
||||
as->passFunctionAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Helpers::setLookup, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Helpers::setLookup, CallResultDestination::InAccumulator);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
|
@ -314,9 +316,9 @@ void BaselineJIT::generate_LoadSuperProperty(int property)
|
|||
STORE_IP();
|
||||
STORE_ACC();
|
||||
as->prepareCallWithArgCount(2);
|
||||
as->passRegAsArg(property, 1);
|
||||
as->passJSSlotAsArg(property, 1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_loadSuperProperty, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_loadSuperProperty, CallResultDestination::InAccumulator);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
|
@ -326,9 +328,9 @@ void BaselineJIT::generate_StoreSuperProperty(int property)
|
|||
STORE_ACC();
|
||||
as->prepareCallWithArgCount(3);
|
||||
as->passAccumulatorAsArg(2);
|
||||
as->passRegAsArg(property, 1);
|
||||
as->passJSSlotAsArg(property, 1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_storeSuperProperty, Assembler::IgnoreResult);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_storeSuperProperty, CallResultDestination::Ignore);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
|
@ -339,9 +341,9 @@ void BaselineJIT::generate_StoreScopeObjectProperty(int base, int propertyIndex)
|
|||
as->prepareCallWithArgCount(4);
|
||||
as->passAccumulatorAsArg(3);
|
||||
as->passInt32AsArg(propertyIndex, 2);
|
||||
as->passRegAsArg(base, 1);
|
||||
as->passJSSlotAsArg(base, 1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_storeQmlScopeObjectProperty, Assembler::IgnoreResult);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_storeQmlScopeObjectProperty, CallResultDestination::Ignore);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
|
@ -351,9 +353,9 @@ void BaselineJIT::generate_StoreContextObjectProperty(int base, int propertyInde
|
|||
as->prepareCallWithArgCount(4);
|
||||
as->passAccumulatorAsArg(3);
|
||||
as->passInt32AsArg(propertyIndex, 2);
|
||||
as->passRegAsArg(base, 1);
|
||||
as->passJSSlotAsArg(base, 1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_storeQmlContextObjectProperty, Assembler::IgnoreResult);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_storeQmlContextObjectProperty, CallResultDestination::Ignore);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
|
@ -363,9 +365,9 @@ void BaselineJIT::generate_LoadScopeObjectProperty(int propertyIndex, int base,
|
|||
as->prepareCallWithArgCount(4);
|
||||
as->passInt32AsArg(captureRequired, 3);
|
||||
as->passInt32AsArg(propertyIndex, 2);
|
||||
as->passRegAsArg(base, 1);
|
||||
as->passJSSlotAsArg(base, 1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_loadQmlScopeObjectProperty, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_loadQmlScopeObjectProperty, CallResultDestination::InAccumulator);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
|
@ -375,9 +377,9 @@ void BaselineJIT::generate_LoadContextObjectProperty(int propertyIndex, int base
|
|||
as->prepareCallWithArgCount(4);
|
||||
as->passInt32AsArg(captureRequired, 3);
|
||||
as->passInt32AsArg(propertyIndex, 2);
|
||||
as->passRegAsArg(base, 1);
|
||||
as->passJSSlotAsArg(base, 1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_loadQmlContextObjectProperty, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_loadQmlContextObjectProperty, CallResultDestination::InAccumulator);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
|
@ -386,9 +388,9 @@ void BaselineJIT::generate_LoadIdObject(int index, int base)
|
|||
STORE_IP();
|
||||
as->prepareCallWithArgCount(3);
|
||||
as->passInt32AsArg(index, 2);
|
||||
as->passRegAsArg(base, 1);
|
||||
as->passJSSlotAsArg(base, 1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_loadQmlIdObject, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_loadQmlIdObject, CallResultDestination::InAccumulator);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
|
@ -409,10 +411,10 @@ void BaselineJIT::generate_CallValue(int name, int argc, int argv)
|
|||
STORE_IP();
|
||||
as->prepareCallWithArgCount(4);
|
||||
as->passInt32AsArg(argc, 3);
|
||||
as->passRegAsArg(argv, 2);
|
||||
as->passRegAsArg(name, 1);
|
||||
as->passJSSlotAsArg(argv, 2);
|
||||
as->passJSSlotAsArg(name, 1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_callValue, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_callValue, CallResultDestination::InAccumulator);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
|
@ -421,11 +423,11 @@ void BaselineJIT::generate_CallProperty(int name, int base, int argc, int argv)
|
|||
STORE_IP();
|
||||
as->prepareCallWithArgCount(5);
|
||||
as->passInt32AsArg(argc, 4);
|
||||
as->passRegAsArg(argv, 3);
|
||||
as->passJSSlotAsArg(argv, 3);
|
||||
as->passInt32AsArg(name, 2);
|
||||
as->passRegAsArg(base, 1);
|
||||
as->passJSSlotAsArg(base, 1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_callProperty, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_callProperty, CallResultDestination::InAccumulator);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
|
@ -434,11 +436,11 @@ void BaselineJIT::generate_CallPropertyLookup(int lookupIndex, int base, int arg
|
|||
STORE_IP();
|
||||
as->prepareCallWithArgCount(5);
|
||||
as->passInt32AsArg(argc, 4);
|
||||
as->passRegAsArg(argv, 3);
|
||||
as->passJSSlotAsArg(argv, 3);
|
||||
as->passInt32AsArg(lookupIndex, 2);
|
||||
as->passRegAsArg(base, 1);
|
||||
as->passJSSlotAsArg(base, 1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_callPropertyLookup, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_callPropertyLookup, CallResultDestination::InAccumulator);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
|
@ -447,11 +449,11 @@ void BaselineJIT::generate_CallElement(int base, int index, int argc, int argv)
|
|||
STORE_IP();
|
||||
as->prepareCallWithArgCount(5);
|
||||
as->passInt32AsArg(argc, 4);
|
||||
as->passRegAsArg(argv, 3);
|
||||
as->passRegAsArg(index, 2);
|
||||
as->passRegAsArg(base, 1);
|
||||
as->passJSSlotAsArg(argv, 3);
|
||||
as->passJSSlotAsArg(index, 2);
|
||||
as->passJSSlotAsArg(base, 1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_callElement, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_callElement, CallResultDestination::InAccumulator);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
|
@ -460,10 +462,10 @@ void BaselineJIT::generate_CallName(int name, int argc, int argv)
|
|||
STORE_IP();
|
||||
as->prepareCallWithArgCount(4);
|
||||
as->passInt32AsArg(argc, 3);
|
||||
as->passRegAsArg(argv, 2);
|
||||
as->passJSSlotAsArg(argv, 2);
|
||||
as->passInt32AsArg(name, 1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_callName, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_callName, CallResultDestination::InAccumulator);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
|
@ -472,9 +474,9 @@ void BaselineJIT::generate_CallPossiblyDirectEval(int argc, int argv)
|
|||
STORE_IP();
|
||||
as->prepareCallWithArgCount(3);
|
||||
as->passInt32AsArg(argc, 2);
|
||||
as->passRegAsArg(argv, 1);
|
||||
as->passJSSlotAsArg(argv, 1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_callPossiblyDirectEval, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_callPossiblyDirectEval, CallResultDestination::InAccumulator);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
|
@ -483,10 +485,10 @@ void BaselineJIT::generate_CallGlobalLookup(int index, int argc, int argv)
|
|||
STORE_IP();
|
||||
as->prepareCallWithArgCount(4);
|
||||
as->passInt32AsArg(argc, 3);
|
||||
as->passRegAsArg(argv, 2);
|
||||
as->passJSSlotAsArg(argv, 2);
|
||||
as->passInt32AsArg(index, 1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_callGlobalLookup, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_callGlobalLookup, CallResultDestination::InAccumulator);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
|
@ -495,11 +497,11 @@ void BaselineJIT::generate_CallScopeObjectProperty(int propIdx, int base, int ar
|
|||
STORE_IP();
|
||||
as->prepareCallWithArgCount(5);
|
||||
as->passInt32AsArg(argc, 4);
|
||||
as->passRegAsArg(argv, 3);
|
||||
as->passJSSlotAsArg(argv, 3);
|
||||
as->passInt32AsArg(propIdx, 2);
|
||||
as->passRegAsArg(base, 1);
|
||||
as->passJSSlotAsArg(base, 1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_callQmlScopeObjectProperty, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_callQmlScopeObjectProperty, CallResultDestination::InAccumulator);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
|
@ -508,11 +510,11 @@ void BaselineJIT::generate_CallContextObjectProperty(int propIdx, int base, int
|
|||
STORE_IP();
|
||||
as->prepareCallWithArgCount(5);
|
||||
as->passInt32AsArg(argc, 4);
|
||||
as->passRegAsArg(argv, 3);
|
||||
as->passJSSlotAsArg(argv, 3);
|
||||
as->passInt32AsArg(propIdx, 2);
|
||||
as->passRegAsArg(base, 1);
|
||||
as->passJSSlotAsArg(base, 1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_callQmlContextObjectProperty, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_callQmlContextObjectProperty, CallResultDestination::InAccumulator);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
|
@ -522,11 +524,11 @@ void BaselineJIT::generate_CallWithSpread(int func, int thisObject, int argc, in
|
|||
STORE_IP();
|
||||
as->prepareCallWithArgCount(5);
|
||||
as->passInt32AsArg(argc, 4);
|
||||
as->passRegAsArg(argv, 3);
|
||||
as->passRegAsArg(thisObject, 2);
|
||||
as->passRegAsArg(func, 1);
|
||||
as->passJSSlotAsArg(argv, 3);
|
||||
as->passJSSlotAsArg(thisObject, 2);
|
||||
as->passJSSlotAsArg(func, 1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_callWithSpread, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_callWithSpread, CallResultDestination::InAccumulator);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
|
@ -537,11 +539,11 @@ void BaselineJIT::generate_Construct(int func, int argc, int argv)
|
|||
STORE_ACC();
|
||||
as->prepareCallWithArgCount(5);
|
||||
as->passInt32AsArg(argc, 4);
|
||||
as->passRegAsArg(argv, 3);
|
||||
as->passJSSlotAsArg(argv, 3);
|
||||
as->passAccumulatorAsArg(2);
|
||||
as->passRegAsArg(func, 1);
|
||||
as->passJSSlotAsArg(func, 1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_construct, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_construct, CallResultDestination::InAccumulator);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
|
@ -551,11 +553,11 @@ void BaselineJIT::generate_ConstructWithSpread(int func, int argc, int argv)
|
|||
STORE_ACC();
|
||||
as->prepareCallWithArgCount(5);
|
||||
as->passInt32AsArg(argc, 4);
|
||||
as->passRegAsArg(argv, 3);
|
||||
as->passJSSlotAsArg(argv, 3);
|
||||
as->passAccumulatorAsArg(2);
|
||||
as->passRegAsArg(func, 1);
|
||||
as->passJSSlotAsArg(func, 1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_constructWithSpread, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_constructWithSpread, CallResultDestination::InAccumulator);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
|
@ -585,7 +587,7 @@ void BaselineJIT::generate_ThrowException()
|
|||
as->prepareCallWithArgCount(2);
|
||||
as->passAccumulatorAsArg(1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_throwException, Assembler::IgnoreResult);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_throwException, CallResultDestination::Ignore);
|
||||
as->gotoCatchException();
|
||||
}
|
||||
|
||||
|
@ -596,7 +598,7 @@ void BaselineJIT::generate_CreateCallContext()
|
|||
{
|
||||
as->prepareCallWithArgCount(1);
|
||||
as->passCppFrameAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(ExecutionContext::newCallContext, Assembler::IgnoreResult); // keeps result in return value register
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(ExecutionContext::newCallContext, CallResultDestination::Ignore); // keeps result in return value register
|
||||
as->storeHeapObject(CallData::Context);
|
||||
}
|
||||
|
||||
|
@ -607,9 +609,9 @@ void BaselineJIT::generate_PushWithContext()
|
|||
STORE_IP();
|
||||
as->saveAccumulatorInFrame();
|
||||
as->prepareCallWithArgCount(2);
|
||||
as->passRegAsArg(0, 1);
|
||||
as->passJSSlotAsArg(0, 1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_createWithContext, Assembler::IgnoreResult); // keeps result in return value register
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_createWithContext, CallResultDestination::Ignore); // keeps result in return value register
|
||||
as->checkException();
|
||||
as->storeHeapObject(CallData::Context);
|
||||
}
|
||||
|
@ -619,16 +621,16 @@ void BaselineJIT::generate_PushBlockContext(int index)
|
|||
as->saveAccumulatorInFrame();
|
||||
as->prepareCallWithArgCount(2);
|
||||
as->passInt32AsArg(index, 1);
|
||||
as->passRegAsArg(0, 0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Helpers::pushBlockContext, Assembler::IgnoreResult);
|
||||
as->passJSSlotAsArg(0, 0);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Helpers::pushBlockContext, CallResultDestination::Ignore);
|
||||
}
|
||||
|
||||
void BaselineJIT::generate_CloneBlockContext()
|
||||
{
|
||||
as->saveAccumulatorInFrame();
|
||||
as->prepareCallWithArgCount(1);
|
||||
as->passRegAsArg(CallData::Context, 0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Helpers::cloneBlockContext, Assembler::IgnoreResult);
|
||||
as->passJSSlotAsArg(CallData::Context, 0);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Helpers::cloneBlockContext, CallResultDestination::Ignore);
|
||||
}
|
||||
|
||||
void BaselineJIT::generate_PushScriptContext(int index)
|
||||
|
@ -637,8 +639,8 @@ void BaselineJIT::generate_PushScriptContext(int index)
|
|||
as->prepareCallWithArgCount(3);
|
||||
as->passInt32AsArg(index, 2);
|
||||
as->passEngineAsArg(1);
|
||||
as->passRegAsArg(0, 0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Helpers::pushScriptContext, Assembler::IgnoreResult);
|
||||
as->passJSSlotAsArg(0, 0);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Helpers::pushScriptContext, CallResultDestination::Ignore);
|
||||
}
|
||||
|
||||
void BaselineJIT::generate_PopScriptContext()
|
||||
|
@ -646,8 +648,8 @@ void BaselineJIT::generate_PopScriptContext()
|
|||
as->saveAccumulatorInFrame();
|
||||
as->prepareCallWithArgCount(2);
|
||||
as->passEngineAsArg(1);
|
||||
as->passRegAsArg(0, 0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Helpers::popScriptContext, Assembler::IgnoreResult);
|
||||
as->passJSSlotAsArg(0, 0);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Helpers::popScriptContext, CallResultDestination::Ignore);
|
||||
}
|
||||
|
||||
void BaselineJIT::generate_PopContext() { as->popContext(); }
|
||||
|
@ -659,7 +661,7 @@ void BaselineJIT::generate_GetIterator(int iterator)
|
|||
as->passInt32AsArg(iterator, 2);
|
||||
as->passAccumulatorAsArg(1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_getIterator, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_getIterator, CallResultDestination::InAccumulator);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
|
@ -667,10 +669,10 @@ void BaselineJIT::generate_IteratorNext(int value)
|
|||
{
|
||||
as->saveAccumulatorInFrame();
|
||||
as->prepareCallWithArgCount(3);
|
||||
as->passRegAsArg(value, 2);
|
||||
as->passJSSlotAsArg(value, 2);
|
||||
as->passAccumulatorAsArg(1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_iteratorNext, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_iteratorNext, CallResultDestination::InAccumulator);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
|
@ -678,10 +680,10 @@ void BaselineJIT::generate_IteratorClose(int done)
|
|||
{
|
||||
as->saveAccumulatorInFrame();
|
||||
as->prepareCallWithArgCount(3);
|
||||
as->passRegAsArg(done, 2);
|
||||
as->passJSSlotAsArg(done, 2);
|
||||
as->passAccumulatorAsArg(1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_iteratorClose, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_iteratorClose, CallResultDestination::InAccumulator);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
|
@ -691,7 +693,7 @@ void BaselineJIT::generate_DestructureRestElement()
|
|||
as->prepareCallWithArgCount(2);
|
||||
as->passAccumulatorAsArg(1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_destructureRestElement, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_destructureRestElement, CallResultDestination::InAccumulator);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
|
@ -699,10 +701,10 @@ void BaselineJIT::generate_DeleteProperty(int base, int index)
|
|||
{
|
||||
STORE_IP();
|
||||
as->prepareCallWithArgCount(3);
|
||||
as->passRegAsArg(index, 2);
|
||||
as->passRegAsArg(base, 1);
|
||||
as->passJSSlotAsArg(index, 2);
|
||||
as->passJSSlotAsArg(base, 1);
|
||||
as->passFunctionAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Helpers::deleteProperty, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Helpers::deleteProperty, CallResultDestination::InAccumulator);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
|
@ -712,7 +714,7 @@ void BaselineJIT::generate_DeleteName(int name)
|
|||
as->prepareCallWithArgCount(2);
|
||||
as->passInt32AsArg(name, 1);
|
||||
as->passFunctionAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Helpers::deleteName, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Helpers::deleteName, CallResultDestination::InAccumulator);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
|
@ -721,7 +723,7 @@ void BaselineJIT::generate_TypeofName(int name)
|
|||
as->prepareCallWithArgCount(2);
|
||||
as->passInt32AsArg(name, 1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_typeofName, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_typeofName, CallResultDestination::InAccumulator);
|
||||
}
|
||||
|
||||
void BaselineJIT::generate_TypeofValue()
|
||||
|
@ -730,7 +732,7 @@ void BaselineJIT::generate_TypeofValue()
|
|||
as->prepareCallWithArgCount(2);
|
||||
as->passAccumulatorAsArg(1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_typeofValue, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_typeofValue, CallResultDestination::InAccumulator);
|
||||
}
|
||||
|
||||
void BaselineJIT::generate_DeclareVar(int varName, int isDeletable)
|
||||
|
@ -739,52 +741,52 @@ void BaselineJIT::generate_DeclareVar(int varName, int isDeletable)
|
|||
as->passInt32AsArg(varName, 2);
|
||||
as->passInt32AsArg(isDeletable, 1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_declareVar, Assembler::IgnoreResult);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_declareVar, CallResultDestination::Ignore);
|
||||
}
|
||||
|
||||
void BaselineJIT::generate_DefineArray(int argc, int args)
|
||||
{
|
||||
as->prepareCallWithArgCount(3);
|
||||
as->passInt32AsArg(argc, 2);
|
||||
as->passRegAsArg(args, 1);
|
||||
as->passJSSlotAsArg(args, 1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_arrayLiteral, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_arrayLiteral, CallResultDestination::InAccumulator);
|
||||
}
|
||||
|
||||
void BaselineJIT::generate_DefineObjectLiteral(int internalClassId, int argc, int args)
|
||||
{
|
||||
as->prepareCallWithArgCount(4);
|
||||
as->passRegAsArg(args, 3);
|
||||
as->passJSSlotAsArg(args, 3);
|
||||
as->passInt32AsArg(argc, 2);
|
||||
as->passInt32AsArg(internalClassId, 1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_objectLiteral, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_objectLiteral, CallResultDestination::InAccumulator);
|
||||
}
|
||||
|
||||
void BaselineJIT::generate_CreateClass(int classIndex, int heritage, int computedNames)
|
||||
{
|
||||
as->prepareCallWithArgCount(4);
|
||||
as->passRegAsArg(computedNames, 3);
|
||||
as->passRegAsArg(heritage, 2);
|
||||
as->passJSSlotAsArg(computedNames, 3);
|
||||
as->passJSSlotAsArg(heritage, 2);
|
||||
as->passInt32AsArg(classIndex, 1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_createClass, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_createClass, CallResultDestination::InAccumulator);
|
||||
}
|
||||
|
||||
void BaselineJIT::generate_CreateMappedArgumentsObject()
|
||||
{
|
||||
as->prepareCallWithArgCount(1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_createMappedArgumentsObject,
|
||||
Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_createMappedArgumentsObject,
|
||||
CallResultDestination::InAccumulator);
|
||||
}
|
||||
|
||||
void BaselineJIT::generate_CreateUnmappedArgumentsObject()
|
||||
{
|
||||
as->prepareCallWithArgCount(1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_createUnmappedArgumentsObject,
|
||||
Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_createUnmappedArgumentsObject,
|
||||
CallResultDestination::InAccumulator);
|
||||
}
|
||||
|
||||
void BaselineJIT::generate_CreateRestParameter(int argIndex)
|
||||
|
@ -792,24 +794,24 @@ void BaselineJIT::generate_CreateRestParameter(int argIndex)
|
|||
as->prepareCallWithArgCount(2);
|
||||
as->passInt32AsArg(argIndex, 1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_createRestParameter, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_createRestParameter, CallResultDestination::InAccumulator);
|
||||
}
|
||||
|
||||
void BaselineJIT::generate_ConvertThisToObject()
|
||||
{
|
||||
as->prepareCallWithArgCount(2);
|
||||
as->passRegAsArg(CallData::This, 1);
|
||||
as->passJSSlotAsArg(CallData::This, 1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Helpers::convertThisToObject, Assembler::IgnoreResult);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Helpers::convertThisToObject, CallResultDestination::Ignore);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
void BaselineJIT::generate_LoadSuperConstructor()
|
||||
{
|
||||
as->prepareCallWithArgCount(2);
|
||||
as->passRegAsArg(CallData::Function, 1);
|
||||
as->passJSSlotAsArg(CallData::Function, 1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Helpers::loadSuperConstructor, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Helpers::loadSuperConstructor, CallResultDestination::InAccumulator);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
|
@ -819,7 +821,7 @@ void BaselineJIT::generate_ToObject()
|
|||
as->prepareCallWithArgCount(2);
|
||||
as->passAccumulatorAsArg(1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Helpers::toObject, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Helpers::toObject, CallResultDestination::InAccumulator);
|
||||
as->checkException();
|
||||
|
||||
}
|
||||
|
@ -848,9 +850,9 @@ void BaselineJIT::generate_CmpIn(int lhs)
|
|||
STORE_ACC();
|
||||
as->prepareCallWithArgCount(3);
|
||||
as->passAccumulatorAsArg(2);
|
||||
as->passRegAsArg(lhs, 1);
|
||||
as->passJSSlotAsArg(lhs, 1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_in, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_in, CallResultDestination::InAccumulator);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
|
@ -859,9 +861,9 @@ void BaselineJIT::generate_CmpInstanceOf(int lhs)
|
|||
STORE_ACC();
|
||||
as->prepareCallWithArgCount(3);
|
||||
as->passAccumulatorAsArg(2);
|
||||
as->passRegAsArg(lhs, 1);
|
||||
as->passJSSlotAsArg(lhs, 1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_instanceof, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_instanceof, CallResultDestination::InAccumulator);
|
||||
as->checkException();
|
||||
}
|
||||
|
||||
|
@ -892,8 +894,8 @@ void BaselineJIT::generate_Exp(int lhs) {
|
|||
STORE_ACC();
|
||||
as->prepareCallWithArgCount(2);
|
||||
as->passAccumulatorAsArg(1);
|
||||
as->passRegAsArg(lhs, 0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Helpers::exp, Assembler::ResultInAccumulator);
|
||||
as->passJSSlotAsArg(lhs, 0);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Helpers::exp, CallResultDestination::InAccumulator);
|
||||
as->checkException();
|
||||
}
|
||||
void BaselineJIT::generate_Mul(int lhs) { as->mul(lhs); }
|
||||
|
@ -909,7 +911,7 @@ void BaselineJIT::generate_Sub(int lhs) { as->sub(lhs); }
|
|||
// as->passAccumulatorAsArg(2);
|
||||
// as->passRegAsArg(lhs, 1);
|
||||
// as->passEngineAsArg(0);
|
||||
// as->callRuntime("binopContext", op, Assembler::ResultInAccumulator);
|
||||
// as->callRuntime("binopContext", op, CallResultDestination::InAccumulator);
|
||||
// as->checkException();
|
||||
//}
|
||||
|
||||
|
@ -917,7 +919,7 @@ void BaselineJIT::generate_LoadQmlContext(int result)
|
|||
{
|
||||
as->prepareCallWithArgCount(1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_loadQmlContext, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_loadQmlContext, CallResultDestination::InAccumulator);
|
||||
as->storeReg(result);
|
||||
}
|
||||
|
||||
|
@ -925,7 +927,7 @@ void BaselineJIT::generate_LoadQmlImportedScripts(int result)
|
|||
{
|
||||
as->prepareCallWithArgCount(1);
|
||||
as->passEngineAsArg(0);
|
||||
JIT_GENERATE_RUNTIME_CALL(Runtime::method_loadQmlImportedScripts, Assembler::ResultInAccumulator);
|
||||
BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_loadQmlImportedScripts, CallResultDestination::InAccumulator);
|
||||
as->storeReg(result);
|
||||
}
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ QT_BEGIN_NAMESPACE
|
|||
namespace QV4 {
|
||||
namespace JIT {
|
||||
|
||||
class Assembler;
|
||||
class BaselineAssembler;
|
||||
|
||||
#ifdef V4_ENABLE_JIT
|
||||
class BaselineJIT final: public Moth::ByteCodeHandler
|
||||
|
@ -221,7 +221,7 @@ protected:
|
|||
|
||||
private:
|
||||
QV4::Function *function;
|
||||
QScopedPointer<Assembler> as;
|
||||
QScopedPointer<BaselineAssembler> as;
|
||||
std::vector<int> labels;
|
||||
};
|
||||
#endif // V4_ENABLE_JIT
|
||||
|
|
|
@ -381,7 +381,16 @@ enum class ObjectLiteralArgument {
|
|||
Setter
|
||||
};
|
||||
|
||||
}
|
||||
namespace JIT {
|
||||
|
||||
enum class CallResultDestination {
|
||||
Ignore,
|
||||
InAccumulator,
|
||||
};
|
||||
|
||||
} // JIT namespace
|
||||
|
||||
} // QV4 namespace
|
||||
|
||||
Q_DECLARE_TYPEINFO(QV4::PropertyAttributes, Q_PRIMITIVE_TYPE);
|
||||
|
||||
|
|
Loading…
Reference in New Issue