From 23aa9d58d006dd50adb3f582df9b7dab4f64be0b Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Fri, 27 Apr 2018 13:25:41 +0200 Subject: Rename qv4jit* to qv4baselinejit So it reflects its contents better. Change-Id: Ie9414117a28e681fbb6220c8cddb41be1481fd44 Reviewed-by: Simon Hausmann --- src/qml/jit/jit.pri | 4 +- src/qml/jit/qv4baselinejit.cpp | 1035 +++++++++++++++++++++++++++++++++++++ src/qml/jit/qv4baselinejit_p.h | 232 +++++++++ src/qml/jit/qv4jit.cpp | 1035 ------------------------------------- src/qml/jit/qv4jit_p.h | 232 --------- src/qml/jsruntime/qv4vme_moth.cpp | 2 +- 6 files changed, 1270 insertions(+), 1270 deletions(-) create mode 100644 src/qml/jit/qv4baselinejit.cpp create mode 100644 src/qml/jit/qv4baselinejit_p.h delete mode 100644 src/qml/jit/qv4jit.cpp delete mode 100644 src/qml/jit/qv4jit_p.h (limited to 'src/qml') diff --git a/src/qml/jit/jit.pri b/src/qml/jit/jit.pri index 2080844d93..2b6b2e7c3c 100644 --- a/src/qml/jit/jit.pri +++ b/src/qml/jit/jit.pri @@ -2,9 +2,9 @@ INCLUDEPATH += $$PWD INCLUDEPATH += $$OUT_PWD SOURCES += \ - $$PWD/qv4jit.cpp \ + $$PWD/qv4baselinejit.cpp \ $$PWD/qv4assembler.cpp HEADERS += \ - $$PWD/qv4jit_p.h \ + $$PWD/qv4baselinejit_p.h \ $$PWD/qv4assembler_p.h diff --git a/src/qml/jit/qv4baselinejit.cpp b/src/qml/jit/qv4baselinejit.cpp new file mode 100644 index 0000000000..3faf2ac8d9 --- /dev/null +++ b/src/qml/jit/qv4baselinejit.cpp @@ -0,0 +1,1035 @@ +/**************************************************************************** +** +** 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 "qv4baselinejit_p.h" +#include "qv4assembler_p.h" +#include +#include + +#ifdef V4_ENABLE_JIT + +QT_USE_NAMESPACE +using namespace QV4; +using namespace QV4::JIT; +using namespace QV4::Moth; + +BaselineJIT::BaselineJIT(Function *function) + : function(function) + , as(new Assembler(function->compilationUnit->constants)) +{} + +BaselineJIT::~BaselineJIT() +{} + +void BaselineJIT::generate() +{ +// qDebug()<<"jitting" << function->name()->toQString(); + const char *code = reinterpret_cast(function->codeData); + uint len = function->compiledFunction->codeSize; + labels = collectLabelsInBytecode(code, len); + + as->generatePrologue(); + decode(code, len); + as->generateEpilogue(); + + as->link(function); +// qDebug()<<"done"; +} + +#define STORE_IP() as->storeInstructionPointer(instructionOffset()) +#define STORE_ACC() as->saveAccumulatorInFrame() + +void BaselineJIT::generate_Ret() +{ + as->ret(); +} + +void BaselineJIT::generate_Debug() { Q_UNREACHABLE(); } + +void BaselineJIT::generate_LoadConst(int index) +{ + as->loadConst(index); +} + +void BaselineJIT::generate_LoadZero() +{ + as->loadValue(Encode(int(0))); +} + +void BaselineJIT::generate_LoadTrue() +{ + as->loadValue(Encode(true)); +} + +void BaselineJIT::generate_LoadFalse() +{ + as->loadValue(Encode(false)); +} + +void BaselineJIT::generate_LoadNull() +{ + as->loadValue(Encode::null()); +} + +void BaselineJIT::generate_LoadUndefined() +{ + as->loadValue(Encode::undefined()); +} + +void BaselineJIT::generate_LoadInt(int value) +{ + //### + as->loadValue(Encode(value)); +} + +void BaselineJIT::generate_MoveConst(int constIndex, int destTemp) +{ + as->copyConst(constIndex, destTemp); +} + +void BaselineJIT::generate_LoadReg(int reg) +{ + as->loadReg(reg); +} + +void BaselineJIT::generate_StoreReg(int reg) +{ + as->storeReg(reg); +} + +void BaselineJIT::generate_MoveReg(int srcReg, int destReg) +{ + as->loadReg(srcReg); + as->storeReg(destReg); +} + +void BaselineJIT::generate_LoadLocal(int index) +{ + as->loadLocal(index); +} + +void BaselineJIT::generate_StoreLocal(int index) +{ + as->checkException(); + as->storeLocal(index); +} + +void BaselineJIT::generate_LoadScopedLocal(int scope, int index) +{ + as->loadLocal(index, scope); +} + +void BaselineJIT::generate_StoreScopedLocal(int scope, int index) +{ + as->checkException(); + as->storeLocal(index, scope); +} + +void BaselineJIT::generate_LoadRuntimeString(int stringId) +{ + as->loadString(stringId); +} + +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); + as->storeReg(destReg); +} + +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); +} + +void BaselineJIT::generate_LoadName(int name) +{ + STORE_IP(); + as->prepareCallWithArgCount(2); + as->passInt32AsArg(name, 1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(Runtime::method_loadName, Assembler::ResultInAccumulator); + as->checkException(); +} + +static ReturnedValue loadGlobalLookupHelper(ExecutionEngine *engine, QV4::Function *f, int index) +{ + QV4::Lookup *l = f->compilationUnit->runtimeLookups + index; + return l->globalGetter(l, engine); +} + +void BaselineJIT::generate_LoadGlobalLookup(int index) +{ + as->prepareCallWithArgCount(3); + as->passInt32AsArg(index, 2); + as->passFunctionAsArg(1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(loadGlobalLookupHelper, Assembler::ResultInAccumulator); + as->checkException(); +} + +void BaselineJIT::generate_StoreNameSloppy(int name) +{ + STORE_IP(); + STORE_ACC(); + as->prepareCallWithArgCount(3); + as->passAccumulatorAsArg(2); + as->passInt32AsArg(name, 1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(Runtime::method_storeNameSloppy, Assembler::IgnoreResult); + as->checkException(); +} + +void BaselineJIT::generate_StoreNameStrict(int name) +{ + STORE_IP(); + STORE_ACC(); + as->prepareCallWithArgCount(3); + as->passAccumulatorAsArg(2); + as->passInt32AsArg(name, 1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(Runtime::method_storeNameStrict, Assembler::IgnoreResult); + as->checkException(); +} + +void BaselineJIT::generate_LoadElement(int base, int index) +{ + STORE_IP(); + as->prepareCallWithArgCount(3); + as->passRegAsArg(index, 2); + as->passRegAsArg(base, 1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(Runtime::method_loadElement, Assembler::ResultInAccumulator); + as->checkException(); +} + +void BaselineJIT::generate_LoadElementA(int base) +{ + STORE_IP(); + STORE_ACC(); + as->prepareCallWithArgCount(3); + as->passAccumulatorAsArg(2); + as->passRegAsArg(base, 1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(Runtime::method_loadElement, Assembler::ResultInAccumulator); + as->checkException(); +} + +static void storeElementHelper(QV4::Function *f, const Value &base, const Value &index, const Value &value) +{ + auto engine = f->internalClass->engine; + if (!Runtime::method_storeElement(engine, base, index, value) && f->isStrict()) + engine->throwTypeError(); +} + +void BaselineJIT::generate_StoreElement(int base, int index) +{ + STORE_IP(); + STORE_ACC(); + as->prepareCallWithArgCount(4); + as->passAccumulatorAsArg(3); + as->passRegAsArg(index, 2); + as->passRegAsArg(base, 1); + as->passFunctionAsArg(0); + JIT_GENERATE_RUNTIME_CALL(storeElementHelper, Assembler::IgnoreResult); + as->checkException(); +} + +void BaselineJIT::generate_LoadProperty(int name, int base) +{ + STORE_IP(); + as->prepareCallWithArgCount(3); + as->passInt32AsArg(name, 2); + as->passRegAsArg(base, 1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(Runtime::method_loadProperty, Assembler::ResultInAccumulator); + as->checkException(); +} +void BaselineJIT::generate_LoadPropertyA(int name) +{ + STORE_IP(); + STORE_ACC(); + as->prepareCallWithArgCount(3); + as->passInt32AsArg(name, 2); + as->passAccumulatorAsArg(1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(Runtime::method_loadProperty, Assembler::ResultInAccumulator); + as->checkException(); +} + +static ReturnedValue getLookupHelper(ExecutionEngine *engine, QV4::Function *f, int index, const QV4::Value &base) +{ + QV4::Lookup *l = f->compilationUnit->runtimeLookups + index; + return l->getter(l, engine, base); +} + +void BaselineJIT::generate_GetLookup(int index, int base) +{ + STORE_IP(); + as->prepareCallWithArgCount(4); + as->passRegAsArg(base, 3); + as->passInt32AsArg(index, 2); + as->passFunctionAsArg(1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(getLookupHelper, Assembler::ResultInAccumulator); + as->checkException(); +} + +void BaselineJIT::generate_GetLookupA(int index) +{ + STORE_IP(); + STORE_ACC(); + as->prepareCallWithArgCount(4); + as->passAccumulatorAsArg(3); + as->passInt32AsArg(index, 2); + as->passFunctionAsArg(1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(getLookupHelper, Assembler::ResultInAccumulator); + as->checkException(); +} + +static void storePropertyHelper(QV4::Function *f, const Value &base, int name, const Value &value) +{ + auto engine = f->internalClass->engine; + if (!Runtime::method_storeProperty(engine, base, name, value) && f->isStrict()) + engine->throwTypeError(); +} + +void BaselineJIT::generate_StoreProperty(int name, int base) +{ + STORE_IP(); + STORE_ACC(); + as->prepareCallWithArgCount(4); + as->passAccumulatorAsArg(3); + as->passInt32AsArg(name, 2); + as->passRegAsArg(base, 1); + as->passFunctionAsArg(0); + JIT_GENERATE_RUNTIME_CALL(storePropertyHelper, Assembler::IgnoreResult); + as->checkException(); +} + +static void setLookupHelper(QV4::Function *f, int index, QV4::Value &base, const QV4::Value &value) +{ + ExecutionEngine *engine = f->internalClass->engine; + QV4::Lookup *l = f->compilationUnit->runtimeLookups + index; + if (!l->setter(l, engine, base, value) && f->isStrict()) + engine->throwTypeError(); +} + +void BaselineJIT::generate_SetLookup(int index, int base) +{ + STORE_IP(); + STORE_ACC(); + as->prepareCallWithArgCount(4); + as->passAccumulatorAsArg(3); + as->passRegAsArg(base, 2); + as->passInt32AsArg(index, 1); + as->passFunctionAsArg(0); + JIT_GENERATE_RUNTIME_CALL(setLookupHelper, Assembler::ResultInAccumulator); + as->checkException(); +} + +void BaselineJIT::generate_StoreScopeObjectProperty(int base, int propertyIndex) +{ + STORE_ACC(); + as->prepareCallWithArgCount(4); + as->passAccumulatorAsArg(3); + as->passInt32AsArg(propertyIndex, 2); + as->passRegAsArg(base, 1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(Runtime::method_storeQmlScopeObjectProperty, Assembler::IgnoreResult); + as->checkException(); +} + +void BaselineJIT::generate_StoreContextObjectProperty(int base, int propertyIndex) +{ + STORE_ACC(); + as->prepareCallWithArgCount(4); + as->passAccumulatorAsArg(3); + as->passInt32AsArg(propertyIndex, 2); + as->passRegAsArg(base, 1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(Runtime::method_storeQmlContextObjectProperty, Assembler::IgnoreResult); + as->checkException(); +} + +void BaselineJIT::generate_LoadScopeObjectProperty(int propertyIndex, int base, int captureRequired) +{ + STORE_IP(); + as->prepareCallWithArgCount(4); + as->passInt32AsArg(captureRequired, 3); + as->passInt32AsArg(propertyIndex, 2); + as->passRegAsArg(base, 1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(Runtime::method_loadQmlScopeObjectProperty, Assembler::ResultInAccumulator); + as->checkException(); +} + +void BaselineJIT::generate_LoadContextObjectProperty(int propertyIndex, int base, int captureRequired) +{ + STORE_IP(); + as->prepareCallWithArgCount(4); + as->passInt32AsArg(captureRequired, 3); + as->passInt32AsArg(propertyIndex, 2); + as->passRegAsArg(base, 1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(Runtime::method_loadQmlContextObjectProperty, Assembler::ResultInAccumulator); + as->checkException(); +} + +void BaselineJIT::generate_LoadIdObject(int index, int base) +{ + STORE_IP(); + as->prepareCallWithArgCount(3); + as->passInt32AsArg(index, 2); + as->passRegAsArg(base, 1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(Runtime::method_loadQmlIdObject, Assembler::ResultInAccumulator); + as->checkException(); +} + +void BaselineJIT::generate_Yield() +{ + // ##### + Q_UNREACHABLE(); +} + +void BaselineJIT::generate_Resume(int) +{ + // ##### + Q_UNREACHABLE(); +} + +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->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(Runtime::method_callValue, Assembler::ResultInAccumulator); + as->checkException(); +} + +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->passInt32AsArg(name, 2); + as->passRegAsArg(base, 1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(Runtime::method_callProperty, Assembler::ResultInAccumulator); + as->checkException(); +} + +void BaselineJIT::generate_CallPropertyLookup(int lookupIndex, int base, int argc, int argv) +{ + STORE_IP(); + as->prepareCallWithArgCount(5); + as->passInt32AsArg(argc, 4); + as->passRegAsArg(argv, 3); + as->passInt32AsArg(lookupIndex, 2); + as->passRegAsArg(base, 1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(Runtime::method_callPropertyLookup, Assembler::ResultInAccumulator); + as->checkException(); +} + +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->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(Runtime::method_callElement, Assembler::ResultInAccumulator); + as->checkException(); +} + +void BaselineJIT::generate_CallName(int name, int argc, int argv) +{ + STORE_IP(); + as->prepareCallWithArgCount(4); + as->passInt32AsArg(argc, 3); + as->passRegAsArg(argv, 2); + as->passInt32AsArg(name, 1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(Runtime::method_callName, Assembler::ResultInAccumulator); + as->checkException(); +} + +void BaselineJIT::generate_CallPossiblyDirectEval(int argc, int argv) +{ + STORE_IP(); + as->prepareCallWithArgCount(3); + as->passInt32AsArg(argc, 2); + as->passRegAsArg(argv, 1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(Runtime::method_callPossiblyDirectEval, Assembler::ResultInAccumulator); + as->checkException(); +} + +void BaselineJIT::generate_CallGlobalLookup(int index, int argc, int argv) +{ + STORE_IP(); + as->prepareCallWithArgCount(4); + as->passInt32AsArg(argc, 3); + as->passRegAsArg(argv, 2); + as->passInt32AsArg(index, 1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(Runtime::method_callGlobalLookup, Assembler::ResultInAccumulator); + as->checkException(); +} + +void BaselineJIT::generate_CallScopeObjectProperty(int propIdx, int base, int argc, int argv) +{ + STORE_IP(); + as->prepareCallWithArgCount(5); + as->passInt32AsArg(argc, 4); + as->passRegAsArg(argv, 3); + as->passInt32AsArg(propIdx, 2); + as->passRegAsArg(base, 1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(Runtime::method_callQmlScopeObjectProperty, Assembler::ResultInAccumulator); + as->checkException(); +} + +void BaselineJIT::generate_CallContextObjectProperty(int propIdx, int base, int argc, int argv) +{ + STORE_IP(); + as->prepareCallWithArgCount(5); + as->passInt32AsArg(argc, 4); + as->passRegAsArg(argv, 3); + as->passInt32AsArg(propIdx, 2); + as->passRegAsArg(base, 1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(Runtime::method_callQmlContextObjectProperty, Assembler::ResultInAccumulator); + as->checkException(); +} + +void BaselineJIT::generate_SetExceptionHandler(int offset) +{ + if (offset) + as->setExceptionHandler(instructionOffset() + offset); + else + as->clearExceptionHandler(); +} + +void BaselineJIT::generate_ThrowException() +{ + STORE_IP(); + STORE_ACC(); + as->prepareCallWithArgCount(2); + as->passAccumulatorAsArg(1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(Runtime::method_throwException, Assembler::IgnoreResult); + as->gotoCatchException(); +} + +void BaselineJIT::generate_GetException() { as->getException(); } +void BaselineJIT::generate_SetException() { as->setException(); } + +void BaselineJIT::generate_CreateCallContext() +{ + as->prepareCallWithArgCount(1); + as->passCppFrameAsArg(0); + JIT_GENERATE_RUNTIME_CALL(ExecutionContext::newCallContext, Assembler::IgnoreResult); // keeps result in return value register + as->storeHeapObject(CallData::Context); +} + +void BaselineJIT::generate_PushCatchContext(int index, int name) { as->pushCatchContext(index, name); } + +static void pushWithContextHelper(ExecutionEngine *engine, QV4::Value *stack) +{ + QV4::Value &accumulator = stack[CallData::Accumulator]; + accumulator = accumulator.toObject(engine); + if (engine->hasException) + return; + ExecutionContext *c = static_cast(stack + CallData::Context); + stack[CallData::Context] = Runtime::method_createWithContext(c, accumulator); +} + +void BaselineJIT::generate_PushWithContext() +{ + STORE_IP(); + as->saveAccumulatorInFrame(); + as->prepareCallWithArgCount(2); + as->passRegAsArg(0, 1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(pushWithContextHelper, Assembler::IgnoreResult); + as->checkException(); +} + +static void pushBlockContextHelper(QV4::Value *stack, int index) +{ + ExecutionContext *c = static_cast(stack + CallData::Context); + stack[CallData::Context] = Runtime::method_createBlockContext(c, index); +} + +void BaselineJIT::generate_PushBlockContext(int index) +{ + as->saveAccumulatorInFrame(); + as->prepareCallWithArgCount(2); + as->passInt32AsArg(index, 1); + as->passRegAsArg(0, 0); + JIT_GENERATE_RUNTIME_CALL(pushBlockContextHelper, Assembler::IgnoreResult); +} + +static void cloneBlockContextHelper(QV4::Value *contextSlot) +{ + *contextSlot = Runtime::method_cloneBlockContext(static_cast(contextSlot)); +} + +void BaselineJIT::generate_CloneBlockContext() +{ + as->saveAccumulatorInFrame(); + as->prepareCallWithArgCount(1); + as->passRegAsArg(CallData::Context, 0); + JIT_GENERATE_RUNTIME_CALL(cloneBlockContextHelper, Assembler::IgnoreResult); +} + +static void pushScriptContextHelper(QV4::Value *stack, ExecutionEngine *engine, int index) +{ + stack[CallData::Context] = Runtime::method_createScriptContext(engine, index); +} + +void BaselineJIT::generate_PushScriptContext(int index) +{ + as->saveAccumulatorInFrame(); + as->prepareCallWithArgCount(3); + as->passInt32AsArg(index, 2); + as->passEngineAsArg(1); + as->passRegAsArg(0, 0); + JIT_GENERATE_RUNTIME_CALL(pushScriptContextHelper, Assembler::IgnoreResult); +} + +static void popScriptContextHelper(QV4::Value *stack, ExecutionEngine *engine) +{ + stack[CallData::Context] = Runtime::method_popScriptContext(engine); +} + +void BaselineJIT::generate_PopScriptContext() +{ + as->saveAccumulatorInFrame(); + as->prepareCallWithArgCount(2); + as->passEngineAsArg(1); + as->passRegAsArg(0, 0); + JIT_GENERATE_RUNTIME_CALL(popScriptContextHelper, Assembler::IgnoreResult); +} + +void BaselineJIT::generate_PopContext() { as->popContext(); } + +void BaselineJIT::generate_GetIterator(int iterator) +{ + as->saveAccumulatorInFrame(); + as->prepareCallWithArgCount(3); + as->passInt32AsArg(iterator, 2); + as->passAccumulatorAsArg(1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(Runtime::method_getIterator, Assembler::ResultInAccumulator); + as->checkException(); +} + +void BaselineJIT::generate_IteratorNext(int value) +{ + as->saveAccumulatorInFrame(); + as->prepareCallWithArgCount(3); + as->passRegAsArg(value, 2); + as->passAccumulatorAsArg(1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(Runtime::method_iteratorNext, Assembler::ResultInAccumulator); + as->checkException(); +} + +void BaselineJIT::generate_IteratorClose(int done) +{ + as->saveAccumulatorInFrame(); + as->prepareCallWithArgCount(3); + as->passRegAsArg(done, 2); + as->passAccumulatorAsArg(1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(Runtime::method_iteratorClose, Assembler::ResultInAccumulator); + as->checkException(); +} + +void BaselineJIT::generate_DestructureRestElement() +{ + as->saveAccumulatorInFrame(); + as->prepareCallWithArgCount(2); + as->passAccumulatorAsArg(1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(Runtime::method_destructureRestElement, Assembler::ResultInAccumulator); + as->checkException(); +} + + + +static ReturnedValue deleteMemberHelper(QV4::Function *function, const QV4::Value &base, int member) +{ + auto engine = function->internalClass->engine; + if (!Runtime::method_deleteMember(engine, base, member)) { + if (function->isStrict()) + engine->throwTypeError(); + return Encode(false); + } else { + return Encode(true); + } +} + +void BaselineJIT::generate_DeleteMember(int member, int base) +{ + STORE_IP(); + as->prepareCallWithArgCount(3); + as->passInt32AsArg(member, 2); + as->passRegAsArg(base, 1); + as->passFunctionAsArg(0); + JIT_GENERATE_RUNTIME_CALL(deleteMemberHelper, Assembler::ResultInAccumulator); + as->checkException(); +} + +static ReturnedValue deleteSubscriptHelper(QV4::Function *function, const QV4::Value &base, const QV4::Value &index) +{ + auto engine = function->internalClass->engine; + if (!Runtime::method_deleteElement(engine, base, index)) { + if (function->isStrict()) + engine->throwTypeError(); + return Encode(false); + } else { + return Encode(true); + } +} + +void BaselineJIT::generate_DeleteSubscript(int base, int index) +{ + STORE_IP(); + as->prepareCallWithArgCount(3); + as->passRegAsArg(index, 2); + as->passRegAsArg(base, 1); + as->passFunctionAsArg(0); + JIT_GENERATE_RUNTIME_CALL(deleteSubscriptHelper, Assembler::ResultInAccumulator); + as->checkException(); +} + +static ReturnedValue deleteNameHelper(QV4::Function *function, int name) +{ + auto engine = function->internalClass->engine; + if (!Runtime::method_deleteName(engine, name)) { + if (function->isStrict()) + engine->throwTypeError(); + return Encode(false); + } else { + return Encode(true); + } +} + +void BaselineJIT::generate_DeleteName(int name) +{ + STORE_IP(); + as->prepareCallWithArgCount(2); + as->passInt32AsArg(name, 1); + as->passFunctionAsArg(0); + JIT_GENERATE_RUNTIME_CALL(deleteNameHelper, Assembler::ResultInAccumulator); + as->checkException(); +} + +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); +} + +void BaselineJIT::generate_TypeofValue() +{ + STORE_ACC(); + as->prepareCallWithArgCount(2); + as->passAccumulatorAsArg(1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(Runtime::method_typeofValue, Assembler::ResultInAccumulator); +} + +void BaselineJIT::generate_DeclareVar(int varName, int isDeletable) +{ + as->prepareCallWithArgCount(3); + as->passInt32AsArg(varName, 2); + as->passInt32AsArg(isDeletable, 1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(Runtime::method_declareVar, Assembler::IgnoreResult); +} + +void BaselineJIT::generate_DefineArray(int argc, int args) +{ + as->prepareCallWithArgCount(3); + as->passInt32AsArg(argc, 2); + as->passRegAsArg(args, 1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(Runtime::method_arrayLiteral, Assembler::ResultInAccumulator); +} + +void BaselineJIT::generate_DefineObjectLiteral(int internalClassId, int arrayValueCount, + int arrayGetterSetterCountAndFlags, int args) +{ + as->prepareCallWithArgCount(5); + as->passInt32AsArg(arrayGetterSetterCountAndFlags, 4); + as->passInt32AsArg(arrayValueCount, 3); + as->passInt32AsArg(internalClassId, 2); + as->passRegAsArg(args, 1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(Runtime::method_objectLiteral, Assembler::ResultInAccumulator); +} +void BaselineJIT::generate_CreateMappedArgumentsObject() +{ + as->prepareCallWithArgCount(1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(Runtime::method_createMappedArgumentsObject, + Assembler::ResultInAccumulator); +} + +void BaselineJIT::generate_CreateUnmappedArgumentsObject() +{ + as->prepareCallWithArgCount(1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(Runtime::method_createUnmappedArgumentsObject, + Assembler::ResultInAccumulator); +} + +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); +} + +static void convertThisToObjectHelper(ExecutionEngine *engine, Value *t) +{ + if (!t->isObject()) { + if (t->isNullOrUndefined()) { + *t = engine->globalObject->asReturnedValue(); + } else { + *t = t->toObject(engine)->asReturnedValue(); + } + } +} + +void BaselineJIT::generate_ConvertThisToObject() +{ + as->prepareCallWithArgCount(2); + as->passRegAsArg(CallData::This, 1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(convertThisToObjectHelper, Assembler::IgnoreResult); + as->checkException(); +} + +static ReturnedValue ToObjectHelper(ExecutionEngine *engine, const Value &obj) +{ + if (obj.isObject()) + return obj.asReturnedValue(); + + return obj.toObject(engine)->asReturnedValue(); +} + +void BaselineJIT::generate_ToObject() +{ + STORE_ACC(); + as->prepareCallWithArgCount(2); + as->passAccumulatorAsArg(1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(ToObjectHelper, Assembler::ResultInAccumulator); + as->checkException(); + +} + +void BaselineJIT::generate_Construct(int func, int argc, int argv) +{ + STORE_IP(); + as->prepareCallWithArgCount(4); + as->passInt32AsArg(argc, 3); + as->passRegAsArg(argv, 2); + as->passRegAsArg(func, 1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(Runtime::method_construct, Assembler::ResultInAccumulator); + as->checkException(); +} + +void BaselineJIT::generate_Jump(int offset) { as->jump(instructionOffset() + offset); } +void BaselineJIT::generate_JumpTrue(int offset) { as->jumpTrue(instructionOffset() + offset); } +void BaselineJIT::generate_JumpFalse(int offset) { as->jumpFalse(instructionOffset() + offset); } +void BaselineJIT::generate_JumpNotUndefined(int offset) { as->jumpNotUndefined(instructionOffset() + offset); } +void BaselineJIT::generate_JumpEmpty(int offset) { as->jumpEmpty(instructionOffset() + offset); } + +void BaselineJIT::generate_CmpEqNull() { as->cmpeqNull(); } +void BaselineJIT::generate_CmpNeNull() { as->cmpneNull(); } +void BaselineJIT::generate_CmpEqInt(int lhs) { as->cmpeqInt(lhs); } +void BaselineJIT::generate_CmpNeInt(int lhs) { as->cmpneInt(lhs); } +void BaselineJIT::generate_CmpEq(int lhs) { as->cmpeq(lhs); } +void BaselineJIT::generate_CmpNe(int lhs) { as->cmpne(lhs); } +void BaselineJIT::generate_CmpGt(int lhs) { as->cmpgt(lhs); } +void BaselineJIT::generate_CmpGe(int lhs) { as->cmpge(lhs); } +void BaselineJIT::generate_CmpLt(int lhs) { as->cmplt(lhs); } +void BaselineJIT::generate_CmpLe(int lhs) { as->cmple(lhs); } +void BaselineJIT::generate_CmpStrictEqual(int lhs) { as->cmpStrictEqual(lhs); } +void BaselineJIT::generate_CmpStrictNotEqual(int lhs) { as->cmpStrictNotEqual(lhs); } + +void BaselineJIT::generate_CmpIn(int lhs) +{ + STORE_ACC(); + as->prepareCallWithArgCount(3); + as->passAccumulatorAsArg(2); + as->passRegAsArg(lhs, 1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(Runtime::method_in, Assembler::ResultInAccumulator); + as->checkException(); +} + +void BaselineJIT::generate_CmpInstanceOf(int lhs) +{ + STORE_ACC(); + as->prepareCallWithArgCount(3); + as->passAccumulatorAsArg(2); + as->passRegAsArg(lhs, 1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(Runtime::method_instanceof, Assembler::ResultInAccumulator); + as->checkException(); +} + +void BaselineJIT::generate_JumpStrictEqualStackSlotInt(int lhs, int rhs, int offset) +{ + as->jumpStrictEqualStackSlotInt(lhs, rhs, instructionOffset() + offset); +} + +void BaselineJIT::generate_JumpStrictNotEqualStackSlotInt(int lhs, int rhs, int offset) +{ + as->jumpStrictNotEqualStackSlotInt(lhs, rhs, instructionOffset() + offset); +} + +void BaselineJIT::generate_UNot() { as->unot(); } +void BaselineJIT::generate_UPlus() { as->toNumber(); } +void BaselineJIT::generate_UMinus() { as->uminus(); } +void BaselineJIT::generate_UCompl() { as->ucompl(); } +void BaselineJIT::generate_Increment() { as->inc(); } +void BaselineJIT::generate_Decrement() { as->dec(); } +void BaselineJIT::generate_Add(int lhs) { as->add(lhs); } + +void BaselineJIT::generate_BitAnd(int lhs) { as->bitAnd(lhs); } +void BaselineJIT::generate_BitOr(int lhs) { as->bitOr(lhs); } +void BaselineJIT::generate_BitXor(int lhs) { as->bitXor(lhs); } +void BaselineJIT::generate_UShr(int lhs) { as->ushr(lhs); } +void BaselineJIT::generate_Shr(int lhs) { as->shr(lhs); } +void BaselineJIT::generate_Shl(int lhs) { as->shl(lhs); } + +void BaselineJIT::generate_BitAndConst(int rhs) { as->bitAndConst(rhs); } +void BaselineJIT::generate_BitOrConst(int rhs) { as->bitOrConst(rhs); } +void BaselineJIT::generate_BitXorConst(int rhs) { as->bitXorConst(rhs); } +void BaselineJIT::generate_UShrConst(int rhs) { as->ushrConst(rhs); } +void BaselineJIT::generate_ShrConst(int rhs) { as->shrConst(rhs); } +void BaselineJIT::generate_ShlConst(int rhs) { as->shlConst(rhs); } + +static ReturnedValue expHelper(const Value &base, const Value &exp) +{ + double b = base.toNumber(); + double e = exp.toNumber(); + return QV4::Encode(pow(b,e)); +} + +void BaselineJIT::generate_Exp(int lhs) { + STORE_IP(); + STORE_ACC(); + as->prepareCallWithArgCount(2); + as->passAccumulatorAsArg(1); + as->passRegAsArg(lhs, 0); + JIT_GENERATE_RUNTIME_CALL(expHelper, Assembler::ResultInAccumulator); + as->checkException(); +} +void BaselineJIT::generate_Mul(int lhs) { as->mul(lhs); } +void BaselineJIT::generate_Div(int lhs) { as->div(lhs); } +void BaselineJIT::generate_Mod(int lhs) { as->mod(lhs); } +void BaselineJIT::generate_Sub(int lhs) { as->sub(lhs); } + +//void BaselineJIT::generate_BinopContext(int alu, int lhs) +//{ +// auto engine = function->internalClass->engine; +// void *op = engine->runtime.runtimeMethods[alu]; +// STORE_ACC(); +// as->passAccumulatorAsArg(2); +// as->passRegAsArg(lhs, 1); +// as->passEngineAsArg(0); +// as->callRuntime("binopContext", op, Assembler::ResultInAccumulator); +// as->checkException(); +//} + +void BaselineJIT::generate_LoadQmlContext(int result) +{ + as->prepareCallWithArgCount(1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(Runtime::method_loadQmlContext, Assembler::ResultInAccumulator); + as->storeReg(result); +} + +void BaselineJIT::generate_LoadQmlImportedScripts(int result) +{ + as->prepareCallWithArgCount(1); + as->passEngineAsArg(0); + JIT_GENERATE_RUNTIME_CALL(Runtime::method_loadQmlImportedScripts, Assembler::ResultInAccumulator); + as->storeReg(result); +} + +void BaselineJIT::startInstruction(Instr::Type /*instr*/) +{ + if (hasLabel()) + as->addLabel(instructionOffset()); +} + +void BaselineJIT::endInstruction(Instr::Type instr) +{ + Q_UNUSED(instr); +} + +#endif // V4_ENABLE_JIT diff --git a/src/qml/jit/qv4baselinejit_p.h b/src/qml/jit/qv4baselinejit_p.h new file mode 100644 index 0000000000..12a3f27e1b --- /dev/null +++ b/src/qml/jit/qv4baselinejit_p.h @@ -0,0 +1,232 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QV4JIT_P_H +#define QV4JIT_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 +#include +#include +#include + +//QT_REQUIRE_CONFIG(qml_jit); + +QT_BEGIN_NAMESPACE + +namespace QV4 { +namespace JIT { + +class Assembler; + +#ifdef V4_ENABLE_JIT +class BaselineJIT final: public Moth::ByteCodeHandler +{ +public: + BaselineJIT(QV4::Function *); + virtual ~BaselineJIT() Q_DECL_OVERRIDE; + + void generate(); + + void generate_Ret() override; + void generate_Debug() override; + void generate_LoadConst(int index) override; + void generate_LoadZero() override; + void generate_LoadTrue() override; + void generate_LoadFalse() override; + void generate_LoadNull() override; + void generate_LoadUndefined() override; + void generate_LoadInt(int value) override; + void generate_MoveConst(int constIndex, int destTemp) override; + void generate_LoadReg(int reg) override; + void generate_StoreReg(int reg) override; + void generate_MoveReg(int srcReg, int destReg) override; + void generate_LoadLocal(int index) override; + void generate_StoreLocal(int index) override; + void generate_LoadScopedLocal(int scope, int index) override; + void generate_StoreScopedLocal(int scope, int index) override; + void generate_LoadRuntimeString(int stringId) override; + void generate_MoveRegExp(int regExpId, int destReg) override; + void generate_LoadClosure(int value) override; + void generate_LoadName(int name) override; + void generate_LoadGlobalLookup(int index) override; + void generate_StoreNameSloppy(int name) override; + void generate_StoreNameStrict(int name) override; + void generate_LoadElement(int base, int index) override; + void generate_LoadElementA(int base) override; + void generate_StoreElement(int base, int index) override; + void generate_LoadProperty(int name, int base) override; + void generate_LoadPropertyA(int name) override; + void generate_GetLookup(int index, int base) override; + void generate_GetLookupA(int index) override; + void generate_StoreProperty(int name, int base) override; + void generate_SetLookup(int index, int base) override; + void generate_StoreScopeObjectProperty(int base, + int propertyIndex) override; + void generate_StoreContextObjectProperty(int base, + int propertyIndex) override; + void generate_LoadScopeObjectProperty(int propertyIndex, int base, + int captureRequired) override; + void generate_LoadContextObjectProperty(int propertyIndex, int base, + int captureRequired) override; + void generate_LoadIdObject(int index, int base) override; + void generate_Yield() override; + void generate_Resume(int) override; + + void generate_CallValue(int name, int argc, int argv) override; + void generate_CallProperty(int name, int base, int argc, int argv) override; + void generate_CallPropertyLookup(int lookupIndex, int base, int argc, int argv) override; + void generate_CallElement(int base, int index, int argc, int argv) override; + void generate_CallName(int name, int argc, int argv) override; + void generate_CallPossiblyDirectEval(int argc, int argv) override; + void generate_CallGlobalLookup(int index, int argc, int argv) override; + void generate_CallScopeObjectProperty(int propIdx, int base, int argc, int argv) override; + void generate_CallContextObjectProperty(int propIdx, int base, int argc, int argv) override; + void generate_SetExceptionHandler(int offset) override; + void generate_ThrowException() override; + void generate_GetException() override; + void generate_SetException() override; + void generate_CreateCallContext() override; + void generate_PushCatchContext(int index, int name) override; + void generate_PushWithContext() override; + void generate_PushBlockContext(int index) override; + void generate_CloneBlockContext() override; + void generate_PushScriptContext(int index) override; + void generate_PopScriptContext() override; + void generate_PopContext() override; + void generate_GetIterator(int iterator) override; + void generate_IteratorNext(int value) override; + void generate_IteratorClose(int done) override; + void generate_DestructureRestElement() override; + void generate_DeleteMember(int member, int base) override; + void generate_DeleteSubscript(int base, int index) override; + void generate_DeleteName(int name) override; + void generate_TypeofName(int name) override; + void generate_TypeofValue() override; + void generate_DeclareVar(int varName, int isDeletable) override; + void generate_DefineArray(int argc, int args) override; + void generate_DefineObjectLiteral(int internalClassId, int arrayValueCount, + int arrayGetterSetterCountAndFlags, + int args) override; + void generate_CreateMappedArgumentsObject() override; + void generate_CreateUnmappedArgumentsObject() override; + void generate_CreateRestParameter(int argIndex) override; + void generate_ConvertThisToObject() override; + void generate_ToObject() override; + void generate_Construct(int func, int argc, int argv) override; + void generate_Jump(int offset) override; + void generate_JumpTrue(int offset) override; + void generate_JumpFalse(int offset) override; + void generate_JumpNotUndefined(int offset) override; + void generate_JumpEmpty(int offset) override; + void generate_CmpEqNull() override; + void generate_CmpNeNull() override; + void generate_CmpEqInt(int lhs) override; + void generate_CmpNeInt(int lhs) override; + void generate_CmpEq(int lhs) override; + void generate_CmpNe(int lhs) override; + void generate_CmpGt(int lhs) override; + void generate_CmpGe(int lhs) override; + void generate_CmpLt(int lhs) override; + void generate_CmpLe(int lhs) override; + void generate_CmpStrictEqual(int lhs) override; + void generate_CmpStrictNotEqual(int lhs) override; + void generate_CmpIn(int lhs) override; + void generate_CmpInstanceOf(int lhs) override; + void generate_JumpStrictEqualStackSlotInt(int lhs, int rhs, + int offset) override; + void generate_JumpStrictNotEqualStackSlotInt(int lhs, int rhs, + int offset) override; + void generate_UNot() override; + void generate_UPlus() override; + void generate_UMinus() override; + void generate_UCompl() override; + void generate_Increment() override; + void generate_Decrement() override; + void generate_Add(int lhs) override; + void generate_BitAnd(int lhs) override; + void generate_BitOr(int lhs) override; + void generate_BitXor(int lhs) override; + void generate_UShr(int lhs) override; + void generate_Shr(int lhs) override; + void generate_Shl(int lhs) override; + void generate_BitAndConst(int rhs) override; + void generate_BitOrConst(int rhs) override; + void generate_BitXorConst(int rhs) override; + void generate_UShrConst(int rhs) override; + void generate_ShrConst(int rhs) override; + void generate_ShlConst(int rhs) override; + void generate_Exp(int lhs) override; + void generate_Mul(int lhs) override; + void generate_Div(int lhs) override; + void generate_Mod(int lhs) override; + void generate_Sub(int lhs) override; + void generate_LoadQmlContext(int result) override; + void generate_LoadQmlImportedScripts(int result) override; + + void startInstruction(Moth::Instr::Type instr) override; + void endInstruction(Moth::Instr::Type instr) override; + +protected: + bool hasLabel() const + { return std::find(labels.cbegin(), labels.cend(), instructionOffset()) != labels.cend(); } + +private: + QV4::Function *function; + QScopedPointer as; + std::vector labels; +}; +#endif // V4_ENABLE_JIT + +} // namespace JIT +} // namespace QV4 + +QT_END_NAMESPACE + +#endif // QV4JIT_P_H diff --git a/src/qml/jit/qv4jit.cpp b/src/qml/jit/qv4jit.cpp deleted file mode 100644 index e9151599f6..0000000000 --- a/src/qml/jit/qv4jit.cpp +++ /dev/null @@ -1,1035 +0,0 @@ -/**************************************************************************** -** -** 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 "qv4jit_p.h" -#include "qv4assembler_p.h" -#include -#include - -#ifdef V4_ENABLE_JIT - -QT_USE_NAMESPACE -using namespace QV4; -using namespace QV4::JIT; -using namespace QV4::Moth; - -BaselineJIT::BaselineJIT(Function *function) - : function(function) - , as(new Assembler(function->compilationUnit->constants)) -{} - -BaselineJIT::~BaselineJIT() -{} - -void BaselineJIT::generate() -{ -// qDebug()<<"jitting" << function->name()->toQString(); - const char *code = reinterpret_cast(function->codeData); - uint len = function->compiledFunction->codeSize; - labels = collectLabelsInBytecode(code, len); - - as->generatePrologue(); - decode(code, len); - as->generateEpilogue(); - - as->link(function); -// qDebug()<<"done"; -} - -#define STORE_IP() as->storeInstructionPointer(instructionOffset()) -#define STORE_ACC() as->saveAccumulatorInFrame() - -void BaselineJIT::generate_Ret() -{ - as->ret(); -} - -void BaselineJIT::generate_Debug() { Q_UNREACHABLE(); } - -void BaselineJIT::generate_LoadConst(int index) -{ - as->loadConst(index); -} - -void BaselineJIT::generate_LoadZero() -{ - as->loadValue(Encode(int(0))); -} - -void BaselineJIT::generate_LoadTrue() -{ - as->loadValue(Encode(true)); -} - -void BaselineJIT::generate_LoadFalse() -{ - as->loadValue(Encode(false)); -} - -void BaselineJIT::generate_LoadNull() -{ - as->loadValue(Encode::null()); -} - -void BaselineJIT::generate_LoadUndefined() -{ - as->loadValue(Encode::undefined()); -} - -void BaselineJIT::generate_LoadInt(int value) -{ - //### - as->loadValue(Encode(value)); -} - -void BaselineJIT::generate_MoveConst(int constIndex, int destTemp) -{ - as->copyConst(constIndex, destTemp); -} - -void BaselineJIT::generate_LoadReg(int reg) -{ - as->loadReg(reg); -} - -void BaselineJIT::generate_StoreReg(int reg) -{ - as->storeReg(reg); -} - -void BaselineJIT::generate_MoveReg(int srcReg, int destReg) -{ - as->loadReg(srcReg); - as->storeReg(destReg); -} - -void BaselineJIT::generate_LoadLocal(int index) -{ - as->loadLocal(index); -} - -void BaselineJIT::generate_StoreLocal(int index) -{ - as->checkException(); - as->storeLocal(index); -} - -void BaselineJIT::generate_LoadScopedLocal(int scope, int index) -{ - as->loadLocal(index, scope); -} - -void BaselineJIT::generate_StoreScopedLocal(int scope, int index) -{ - as->checkException(); - as->storeLocal(index, scope); -} - -void BaselineJIT::generate_LoadRuntimeString(int stringId) -{ - as->loadString(stringId); -} - -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); - as->storeReg(destReg); -} - -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); -} - -void BaselineJIT::generate_LoadName(int name) -{ - STORE_IP(); - as->prepareCallWithArgCount(2); - as->passInt32AsArg(name, 1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(Runtime::method_loadName, Assembler::ResultInAccumulator); - as->checkException(); -} - -static ReturnedValue loadGlobalLookupHelper(ExecutionEngine *engine, QV4::Function *f, int index) -{ - QV4::Lookup *l = f->compilationUnit->runtimeLookups + index; - return l->globalGetter(l, engine); -} - -void BaselineJIT::generate_LoadGlobalLookup(int index) -{ - as->prepareCallWithArgCount(3); - as->passInt32AsArg(index, 2); - as->passFunctionAsArg(1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(loadGlobalLookupHelper, Assembler::ResultInAccumulator); - as->checkException(); -} - -void BaselineJIT::generate_StoreNameSloppy(int name) -{ - STORE_IP(); - STORE_ACC(); - as->prepareCallWithArgCount(3); - as->passAccumulatorAsArg(2); - as->passInt32AsArg(name, 1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(Runtime::method_storeNameSloppy, Assembler::IgnoreResult); - as->checkException(); -} - -void BaselineJIT::generate_StoreNameStrict(int name) -{ - STORE_IP(); - STORE_ACC(); - as->prepareCallWithArgCount(3); - as->passAccumulatorAsArg(2); - as->passInt32AsArg(name, 1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(Runtime::method_storeNameStrict, Assembler::IgnoreResult); - as->checkException(); -} - -void BaselineJIT::generate_LoadElement(int base, int index) -{ - STORE_IP(); - as->prepareCallWithArgCount(3); - as->passRegAsArg(index, 2); - as->passRegAsArg(base, 1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(Runtime::method_loadElement, Assembler::ResultInAccumulator); - as->checkException(); -} - -void BaselineJIT::generate_LoadElementA(int base) -{ - STORE_IP(); - STORE_ACC(); - as->prepareCallWithArgCount(3); - as->passAccumulatorAsArg(2); - as->passRegAsArg(base, 1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(Runtime::method_loadElement, Assembler::ResultInAccumulator); - as->checkException(); -} - -static void storeElementHelper(QV4::Function *f, const Value &base, const Value &index, const Value &value) -{ - auto engine = f->internalClass->engine; - if (!Runtime::method_storeElement(engine, base, index, value) && f->isStrict()) - engine->throwTypeError(); -} - -void BaselineJIT::generate_StoreElement(int base, int index) -{ - STORE_IP(); - STORE_ACC(); - as->prepareCallWithArgCount(4); - as->passAccumulatorAsArg(3); - as->passRegAsArg(index, 2); - as->passRegAsArg(base, 1); - as->passFunctionAsArg(0); - JIT_GENERATE_RUNTIME_CALL(storeElementHelper, Assembler::IgnoreResult); - as->checkException(); -} - -void BaselineJIT::generate_LoadProperty(int name, int base) -{ - STORE_IP(); - as->prepareCallWithArgCount(3); - as->passInt32AsArg(name, 2); - as->passRegAsArg(base, 1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(Runtime::method_loadProperty, Assembler::ResultInAccumulator); - as->checkException(); -} -void BaselineJIT::generate_LoadPropertyA(int name) -{ - STORE_IP(); - STORE_ACC(); - as->prepareCallWithArgCount(3); - as->passInt32AsArg(name, 2); - as->passAccumulatorAsArg(1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(Runtime::method_loadProperty, Assembler::ResultInAccumulator); - as->checkException(); -} - -static ReturnedValue getLookupHelper(ExecutionEngine *engine, QV4::Function *f, int index, const QV4::Value &base) -{ - QV4::Lookup *l = f->compilationUnit->runtimeLookups + index; - return l->getter(l, engine, base); -} - -void BaselineJIT::generate_GetLookup(int index, int base) -{ - STORE_IP(); - as->prepareCallWithArgCount(4); - as->passRegAsArg(base, 3); - as->passInt32AsArg(index, 2); - as->passFunctionAsArg(1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(getLookupHelper, Assembler::ResultInAccumulator); - as->checkException(); -} - -void BaselineJIT::generate_GetLookupA(int index) -{ - STORE_IP(); - STORE_ACC(); - as->prepareCallWithArgCount(4); - as->passAccumulatorAsArg(3); - as->passInt32AsArg(index, 2); - as->passFunctionAsArg(1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(getLookupHelper, Assembler::ResultInAccumulator); - as->checkException(); -} - -static void storePropertyHelper(QV4::Function *f, const Value &base, int name, const Value &value) -{ - auto engine = f->internalClass->engine; - if (!Runtime::method_storeProperty(engine, base, name, value) && f->isStrict()) - engine->throwTypeError(); -} - -void BaselineJIT::generate_StoreProperty(int name, int base) -{ - STORE_IP(); - STORE_ACC(); - as->prepareCallWithArgCount(4); - as->passAccumulatorAsArg(3); - as->passInt32AsArg(name, 2); - as->passRegAsArg(base, 1); - as->passFunctionAsArg(0); - JIT_GENERATE_RUNTIME_CALL(storePropertyHelper, Assembler::IgnoreResult); - as->checkException(); -} - -static void setLookupHelper(QV4::Function *f, int index, QV4::Value &base, const QV4::Value &value) -{ - ExecutionEngine *engine = f->internalClass->engine; - QV4::Lookup *l = f->compilationUnit->runtimeLookups + index; - if (!l->setter(l, engine, base, value) && f->isStrict()) - engine->throwTypeError(); -} - -void BaselineJIT::generate_SetLookup(int index, int base) -{ - STORE_IP(); - STORE_ACC(); - as->prepareCallWithArgCount(4); - as->passAccumulatorAsArg(3); - as->passRegAsArg(base, 2); - as->passInt32AsArg(index, 1); - as->passFunctionAsArg(0); - JIT_GENERATE_RUNTIME_CALL(setLookupHelper, Assembler::ResultInAccumulator); - as->checkException(); -} - -void BaselineJIT::generate_StoreScopeObjectProperty(int base, int propertyIndex) -{ - STORE_ACC(); - as->prepareCallWithArgCount(4); - as->passAccumulatorAsArg(3); - as->passInt32AsArg(propertyIndex, 2); - as->passRegAsArg(base, 1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(Runtime::method_storeQmlScopeObjectProperty, Assembler::IgnoreResult); - as->checkException(); -} - -void BaselineJIT::generate_StoreContextObjectProperty(int base, int propertyIndex) -{ - STORE_ACC(); - as->prepareCallWithArgCount(4); - as->passAccumulatorAsArg(3); - as->passInt32AsArg(propertyIndex, 2); - as->passRegAsArg(base, 1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(Runtime::method_storeQmlContextObjectProperty, Assembler::IgnoreResult); - as->checkException(); -} - -void BaselineJIT::generate_LoadScopeObjectProperty(int propertyIndex, int base, int captureRequired) -{ - STORE_IP(); - as->prepareCallWithArgCount(4); - as->passInt32AsArg(captureRequired, 3); - as->passInt32AsArg(propertyIndex, 2); - as->passRegAsArg(base, 1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(Runtime::method_loadQmlScopeObjectProperty, Assembler::ResultInAccumulator); - as->checkException(); -} - -void BaselineJIT::generate_LoadContextObjectProperty(int propertyIndex, int base, int captureRequired) -{ - STORE_IP(); - as->prepareCallWithArgCount(4); - as->passInt32AsArg(captureRequired, 3); - as->passInt32AsArg(propertyIndex, 2); - as->passRegAsArg(base, 1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(Runtime::method_loadQmlContextObjectProperty, Assembler::ResultInAccumulator); - as->checkException(); -} - -void BaselineJIT::generate_LoadIdObject(int index, int base) -{ - STORE_IP(); - as->prepareCallWithArgCount(3); - as->passInt32AsArg(index, 2); - as->passRegAsArg(base, 1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(Runtime::method_loadQmlIdObject, Assembler::ResultInAccumulator); - as->checkException(); -} - -void BaselineJIT::generate_Yield() -{ - // ##### - Q_UNREACHABLE(); -} - -void BaselineJIT::generate_Resume(int) -{ - // ##### - Q_UNREACHABLE(); -} - -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->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(Runtime::method_callValue, Assembler::ResultInAccumulator); - as->checkException(); -} - -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->passInt32AsArg(name, 2); - as->passRegAsArg(base, 1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(Runtime::method_callProperty, Assembler::ResultInAccumulator); - as->checkException(); -} - -void BaselineJIT::generate_CallPropertyLookup(int lookupIndex, int base, int argc, int argv) -{ - STORE_IP(); - as->prepareCallWithArgCount(5); - as->passInt32AsArg(argc, 4); - as->passRegAsArg(argv, 3); - as->passInt32AsArg(lookupIndex, 2); - as->passRegAsArg(base, 1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(Runtime::method_callPropertyLookup, Assembler::ResultInAccumulator); - as->checkException(); -} - -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->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(Runtime::method_callElement, Assembler::ResultInAccumulator); - as->checkException(); -} - -void BaselineJIT::generate_CallName(int name, int argc, int argv) -{ - STORE_IP(); - as->prepareCallWithArgCount(4); - as->passInt32AsArg(argc, 3); - as->passRegAsArg(argv, 2); - as->passInt32AsArg(name, 1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(Runtime::method_callName, Assembler::ResultInAccumulator); - as->checkException(); -} - -void BaselineJIT::generate_CallPossiblyDirectEval(int argc, int argv) -{ - STORE_IP(); - as->prepareCallWithArgCount(3); - as->passInt32AsArg(argc, 2); - as->passRegAsArg(argv, 1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(Runtime::method_callPossiblyDirectEval, Assembler::ResultInAccumulator); - as->checkException(); -} - -void BaselineJIT::generate_CallGlobalLookup(int index, int argc, int argv) -{ - STORE_IP(); - as->prepareCallWithArgCount(4); - as->passInt32AsArg(argc, 3); - as->passRegAsArg(argv, 2); - as->passInt32AsArg(index, 1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(Runtime::method_callGlobalLookup, Assembler::ResultInAccumulator); - as->checkException(); -} - -void BaselineJIT::generate_CallScopeObjectProperty(int propIdx, int base, int argc, int argv) -{ - STORE_IP(); - as->prepareCallWithArgCount(5); - as->passInt32AsArg(argc, 4); - as->passRegAsArg(argv, 3); - as->passInt32AsArg(propIdx, 2); - as->passRegAsArg(base, 1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(Runtime::method_callQmlScopeObjectProperty, Assembler::ResultInAccumulator); - as->checkException(); -} - -void BaselineJIT::generate_CallContextObjectProperty(int propIdx, int base, int argc, int argv) -{ - STORE_IP(); - as->prepareCallWithArgCount(5); - as->passInt32AsArg(argc, 4); - as->passRegAsArg(argv, 3); - as->passInt32AsArg(propIdx, 2); - as->passRegAsArg(base, 1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(Runtime::method_callQmlContextObjectProperty, Assembler::ResultInAccumulator); - as->checkException(); -} - -void BaselineJIT::generate_SetExceptionHandler(int offset) -{ - if (offset) - as->setExceptionHandler(instructionOffset() + offset); - else - as->clearExceptionHandler(); -} - -void BaselineJIT::generate_ThrowException() -{ - STORE_IP(); - STORE_ACC(); - as->prepareCallWithArgCount(2); - as->passAccumulatorAsArg(1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(Runtime::method_throwException, Assembler::IgnoreResult); - as->gotoCatchException(); -} - -void BaselineJIT::generate_GetException() { as->getException(); } -void BaselineJIT::generate_SetException() { as->setException(); } - -void BaselineJIT::generate_CreateCallContext() -{ - as->prepareCallWithArgCount(1); - as->passCppFrameAsArg(0); - JIT_GENERATE_RUNTIME_CALL(ExecutionContext::newCallContext, Assembler::IgnoreResult); // keeps result in return value register - as->storeHeapObject(CallData::Context); -} - -void BaselineJIT::generate_PushCatchContext(int index, int name) { as->pushCatchContext(index, name); } - -static void pushWithContextHelper(ExecutionEngine *engine, QV4::Value *stack) -{ - QV4::Value &accumulator = stack[CallData::Accumulator]; - accumulator = accumulator.toObject(engine); - if (engine->hasException) - return; - ExecutionContext *c = static_cast(stack + CallData::Context); - stack[CallData::Context] = Runtime::method_createWithContext(c, accumulator); -} - -void BaselineJIT::generate_PushWithContext() -{ - STORE_IP(); - as->saveAccumulatorInFrame(); - as->prepareCallWithArgCount(2); - as->passRegAsArg(0, 1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(pushWithContextHelper, Assembler::IgnoreResult); - as->checkException(); -} - -static void pushBlockContextHelper(QV4::Value *stack, int index) -{ - ExecutionContext *c = static_cast(stack + CallData::Context); - stack[CallData::Context] = Runtime::method_createBlockContext(c, index); -} - -void BaselineJIT::generate_PushBlockContext(int index) -{ - as->saveAccumulatorInFrame(); - as->prepareCallWithArgCount(2); - as->passInt32AsArg(index, 1); - as->passRegAsArg(0, 0); - JIT_GENERATE_RUNTIME_CALL(pushBlockContextHelper, Assembler::IgnoreResult); -} - -static void cloneBlockContextHelper(QV4::Value *contextSlot) -{ - *contextSlot = Runtime::method_cloneBlockContext(static_cast(contextSlot)); -} - -void BaselineJIT::generate_CloneBlockContext() -{ - as->saveAccumulatorInFrame(); - as->prepareCallWithArgCount(1); - as->passRegAsArg(CallData::Context, 0); - JIT_GENERATE_RUNTIME_CALL(cloneBlockContextHelper, Assembler::IgnoreResult); -} - -static void pushScriptContextHelper(QV4::Value *stack, ExecutionEngine *engine, int index) -{ - stack[CallData::Context] = Runtime::method_createScriptContext(engine, index); -} - -void BaselineJIT::generate_PushScriptContext(int index) -{ - as->saveAccumulatorInFrame(); - as->prepareCallWithArgCount(3); - as->passInt32AsArg(index, 2); - as->passEngineAsArg(1); - as->passRegAsArg(0, 0); - JIT_GENERATE_RUNTIME_CALL(pushScriptContextHelper, Assembler::IgnoreResult); -} - -static void popScriptContextHelper(QV4::Value *stack, ExecutionEngine *engine) -{ - stack[CallData::Context] = Runtime::method_popScriptContext(engine); -} - -void BaselineJIT::generate_PopScriptContext() -{ - as->saveAccumulatorInFrame(); - as->prepareCallWithArgCount(2); - as->passEngineAsArg(1); - as->passRegAsArg(0, 0); - JIT_GENERATE_RUNTIME_CALL(popScriptContextHelper, Assembler::IgnoreResult); -} - -void BaselineJIT::generate_PopContext() { as->popContext(); } - -void BaselineJIT::generate_GetIterator(int iterator) -{ - as->saveAccumulatorInFrame(); - as->prepareCallWithArgCount(3); - as->passInt32AsArg(iterator, 2); - as->passAccumulatorAsArg(1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(Runtime::method_getIterator, Assembler::ResultInAccumulator); - as->checkException(); -} - -void BaselineJIT::generate_IteratorNext(int value) -{ - as->saveAccumulatorInFrame(); - as->prepareCallWithArgCount(3); - as->passRegAsArg(value, 2); - as->passAccumulatorAsArg(1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(Runtime::method_iteratorNext, Assembler::ResultInAccumulator); - as->checkException(); -} - -void BaselineJIT::generate_IteratorClose(int done) -{ - as->saveAccumulatorInFrame(); - as->prepareCallWithArgCount(3); - as->passRegAsArg(done, 2); - as->passAccumulatorAsArg(1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(Runtime::method_iteratorClose, Assembler::ResultInAccumulator); - as->checkException(); -} - -void BaselineJIT::generate_DestructureRestElement() -{ - as->saveAccumulatorInFrame(); - as->prepareCallWithArgCount(2); - as->passAccumulatorAsArg(1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(Runtime::method_destructureRestElement, Assembler::ResultInAccumulator); - as->checkException(); -} - - - -static ReturnedValue deleteMemberHelper(QV4::Function *function, const QV4::Value &base, int member) -{ - auto engine = function->internalClass->engine; - if (!Runtime::method_deleteMember(engine, base, member)) { - if (function->isStrict()) - engine->throwTypeError(); - return Encode(false); - } else { - return Encode(true); - } -} - -void BaselineJIT::generate_DeleteMember(int member, int base) -{ - STORE_IP(); - as->prepareCallWithArgCount(3); - as->passInt32AsArg(member, 2); - as->passRegAsArg(base, 1); - as->passFunctionAsArg(0); - JIT_GENERATE_RUNTIME_CALL(deleteMemberHelper, Assembler::ResultInAccumulator); - as->checkException(); -} - -static ReturnedValue deleteSubscriptHelper(QV4::Function *function, const QV4::Value &base, const QV4::Value &index) -{ - auto engine = function->internalClass->engine; - if (!Runtime::method_deleteElement(engine, base, index)) { - if (function->isStrict()) - engine->throwTypeError(); - return Encode(false); - } else { - return Encode(true); - } -} - -void BaselineJIT::generate_DeleteSubscript(int base, int index) -{ - STORE_IP(); - as->prepareCallWithArgCount(3); - as->passRegAsArg(index, 2); - as->passRegAsArg(base, 1); - as->passFunctionAsArg(0); - JIT_GENERATE_RUNTIME_CALL(deleteSubscriptHelper, Assembler::ResultInAccumulator); - as->checkException(); -} - -static ReturnedValue deleteNameHelper(QV4::Function *function, int name) -{ - auto engine = function->internalClass->engine; - if (!Runtime::method_deleteName(engine, name)) { - if (function->isStrict()) - engine->throwTypeError(); - return Encode(false); - } else { - return Encode(true); - } -} - -void BaselineJIT::generate_DeleteName(int name) -{ - STORE_IP(); - as->prepareCallWithArgCount(2); - as->passInt32AsArg(name, 1); - as->passFunctionAsArg(0); - JIT_GENERATE_RUNTIME_CALL(deleteNameHelper, Assembler::ResultInAccumulator); - as->checkException(); -} - -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); -} - -void BaselineJIT::generate_TypeofValue() -{ - STORE_ACC(); - as->prepareCallWithArgCount(2); - as->passAccumulatorAsArg(1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(Runtime::method_typeofValue, Assembler::ResultInAccumulator); -} - -void BaselineJIT::generate_DeclareVar(int varName, int isDeletable) -{ - as->prepareCallWithArgCount(3); - as->passInt32AsArg(varName, 2); - as->passInt32AsArg(isDeletable, 1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(Runtime::method_declareVar, Assembler::IgnoreResult); -} - -void BaselineJIT::generate_DefineArray(int argc, int args) -{ - as->prepareCallWithArgCount(3); - as->passInt32AsArg(argc, 2); - as->passRegAsArg(args, 1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(Runtime::method_arrayLiteral, Assembler::ResultInAccumulator); -} - -void BaselineJIT::generate_DefineObjectLiteral(int internalClassId, int arrayValueCount, - int arrayGetterSetterCountAndFlags, int args) -{ - as->prepareCallWithArgCount(5); - as->passInt32AsArg(arrayGetterSetterCountAndFlags, 4); - as->passInt32AsArg(arrayValueCount, 3); - as->passInt32AsArg(internalClassId, 2); - as->passRegAsArg(args, 1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(Runtime::method_objectLiteral, Assembler::ResultInAccumulator); -} -void BaselineJIT::generate_CreateMappedArgumentsObject() -{ - as->prepareCallWithArgCount(1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(Runtime::method_createMappedArgumentsObject, - Assembler::ResultInAccumulator); -} - -void BaselineJIT::generate_CreateUnmappedArgumentsObject() -{ - as->prepareCallWithArgCount(1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(Runtime::method_createUnmappedArgumentsObject, - Assembler::ResultInAccumulator); -} - -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); -} - -static void convertThisToObjectHelper(ExecutionEngine *engine, Value *t) -{ - if (!t->isObject()) { - if (t->isNullOrUndefined()) { - *t = engine->globalObject->asReturnedValue(); - } else { - *t = t->toObject(engine)->asReturnedValue(); - } - } -} - -void BaselineJIT::generate_ConvertThisToObject() -{ - as->prepareCallWithArgCount(2); - as->passRegAsArg(CallData::This, 1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(convertThisToObjectHelper, Assembler::IgnoreResult); - as->checkException(); -} - -static ReturnedValue ToObjectHelper(ExecutionEngine *engine, const Value &obj) -{ - if (obj.isObject()) - return obj.asReturnedValue(); - - return obj.toObject(engine)->asReturnedValue(); -} - -void BaselineJIT::generate_ToObject() -{ - STORE_ACC(); - as->prepareCallWithArgCount(2); - as->passAccumulatorAsArg(1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(ToObjectHelper, Assembler::ResultInAccumulator); - as->checkException(); - -} - -void BaselineJIT::generate_Construct(int func, int argc, int argv) -{ - STORE_IP(); - as->prepareCallWithArgCount(4); - as->passInt32AsArg(argc, 3); - as->passRegAsArg(argv, 2); - as->passRegAsArg(func, 1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(Runtime::method_construct, Assembler::ResultInAccumulator); - as->checkException(); -} - -void BaselineJIT::generate_Jump(int offset) { as->jump(instructionOffset() + offset); } -void BaselineJIT::generate_JumpTrue(int offset) { as->jumpTrue(instructionOffset() + offset); } -void BaselineJIT::generate_JumpFalse(int offset) { as->jumpFalse(instructionOffset() + offset); } -void BaselineJIT::generate_JumpNotUndefined(int offset) { as->jumpNotUndefined(instructionOffset() + offset); } -void BaselineJIT::generate_JumpEmpty(int offset) { as->jumpEmpty(instructionOffset() + offset); } - -void BaselineJIT::generate_CmpEqNull() { as->cmpeqNull(); } -void BaselineJIT::generate_CmpNeNull() { as->cmpneNull(); } -void BaselineJIT::generate_CmpEqInt(int lhs) { as->cmpeqInt(lhs); } -void BaselineJIT::generate_CmpNeInt(int lhs) { as->cmpneInt(lhs); } -void BaselineJIT::generate_CmpEq(int lhs) { as->cmpeq(lhs); } -void BaselineJIT::generate_CmpNe(int lhs) { as->cmpne(lhs); } -void BaselineJIT::generate_CmpGt(int lhs) { as->cmpgt(lhs); } -void BaselineJIT::generate_CmpGe(int lhs) { as->cmpge(lhs); } -void BaselineJIT::generate_CmpLt(int lhs) { as->cmplt(lhs); } -void BaselineJIT::generate_CmpLe(int lhs) { as->cmple(lhs); } -void BaselineJIT::generate_CmpStrictEqual(int lhs) { as->cmpStrictEqual(lhs); } -void BaselineJIT::generate_CmpStrictNotEqual(int lhs) { as->cmpStrictNotEqual(lhs); } - -void BaselineJIT::generate_CmpIn(int lhs) -{ - STORE_ACC(); - as->prepareCallWithArgCount(3); - as->passAccumulatorAsArg(2); - as->passRegAsArg(lhs, 1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(Runtime::method_in, Assembler::ResultInAccumulator); - as->checkException(); -} - -void BaselineJIT::generate_CmpInstanceOf(int lhs) -{ - STORE_ACC(); - as->prepareCallWithArgCount(3); - as->passAccumulatorAsArg(2); - as->passRegAsArg(lhs, 1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(Runtime::method_instanceof, Assembler::ResultInAccumulator); - as->checkException(); -} - -void BaselineJIT::generate_JumpStrictEqualStackSlotInt(int lhs, int rhs, int offset) -{ - as->jumpStrictEqualStackSlotInt(lhs, rhs, instructionOffset() + offset); -} - -void BaselineJIT::generate_JumpStrictNotEqualStackSlotInt(int lhs, int rhs, int offset) -{ - as->jumpStrictNotEqualStackSlotInt(lhs, rhs, instructionOffset() + offset); -} - -void BaselineJIT::generate_UNot() { as->unot(); } -void BaselineJIT::generate_UPlus() { as->toNumber(); } -void BaselineJIT::generate_UMinus() { as->uminus(); } -void BaselineJIT::generate_UCompl() { as->ucompl(); } -void BaselineJIT::generate_Increment() { as->inc(); } -void BaselineJIT::generate_Decrement() { as->dec(); } -void BaselineJIT::generate_Add(int lhs) { as->add(lhs); } - -void BaselineJIT::generate_BitAnd(int lhs) { as->bitAnd(lhs); } -void BaselineJIT::generate_BitOr(int lhs) { as->bitOr(lhs); } -void BaselineJIT::generate_BitXor(int lhs) { as->bitXor(lhs); } -void BaselineJIT::generate_UShr(int lhs) { as->ushr(lhs); } -void BaselineJIT::generate_Shr(int lhs) { as->shr(lhs); } -void BaselineJIT::generate_Shl(int lhs) { as->shl(lhs); } - -void BaselineJIT::generate_BitAndConst(int rhs) { as->bitAndConst(rhs); } -void BaselineJIT::generate_BitOrConst(int rhs) { as->bitOrConst(rhs); } -void BaselineJIT::generate_BitXorConst(int rhs) { as->bitXorConst(rhs); } -void BaselineJIT::generate_UShrConst(int rhs) { as->ushrConst(rhs); } -void BaselineJIT::generate_ShrConst(int rhs) { as->shrConst(rhs); } -void BaselineJIT::generate_ShlConst(int rhs) { as->shlConst(rhs); } - -static ReturnedValue expHelper(const Value &base, const Value &exp) -{ - double b = base.toNumber(); - double e = exp.toNumber(); - return QV4::Encode(pow(b,e)); -} - -void BaselineJIT::generate_Exp(int lhs) { - STORE_IP(); - STORE_ACC(); - as->prepareCallWithArgCount(2); - as->passAccumulatorAsArg(1); - as->passRegAsArg(lhs, 0); - JIT_GENERATE_RUNTIME_CALL(expHelper, Assembler::ResultInAccumulator); - as->checkException(); -} -void BaselineJIT::generate_Mul(int lhs) { as->mul(lhs); } -void BaselineJIT::generate_Div(int lhs) { as->div(lhs); } -void BaselineJIT::generate_Mod(int lhs) { as->mod(lhs); } -void BaselineJIT::generate_Sub(int lhs) { as->sub(lhs); } - -//void BaselineJIT::generate_BinopContext(int alu, int lhs) -//{ -// auto engine = function->internalClass->engine; -// void *op = engine->runtime.runtimeMethods[alu]; -// STORE_ACC(); -// as->passAccumulatorAsArg(2); -// as->passRegAsArg(lhs, 1); -// as->passEngineAsArg(0); -// as->callRuntime("binopContext", op, Assembler::ResultInAccumulator); -// as->checkException(); -//} - -void BaselineJIT::generate_LoadQmlContext(int result) -{ - as->prepareCallWithArgCount(1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(Runtime::method_loadQmlContext, Assembler::ResultInAccumulator); - as->storeReg(result); -} - -void BaselineJIT::generate_LoadQmlImportedScripts(int result) -{ - as->prepareCallWithArgCount(1); - as->passEngineAsArg(0); - JIT_GENERATE_RUNTIME_CALL(Runtime::method_loadQmlImportedScripts, Assembler::ResultInAccumulator); - as->storeReg(result); -} - -void BaselineJIT::startInstruction(Instr::Type /*instr*/) -{ - if (hasLabel()) - as->addLabel(instructionOffset()); -} - -void BaselineJIT::endInstruction(Instr::Type instr) -{ - Q_UNUSED(instr); -} - -#endif // V4_ENABLE_JIT diff --git a/src/qml/jit/qv4jit_p.h b/src/qml/jit/qv4jit_p.h deleted file mode 100644 index 12a3f27e1b..0000000000 --- a/src/qml/jit/qv4jit_p.h +++ /dev/null @@ -1,232 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef QV4JIT_P_H -#define QV4JIT_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 -#include -#include -#include - -//QT_REQUIRE_CONFIG(qml_jit); - -QT_BEGIN_NAMESPACE - -namespace QV4 { -namespace JIT { - -class Assembler; - -#ifdef V4_ENABLE_JIT -class BaselineJIT final: public Moth::ByteCodeHandler -{ -public: - BaselineJIT(QV4::Function *); - virtual ~BaselineJIT() Q_DECL_OVERRIDE; - - void generate(); - - void generate_Ret() override; - void generate_Debug() override; - void generate_LoadConst(int index) override; - void generate_LoadZero() override; - void generate_LoadTrue() override; - void generate_LoadFalse() override; - void generate_LoadNull() override; - void generate_LoadUndefined() override; - void generate_LoadInt(int value) override; - void generate_MoveConst(int constIndex, int destTemp) override; - void generate_LoadReg(int reg) override; - void generate_StoreReg(int reg) override; - void generate_MoveReg(int srcReg, int destReg) override; - void generate_LoadLocal(int index) override; - void generate_StoreLocal(int index) override; - void generate_LoadScopedLocal(int scope, int index) override; - void generate_StoreScopedLocal(int scope, int index) override; - void generate_LoadRuntimeString(int stringId) override; - void generate_MoveRegExp(int regExpId, int destReg) override; - void generate_LoadClosure(int value) override; - void generate_LoadName(int name) override; - void generate_LoadGlobalLookup(int index) override; - void generate_StoreNameSloppy(int name) override; - void generate_StoreNameStrict(int name) override; - void generate_LoadElement(int base, int index) override; - void generate_LoadElementA(int base) override; - void generate_StoreElement(int base, int index) override; - void generate_LoadProperty(int name, int base) override; - void generate_LoadPropertyA(int name) override; - void generate_GetLookup(int index, int base) override; - void generate_GetLookupA(int index) override; - void generate_StoreProperty(int name, int base) override; - void generate_SetLookup(int index, int base) override; - void generate_StoreScopeObjectProperty(int base, - int propertyIndex) override; - void generate_StoreContextObjectProperty(int base, - int propertyIndex) override; - void generate_LoadScopeObjectProperty(int propertyIndex, int base, - int captureRequired) override; - void generate_LoadContextObjectProperty(int propertyIndex, int base, - int captureRequired) override; - void generate_LoadIdObject(int index, int base) override; - void generate_Yield() override; - void generate_Resume(int) override; - - void generate_CallValue(int name, int argc, int argv) override; - void generate_CallProperty(int name, int base, int argc, int argv) override; - void generate_CallPropertyLookup(int lookupIndex, int base, int argc, int argv) override; - void generate_CallElement(int base, int index, int argc, int argv) override; - void generate_CallName(int name, int argc, int argv) override; - void generate_CallPossiblyDirectEval(int argc, int argv) override; - void generate_CallGlobalLookup(int index, int argc, int argv) override; - void generate_CallScopeObjectProperty(int propIdx, int base, int argc, int argv) override; - void generate_CallContextObjectProperty(int propIdx, int base, int argc, int argv) override; - void generate_SetExceptionHandler(int offset) override; - void generate_ThrowException() override; - void generate_GetException() override; - void generate_SetException() override; - void generate_CreateCallContext() override; - void generate_PushCatchContext(int index, int name) override; - void generate_PushWithContext() override; - void generate_PushBlockContext(int index) override; - void generate_CloneBlockContext() override; - void generate_PushScriptContext(int index) override; - void generate_PopScriptContext() override; - void generate_PopContext() override; - void generate_GetIterator(int iterator) override; - void generate_IteratorNext(int value) override; - void generate_IteratorClose(int done) override; - void generate_DestructureRestElement() override; - void generate_DeleteMember(int member, int base) override; - void generate_DeleteSubscript(int base, int index) override; - void generate_DeleteName(int name) override; - void generate_TypeofName(int name) override; - void generate_TypeofValue() override; - void generate_DeclareVar(int varName, int isDeletable) override; - void generate_DefineArray(int argc, int args) override; - void generate_DefineObjectLiteral(int internalClassId, int arrayValueCount, - int arrayGetterSetterCountAndFlags, - int args) override; - void generate_CreateMappedArgumentsObject() override; - void generate_CreateUnmappedArgumentsObject() override; - void generate_CreateRestParameter(int argIndex) override; - void generate_ConvertThisToObject() override; - void generate_ToObject() override; - void generate_Construct(int func, int argc, int argv) override; - void generate_Jump(int offset) override; - void generate_JumpTrue(int offset) override; - void generate_JumpFalse(int offset) override; - void generate_JumpNotUndefined(int offset) override; - void generate_JumpEmpty(int offset) override; - void generate_CmpEqNull() override; - void generate_CmpNeNull() override; - void generate_CmpEqInt(int lhs) override; - void generate_CmpNeInt(int lhs) override; - void generate_CmpEq(int lhs) override; - void generate_CmpNe(int lhs) override; - void generate_CmpGt(int lhs) override; - void generate_CmpGe(int lhs) override; - void generate_CmpLt(int lhs) override; - void generate_CmpLe(int lhs) override; - void generate_CmpStrictEqual(int lhs) override; - void generate_CmpStrictNotEqual(int lhs) override; - void generate_CmpIn(int lhs) override; - void generate_CmpInstanceOf(int lhs) override; - void generate_JumpStrictEqualStackSlotInt(int lhs, int rhs, - int offset) override; - void generate_JumpStrictNotEqualStackSlotInt(int lhs, int rhs, - int offset) override; - void generate_UNot() override; - void generate_UPlus() override; - void generate_UMinus() override; - void generate_UCompl() override; - void generate_Increment() override; - void generate_Decrement() override; - void generate_Add(int lhs) override; - void generate_BitAnd(int lhs) override; - void generate_BitOr(int lhs) override; - void generate_BitXor(int lhs) override; - void generate_UShr(int lhs) override; - void generate_Shr(int lhs) override; - void generate_Shl(int lhs) override; - void generate_BitAndConst(int rhs) override; - void generate_BitOrConst(int rhs) override; - void generate_BitXorConst(int rhs) override; - void generate_UShrConst(int rhs) override; - void generate_ShrConst(int rhs) override; - void generate_ShlConst(int rhs) override; - void generate_Exp(int lhs) override; - void generate_Mul(int lhs) override; - void generate_Div(int lhs) override; - void generate_Mod(int lhs) override; - void generate_Sub(int lhs) override; - void generate_LoadQmlContext(int result) override; - void generate_LoadQmlImportedScripts(int result) override; - - void startInstruction(Moth::Instr::Type instr) override; - void endInstruction(Moth::Instr::Type instr) override; - -protected: - bool hasLabel() const - { return std::find(labels.cbegin(), labels.cend(), instructionOffset()) != labels.cend(); } - -private: - QV4::Function *function; - QScopedPointer as; - std::vector labels; -}; -#endif // V4_ENABLE_JIT - -} // namespace JIT -} // namespace QV4 - -QT_END_NAMESPACE - -#endif // QV4JIT_P_H diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index 84d5d6e6e4..d89d314942 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -61,7 +61,7 @@ #include "qv4alloca_p.h" -#include +#include #undef COUNT_INSTRUCTIONS -- cgit v1.2.3