aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jit/qv4operation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/jit/qv4operation.cpp')
-rw-r--r--src/qml/jit/qv4operation.cpp770
1 files changed, 0 insertions, 770 deletions
diff --git a/src/qml/jit/qv4operation.cpp b/src/qml/jit/qv4operation.cpp
deleted file mode 100644
index acd5328fd0..0000000000
--- a/src/qml/jit/qv4operation.cpp
+++ /dev/null
@@ -1,770 +0,0 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
-
-#include "qv4operation_p.h"
-#include "qv4runtimesupport_p.h"
-
-QT_BEGIN_NAMESPACE
-namespace QV4 {
-namespace IR {
-
-OperationBuilder::OperationBuilder(QQmlJS::MemoryPool *graphPool)
- : m_graphPool(graphPool)
-{}
-
-OperationBuilder *OperationBuilder::create(QQmlJS::MemoryPool *pool)
-{
- return pool->New<OperationBuilder>(pool);
-}
-
-Operation *OperationBuilder::getConstant(Value v)
-{
- Type t;
- switch (v.type()) {
- case Value::Undefined_Type: t = Type::undefinedType(); break;
- case Value::Integer_Type: t = Type::int32Type(); break;
- case Value::Boolean_Type: t = Type::booleanType(); break;
- case Value::Null_Type: t = Type::nullType(); break;
- case Value::Double_Type: t = Type::doubleType(); break;
- case Value::Managed_Type: t = Type::objectType(); break;
- default:
- if (v.isEmpty())
- t = Type::emptyType();
- else
- Q_UNREACHABLE();
- }
- return OperationWithPayload<ConstantPayload>::create(
- m_graphPool, Meta::Constant, 0, 0, 0, 1, 0, 0, t, Operation::NoFlags,
- ConstantPayload(v));
-}
-
-Operation *OperationBuilder::getParam(unsigned index, const Function::StringId name)
-{
- return OperationWithPayload<ParameterPayload>::create(m_graphPool, Meta::Parameter,
- 1, 0, 0,
- 1, 0, 0,
- Type::anyType(), Operation::NoFlags,
- ParameterPayload(index, name));
-}
-
-Operation *OperationBuilder::getRegion(unsigned nControlInputs) //### cache common operands in the static pool
-{
- return Operation::create(m_graphPool, Meta::Region,
- 0, 0, uint16_t(nControlInputs),
- 0, 0, 1,
- Type(), Operation::NoFlags);
-}
-
-Operation *OperationBuilder::getPhi(unsigned nValueInputs) //### cache common operands in the static pool
-{
- return Operation::create(m_graphPool, Meta::Phi,
- uint16_t(nValueInputs), 0, 1,
- 1, 0, 0,
- Type::anyType(), Operation::NoFlags);
-}
-
-Operation *OperationBuilder::getEffectPhi(unsigned nEffectInputs) //### cache common operands in the static pool
-{
- return Operation::create(m_graphPool, Meta::EffectPhi,
- 0, uint16_t(nEffectInputs), 1,
- 0, 1, 0,
- Type(), Operation::NoFlags);
-}
-
-Operation *OperationBuilder::getUnwindDispatch(unsigned nContinuations, int unwindHandlerOffset,
- int fallthroughSuccessor)
-{
- return OperationWithPayload<UnwindDispatchPayload>::create(
- m_graphPool, Meta::UnwindDispatch,
- 0, 1, 1, 0, nContinuations, nContinuations,
- Type(), Operation::NoFlags,
- UnwindDispatchPayload(unwindHandlerOffset,
- fallthroughSuccessor));
-}
-
-Operation *OperationBuilder::getHandleUnwind(int unwindHandlerOffset)
-{
- return OperationWithPayload<HandleUnwindPayload>::create(m_graphPool, Meta::HandleUnwind,
- 0, 1, 1, 0, 1, 1,
- Type(), Operation::NoFlags,
- HandleUnwindPayload(unwindHandlerOffset));
-}
-
-Operation *OperationBuilder::getFrameState(uint16_t frameSize)
-{
- if (m_opFrameState == nullptr)
- m_opFrameState = Operation::create(m_graphPool, Meta::FrameState,
- frameSize, 0, 0, 0, 0, 1,
- Type(), Operation::NoFlags);
- else
- Q_ASSERT(frameSize == m_opFrameState->valueInputCount());
-
- return m_opFrameState;
-}
-
-Operation *OperationBuilder::getStart(uint16_t outputCount)
-{
- return Operation::create(m_graphPool, Meta::Start,
- 0, 0, 0,
- outputCount, 1, 1,
- Type(), Operation::NoFlags);
-}
-
-Operation *OperationBuilder::getEnd(uint16_t controlInputCount)
-{
- return Operation::create(m_graphPool, Meta::End,
- 0, 0, controlInputCount,
- 0, 0, 0,
- Type(), Operation::NoFlags);
-}
-
-inline Operation *createOperation(Operation::Kind kind, QQmlJS::MemoryPool *staticPool)
-{
- auto get = [&](uint16_t inValueCount, uint16_t inEffectCount, uint16_t inControlCount,
- uint16_t outValueCount, uint16_t outEffectCount, uint16_t outControlCount,
- Type (*typeCreator)(), uint8_t flags) {
- return Operation::create(staticPool, kind, inValueCount, inEffectCount, inControlCount,
- outValueCount, outEffectCount, outControlCount, typeCreator(),
- flags);
- };
-
- using K = Operation::Kind;
- using F = Operation::Flags;
- const auto none = &Type::noneType;
- const auto any = &Type::anyType;
- const auto number = &Type::numberType;
- const auto boolean = &Type::booleanType;
-
- switch (kind) {
- case K::Undefined:
- return OperationWithPayload<ConstantPayload>::create(
- staticPool, K::Undefined, 0, 0, 0, 1, 0, 0, Type::undefinedType(), F::NoFlags,
- ConstantPayload(Primitive::undefinedValue()));
- case K::Empty:
- return OperationWithPayload<ConstantPayload>::create(
- staticPool, K::Constant, 0, 0, 0, 1, 0, 0, Type::emptyType(), Operation::NoFlags,
- ConstantPayload(Primitive::emptyValue()));
- case K::Engine: return get(1, 0, 0, 1, 0, 0, none, F::NoFlags);
- case K::CppFrame: return get(1, 0, 0, 1, 0, 0, none, F::NoFlags);
- case K::Function: return get(1, 0, 0, 1, 0, 0, none, F::NoFlags);
- case K::Jump: return get(0, 0, 1, 0, 0, 1, none, F::NoFlags);
- case K::Return: return get(1, 1, 1, 0, 0, 1, none, F::NoFlags);
- case K::Branch: return get(1, 0, 1, 0, 0, 2, none, F::HasFrameStateInput | F::NeedsBytecodeOffsets);
- case K::IfTrue: return get(0, 0, 1, 0, 0, 1, none, F::NoFlags);
- case K::IfFalse: return get(0, 0, 1, 0, 0, 1, none, F::NoFlags);
- case K::SelectOutput: return get(3, 1, 1, 1, 1, 1, any, F::NoFlags);
- case K::Throw: return get(1, 1, 1, 0, 1, 1, any, F::NeedsBytecodeOffsets);
- case K::OnException: return get(0, 0, 1, 0, 0, 1, none, F::NoFlags);
- case K::ThrowReferenceError: return get(1, 1, 1, 0, 1, 1, any, F::NeedsBytecodeOffsets);
- case K::UnwindToLabel: return get(2, 1, 1, 0, 1, 1, none, F::NoFlags);
- case K::LoadRegExp: return get(1, 0, 0, 1, 0, 0, any, F::NoFlags);
- case K::ScopedLoad: return get(2, 1, 0, 1, 1, 0, any, F::NoFlags);
- case K::ScopedStore: return get(3, 1, 0, 0, 1, 0, none, F::NoFlags);
- case K::JSLoadElement: return get(2, 1, 1, 1, 1, 2, any, F::CanThrow);
- case K::JSGetLookup: return get(2, 1, 1, 1, 1, 2, any, F::CanThrow);
- case K::JSLoadProperty: return get(2, 1, 1, 1, 1, 2, any, F::CanThrow);
- case K::JSStoreElement: return get(3, 1, 1, 0, 1, 2, none, F::CanThrow);
- case K::JSSetLookupStrict: return get(3, 1, 1, 0, 1, 2, none, F::CanThrow);
- case K::JSSetLookupSloppy: return get(3, 1, 1, 0, 1, 2, none, F::CanThrow);
- case K::JSStoreProperty: return get(3, 1, 1, 0, 1, 2, none, F::CanThrow);
- case K::JSLoadName: return get(1, 1, 1, 1, 1, 2, any, F::CanThrow);
- case K::JSLoadGlobalLookup: return get(1, 1, 1, 1, 1, 2, any, F::CanThrow);
- case K::JSStoreNameSloppy: return get(2, 1, 1, 0, 1, 2, none, F::CanThrow);
- case K::JSStoreNameStrict: return get(2, 1, 1, 0, 1, 2, none, F::CanThrow);
- case K::JSLoadSuperProperty: return get(1, 1, 1, 1, 1, 2, any, F::CanThrow);
- case K::JSStoreSuperProperty: return get(2, 1, 1, 0, 1, 2, any, F::CanThrow);
- case K::JSLoadClosure: return get(1, 1, 0, 1, 1, 0, any, F::Pure);
- case K::JSGetIterator: return get(2, 1, 1, 1, 1, 2, any, F::CanThrow);
-
- // special case: see GraphBuilder::generate_IteratorNext
- case K::JSIteratorNext: return get(2, 1, 1, 2, 1, 1, any, F::NoFlags);
-
- // special case: see GraphBuilder::generate_IteratorNext
- case K::JSIteratorNextForYieldStar: return get(3, 1, 1, 2, 1, 1, any, F::NoFlags);
-
- case K::JSIteratorClose: return get(2, 1, 1, 1, 1, 2, any, F::CanThrow);
- case K::JSDeleteProperty: return get(2, 1, 1, 1, 1, 2, any, F::CanThrow);
- case K::JSDeleteName: return get(1, 1, 1, 1, 1, 2, any, F::CanThrow);
- case K::JSIn: return get(2, 1, 1, 1, 1, 2, any, F::CanThrow);
- case K::JSInstanceOf: return get(2, 1, 1, 1, 1, 2, any, F::CanThrow);
- case K::QMLLoadQmlContextPropertyLookup: return get(1, 1, 1, 1, 1, 2, any, F::CanThrow);
-
- case K::JSEqual: return get(2, 1, 1, 1, 1, 2, boolean, F::CanThrow);
- case K::JSGreaterThan: return get(2, 1, 1, 1, 1, 2, boolean, F::CanThrow);
- case K::JSGreaterEqual: return get(2, 1, 1, 1, 1, 2, boolean, F::CanThrow);
- case K::JSLessThan: return get(2, 1, 1, 1, 1, 2, boolean, F::CanThrow);
- case K::JSLessEqual: return get(2, 1, 1, 1, 1, 2, boolean, F::CanThrow);
- case K::JSStrictEqual: return get(2, 1, 1, 1, 1, 2, boolean, F::CanThrow);
-
- case K::JSAdd: return get(2, 1, 1, 1, 1, 2, any, F::CanThrow);
- case K::JSSubtract: return get(2, 1, 1, 1, 1, 2, number, F::CanThrow);
- case K::JSMultiply: return get(2, 1, 1, 1, 1, 2, number, F::CanThrow);
- case K::JSDivide: return get(2, 1, 1, 1, 1, 2, number, F::CanThrow);
- case K::JSModulo: return get(2, 1, 1, 1, 1, 2, number, F::CanThrow);
- case K::JSExponentiate: return get(2, 1, 1, 1, 1, 2, number, F::CanThrow);
-
- case K::JSBitAnd: return get(2, 1, 1, 1, 1, 2, any, F::CanThrow);
- case K::JSBitOr: return get(2, 1, 1, 1, 1, 2, any, F::CanThrow);
- case K::JSBitXor: return get(2, 1, 1, 1, 1, 2, any, F::CanThrow);
- case K::JSUnsignedShiftRight: return get(2, 1, 1, 1, 1, 2, any, F::CanThrow);
- case K::JSShiftRight: return get(2, 1, 1, 1, 1, 2, any, F::CanThrow);
- case K::JSShiftLeft: return get(2, 1, 1, 1, 1, 2, any, F::CanThrow);
-
- case K::JSNegate: return get(1, 1, 1, 1, 1, 2, number, F::CanThrow);
- case K::JSToNumber: return get(1, 1, 1, 1, 1, 2, number, F::CanThrow);
- case K::Alloca: return get(1, 0, 0, 1, 0, 0, none, F::NoFlags);
-
- //### it is questionable if VAAlloc/VASeal need effect edges
- case K::VAAlloc: return get(1, 1, 0, 1, 1, 0, none, F::NoFlags);
-
- case K::VAStore: return get(3, 0, 0, 1, 0, 0, none, F::NoFlags);
-
- case K::JSTypeofName: return get(1, 1, 0, 1, 1, 0, any, F::NoFlags);
- case K::JSTypeofValue: return get(1, 0, 0, 1, 0, 0, any, F::Pure);
- case K::JSDeclareVar: return get(2, 1, 1, 1, 1, 2, any, F::CanThrow);
- case K::JSDestructureRestElement: return get(1, 1, 1, 1, 1, 2, any, F::CanThrow);
-
- case K::JSCreateCallContext: return get(0, 1, 1, 0, 1, 1, none, F::NoFlags);
- case K::JSCreateCatchContext: return get(2, 1, 1, 1, 1, 1, none, F::NoFlags);
- case K::JSCreateWithContext: return get(1, 1, 1, 1, 1, 1, any, F::NoFlags);
- case K::JSCreateBlockContext: return get(1, 1, 1, 1, 1, 1, none, F::NoFlags);
- case K::JSCloneBlockContext: return get(0, 1, 1, 0, 1, 1, none, F::NoFlags);
- case K::JSCreateScriptContext: return get(1, 1, 1, 1, 1, 1, none, F::NoFlags);
- case K::JSPopScriptContext: return get(0, 1, 1, 1, 1, 1, none, F::NoFlags);
- case K::PopContext: return get(0, 1, 1, 0, 1, 1, none, F::NoFlags);
-
- case K::JSThisToObject: return get(1, 1, 1, 0, 1, 2, any, F::NoFlags);
- case K::JSCreateMappedArgumentsObject: return get(0, 1, 0, 1, 1, 0, any, F::NoFlags);
- case K::JSCreateUnmappedArgumentsObject: return get(0, 1, 0, 1, 1, 0, any, F::NoFlags);
- case K::JSCreateRestParameter: return get(1, 0, 0, 1, 0, 0, any, F::NoFlags);
- case K::JSLoadSuperConstructor: return get(1, 1, 1, 1, 1, 2, any, F::NoFlags);
- case K::JSThrowOnNullOrUndefined: return get(1, 1, 1, 0, 1, 2, none, F::CanThrow);
- case K::JSGetTemplateObject: return get(1, 0, 0, 1, 0, 0, any, F::NoFlags);
- case K::StoreThis: return get(1, 1, 0, 1, 1, 0, any, F::NoFlags);
-
- case K::GetException: return get(0, 1, 0, 1, 1, 0, any, F::NoFlags);
- case K::SetException: return get(1, 1, 0, 0, 1, 0, any, F::NoFlags);
-
- case K::ToObject: return get(1, 1, 1, 1, 1, 2, any, F::CanThrow);
- case K::ToBoolean: return get(1, 0, 0, 1, 0, 0, boolean, F::Pure);
-
- case K::IsEmpty: return get(1, 0, 0, 1, 0, 0, boolean, F::Pure);
-
- case K::BooleanNot: return get(1, 0, 0, 1, 0, 0, boolean, F::NoFlags);
- case K::HasException: return get(1, 1, 0, 1, 1, 0, boolean, F::NoFlags);
-
- case K::Swap: return get(0, 0, 0, 0, 0, 0, none, F::NoFlags);
- case K::Move: return get(1, 0, 0, 1, 0, 0, none, F::NoFlags);
-
- default: // Non-static operations:
- return nullptr;
- }
-}
-
-Operation *OperationBuilder::staticOperation(Operation::Kind kind)
-{
- static QAtomicPointer<Operation *> ops;
- if (Operation **staticOps = ops.load())
- return staticOps[kind];
-
- static QAtomicInt initializing = 0;
- if (initializing.testAndSetOrdered(0, 1)) {
- // This is safe now, because we can only run this piece of code once during the life time
- // of the application as we can only change initializing from 0 to 1 once.
- Operation **staticOps = new Operation *[Meta::KindsEnd];
- static QQmlJS::MemoryPool pool;
- for (int i = 0; i < Meta::KindsEnd; ++i)
- staticOps[i] = createOperation(Operation::Kind(i), &pool);
- bool success = ops.testAndSetOrdered(nullptr, staticOps);
- Q_ASSERT(success);
- } else {
- // Unfortunately we need to busy wait now until the other thread finishes the static
- // initialization;
- while (!ops.load()) {}
- }
-
- return ops.load()[kind];
-}
-
-Operation *OperationBuilder::getJSVarArgsCall(Operation::Kind kind, uint16_t argc)
-{
- return Operation::create(m_graphPool, kind,
- argc, 1, 1, 1, 1, 2,
- Type::anyType(), Operation::CanThrow);
-}
-
-Operation *OperationBuilder::getJSTailCall(uint16_t argc)
-{
- return Operation::create(m_graphPool, Meta::JSTailCall,
- argc, 1, 1, 0, 0, 1,
- Type(), Operation::NoFlags);
-}
-
-Operation *OperationBuilder::getTailCall()
-{
- // special varargs call, takes cppframe, engine, func, thisObject, argv, argc
- return Operation::create(m_graphPool, Meta::TailCall,
- 6, 1, 1, 0, 0, 1,
- Type(), Operation::NoFlags);
-}
-
-Operation *OperationBuilder::getCall(Operation::Kind callee)
-{
- const bool canThrow = CallPayload::canThrow(callee);
- const Type retTy = CallPayload::returnType(callee);
- uint16_t nControlInputs = 0;
- uint16_t nControlOutputs = 0;
- if (canThrow) {
- nControlInputs = 1;
- nControlOutputs += 2;
- }
- if (CallPayload::changesContext(callee)) {
- nControlInputs = 1;
- nControlOutputs = std::max<uint16_t>(nControlInputs, 1);
- }
- if (callee == Meta::Throw || callee == Meta::ThrowReferenceError ||
- callee == Meta::JSIteratorNext || callee == Meta::JSIteratorNextForYieldStar) {
- nControlInputs = 1;
- nControlOutputs = 1;
- }
- Operation::Flags flags = Operation::NoFlags;
- if (canThrow)
- flags = Operation::Flags(flags | Operation::CanThrow);
- if (CallPayload::isPure(callee))
- flags = Operation::Flags(flags | Operation::Pure);
- const uint16_t nEffects = (flags & Operation::Pure) ? 0 : 1;
- const uint16_t nValueOutputs = retTy.isNone() ? 0 : 1;
- const uint16_t nValueInputs = CallPayload::argc(callee);
-
- return OperationWithPayload<CallPayload>::create(
- m_graphPool, Meta::Call,
- nValueInputs, nEffects, nControlInputs,
- nValueOutputs, nEffects, nControlOutputs,
- retTy, flags,
- CallPayload(callee));
-}
-
-Operation *OperationBuilder::getVASeal(uint16_t nElements)
-{
- return Operation::create(m_graphPool, Meta::VASeal,
- nElements + 1, 1, 0, 1, 1, 0,
- Type::anyType(), Operation::NoFlags);
-}
-
-QString Operation::debugString() const
-{
- switch (kind()) {
-
- case Meta::Constant:
- return QStringLiteral("Constant[%1]").arg(ConstantPayload::get(*this)->debugString());
- case Meta::Parameter:
- return QStringLiteral("Parameter[%1]").arg(ParameterPayload::get(*this)->debugString());
- case Meta::Call:
- return QStringLiteral("Call[%1]").arg(CallPayload::get(*this)->debugString());
- case Meta::UnwindDispatch:
- return QStringLiteral("UnwindDispatch[%1]").arg(UnwindDispatchPayload::get(*this)
- ->debugString());
- case Meta::HandleUnwind:
- return QStringLiteral("HandleUnwind[%1]").arg(HandleUnwindPayload::get(*this)
- ->debugString());
-
- default:
- return QString::fromLatin1(QMetaEnum::fromType<Meta::OpKind>().valueToKey(kind()));
- }
-}
-
-QString ConstantPayload::debugString() const
-{
- return debugString(m_value);
-}
-
-QString ConstantPayload::debugString(QV4::Value v)
-{
- if (v.isManaged())
- return QString::asprintf("Ptr: %p", v.heapObject());
- if (v.isEmpty())
- return QStringLiteral("empty");
- return v.toQStringNoThrow();
-}
-
-QString ParameterPayload::debugString() const
-{
- return QStringLiteral("%1").arg(m_index);
-}
-
-QString UnwindDispatchPayload::debugString() const
-{
- return QStringLiteral("%1, %2").arg(QString::number(m_fallthroughSuccessor),
- QString::number(m_unwindHandlerOffset));
-}
-
-QString HandleUnwindPayload::debugString() const
-{
- return QStringLiteral("%1").arg(m_unwindHandlerOffset);
-}
-
-static Type translateType(RuntimeSupport::ArgumentType t)
-{
- switch (t) {
- case RuntimeSupport::ArgumentType::Int: return Type::int32Type();
- case RuntimeSupport::ArgumentType::Bool: return Type::booleanType();
- case RuntimeSupport::ArgumentType::Void: return Type();
- case RuntimeSupport::ArgumentType::Engine: return Type::rawPointerType();
- case RuntimeSupport::ArgumentType::ValueRef: return Type::anyType();
- case RuntimeSupport::ArgumentType::ValueArray: return Type::anyType();
- case RuntimeSupport::ArgumentType::ReturnedValue: return Type::anyType();
- default: Q_UNREACHABLE();
- }
-}
-
-template<template<typename Operation> class M /* MetaOperation */, typename ReturnValue>
-static ReturnValue operateOnRuntimeCall(Operation::Kind kind, bool abortOnMissingCall = true)
-{
- using K = Operation::Kind;
- using R = Runtime;
-
- switch (kind) {
- case K::Throw: return M<R::ThrowException>::doIt();
- case K::ThrowReferenceError: return M<R::ThrowReferenceError>::doIt();
-
- case K::JSEqual: return M<R::CompareEqual>::doIt();
- case K::JSGreaterThan: return M<R::CompareGreaterThan>::doIt();
- case K::JSGreaterEqual: return M<R::CompareGreaterEqual>::doIt();
- case K::JSLessThan: return M<R::CompareLessThan>::doIt();
- case K::JSLessEqual: return M<R::CompareLessEqual>::doIt();
- case K::JSStrictEqual: return M<R::CompareStrictEqual>::doIt();
-
- case K::JSBitAnd: return M<R::BitAnd>::doIt();
- case K::JSBitOr: return M<R::BitOr>::doIt();
- case K::JSBitXor: return M<R::BitXor>::doIt();
- case K::JSUnsignedShiftRight: return M<R::UShr>::doIt();
- case K::JSShiftRight: return M<R::Shr>::doIt();
- case K::JSShiftLeft: return M<R::Shl>::doIt();
-
- case K::JSAdd: return M<R::Add>::doIt();
- case K::JSSubtract: return M<R::Sub>::doIt();
- case K::JSMultiply: return M<R::Mul>::doIt();
- case K::JSDivide: return M<R::Div>::doIt();
- case K::JSModulo: return M<R::Mod>::doIt();
- case K::JSExponentiate: return M<R::Exp>::doIt();
-
- case K::ToBoolean: return M<R::ToBoolean>::doIt();
- case K::ToObject: return M<R::ToObject>::doIt();
-
- case K::JSNegate: return M<R::UMinus>::doIt();
- case K::JSToNumber: return M<R::ToNumber>::doIt();
-
- case K::JSLoadName: return M<R::LoadName>::doIt();
- case K::JSLoadElement: return M<R::LoadElement>::doIt();
- case K::JSStoreElement: return M<R::StoreElement>::doIt();
- case K::JSGetLookup: return M<R::GetLookup>::doIt();
- case K::JSSetLookupStrict: return M<R::SetLookupStrict>::doIt();
- case K::JSSetLookupSloppy: return M<R::SetLookupSloppy>::doIt();
- case K::JSLoadProperty: return M<R::LoadProperty>::doIt();
- case K::JSStoreProperty: return M<R::StoreProperty>::doIt();
- case K::JSLoadGlobalLookup: return M<R::LoadGlobalLookup>::doIt();
- case K::JSStoreNameSloppy: return M<R::StoreNameSloppy>::doIt();
- case K::JSStoreNameStrict: return M<R::StoreNameStrict>::doIt();
- case K::JSLoadSuperProperty: return M<R::LoadSuperProperty>::doIt();
- case K::JSStoreSuperProperty: return M<R::StoreSuperProperty>::doIt();
- case K::JSLoadClosure: return M<R::Closure>::doIt();
- case K::JSGetIterator: return M<R::GetIterator>::doIt();
- case K::JSIteratorNext: return M<R::IteratorNext>::doIt();
- case K::JSIteratorNextForYieldStar: return M<R::IteratorNextForYieldStar>::doIt();
- case K::JSIteratorClose: return M<R::IteratorClose>::doIt();
- case K::JSDeleteProperty: return M<R::DeleteProperty>::doIt();
- case K::JSDeleteName: return M<R::DeleteName>::doIt();
- case K::JSIn: return M<R::In>::doIt();
- case K::JSInstanceOf: return M<R::Instanceof>::doIt();
- case K::QMLLoadQmlContextPropertyLookup: return M<R::LoadQmlContextPropertyLookup>::doIt();
-
- case K::JSTypeofName: return M<R::TypeofName>::doIt();
- case K::JSTypeofValue: return M<R::TypeofValue>::doIt();
- case K::JSDeclareVar: return M<R::DeclareVar>::doIt();
- case K::JSDestructureRestElement: return M<R::DestructureRestElement>::doIt();
- case K::JSThisToObject: return M<R::ConvertThisToObject>::doIt();
- case K::JSCreateMappedArgumentsObject: return M<R::CreateMappedArgumentsObject>::doIt();
- case K::JSCreateUnmappedArgumentsObject: return M<R::CreateUnmappedArgumentsObject>::doIt();
- case K::JSCreateRestParameter: return M<R::CreateRestParameter>::doIt();
- case K::JSLoadSuperConstructor: return M<R::LoadSuperConstructor>::doIt();
- case K::JSThrowOnNullOrUndefined: return M<R::ThrowOnNullOrUndefined>::doIt();
-
- case K::JSCreateCallContext: return M<R::PushCallContext>::doIt();
- case K::JSCreateCatchContext: return M<R::PushCatchContext>::doIt();
- case K::JSCreateWithContext: return M<R::PushWithContext>::doIt();
- case K::JSCreateBlockContext: return M<R::PushBlockContext>::doIt();
- case K::JSCloneBlockContext: return M<R::CloneBlockContext>::doIt();
- case K::JSCreateScriptContext: return M<R::PushScriptContext>::doIt();
- case K::JSPopScriptContext: return M<R::PopScriptContext>::doIt();
-
- case K::LoadRegExp: return M<R::RegexpLiteral>::doIt();
- case K::JSGetTemplateObject: return M<R::GetTemplateObject>::doIt();
-
- case K::JSCallName: return M<R::CallName>::doIt();
- case K::JSCallValue: return M<R::CallValue>::doIt();
- case K::JSCallElement: return M<R::CallElement>::doIt();
- case K::JSCallLookup: return M<R::CallPropertyLookup>::doIt();
- case K::JSCallProperty: return M<R::CallProperty>::doIt();
- case K::JSCallGlobalLookup: return M<R::CallGlobalLookup>::doIt();
- case K::JSCallPossiblyDirectEval: return M<R::CallPossiblyDirectEval>::doIt();
- case K::JSCallWithReceiver: return M<R::CallWithReceiver>::doIt();
- case K::JSDefineObjectLiteral: return M<R::ObjectLiteral>::doIt();
- case K::JSDefineArray: return M<R::ArrayLiteral>::doIt();
- case K::JSCallWithSpread: return M<R::CallWithSpread>::doIt();
- case K::JSConstruct: return M<R::Construct>::doIt();
- case K::JSConstructWithSpread: return M<R::ConstructWithSpread>::doIt();
- case K::JSTailCall: return M<R::TailCall>::doIt();
- case K::JSCreateClass: return M<R::CreateClass>::doIt();
- default:
- if (abortOnMissingCall)
- Q_UNREACHABLE();
- else
- return ReturnValue();
- }
-}
-
-template<typename Method>
-struct IsRuntimeMethodOperation
-{
- static constexpr bool doIt() { return true; }
-};
-
-bool CallPayload::isRuntimeCall(Operation::Kind m)
-{
- return operateOnRuntimeCall<IsRuntimeMethodOperation, bool>(m, false);
-}
-
-QString CallPayload::debugString() const
-{
- return QString::fromLatin1(QMetaEnum::fromType<Meta::OpKind>().valueToKey(m_callee));
-}
-
-template<typename Method>
-struct MethodArgcOperation
-{
- static constexpr unsigned doIt() { return RuntimeSupport::argumentCount<Method>(); }
-};
-
-unsigned CallPayload::argc(Operation::Kind callee)
-{
- return operateOnRuntimeCall<MethodArgcOperation, unsigned>(callee);
-}
-
-template<typename Method> struct MethodArg1TyOperation { static constexpr RuntimeSupport::ArgumentType doIt() { return RuntimeSupport::arg1Type<Method>(); } };
-template<typename Method> struct MethodArg2TyOperation { static constexpr RuntimeSupport::ArgumentType doIt() { return RuntimeSupport::arg2Type<Method>(); } };
-template<typename Method> struct MethodArg3TyOperation { static constexpr RuntimeSupport::ArgumentType doIt() { return RuntimeSupport::arg3Type<Method>(); } };
-template<typename Method> struct MethodArg4TyOperation { static constexpr RuntimeSupport::ArgumentType doIt() { return RuntimeSupport::arg4Type<Method>(); } };
-template<typename Method> struct MethodArg5TyOperation { static constexpr RuntimeSupport::ArgumentType doIt() { return RuntimeSupport::arg5Type<Method>(); } };
-template<typename Method> struct MethodArg6TyOperation { static constexpr RuntimeSupport::ArgumentType doIt() { return RuntimeSupport::arg6Type<Method>(); } };
-
-static RuntimeSupport::ArgumentType untranslatedArgumentType(Operation::Kind m, unsigned arg)
-{
- if (m == Meta::JSTailCall) {
- if (arg < 4)
- return RuntimeSupport::ArgumentType::ValueRef;
- else
- return RuntimeSupport::ArgumentType::Invalid;
- }
-
- switch (arg) {
- case 0: return operateOnRuntimeCall<MethodArg1TyOperation, RuntimeSupport::ArgumentType>(m);
- case 1: return operateOnRuntimeCall<MethodArg2TyOperation, RuntimeSupport::ArgumentType>(m);
- case 2: return operateOnRuntimeCall<MethodArg3TyOperation, RuntimeSupport::ArgumentType>(m);
- case 3: return operateOnRuntimeCall<MethodArg4TyOperation, RuntimeSupport::ArgumentType>(m);
- case 4: return operateOnRuntimeCall<MethodArg5TyOperation, RuntimeSupport::ArgumentType>(m);
- case 5: return operateOnRuntimeCall<MethodArg6TyOperation, RuntimeSupport::ArgumentType>(m);
- default: return RuntimeSupport::ArgumentType::Invalid;
- }
-}
-
-bool CallPayload::needsStorageOnJSStack(Operation::Kind m, unsigned arg, const Operation *op,
- Type nodeType)
-{
- auto argTy = untranslatedArgumentType(m, arg);
- if (argTy == RuntimeSupport::ArgumentType::ValueArray)
- return true;
- if (argTy != RuntimeSupport::ArgumentType::ValueRef)
- return false;
-
- if (op->kind() == Meta::Constant)
- return true;
-
- return !nodeType.isObject() && !nodeType.isRawPointer() && !nodeType.isAny();
-}
-
-template<typename Method>
-struct MethodRetTyOperation
-{
- static constexpr RuntimeSupport::ArgumentType doIt() { return RuntimeSupport::retType<Method>(); }
-};
-
-Type CallPayload::returnType(Operation::Kind m)
-{
- if (m == Meta::JSTailCall)
- return Type();
-
- auto t = operateOnRuntimeCall<MethodRetTyOperation, RuntimeSupport::ArgumentType>(m);
- return translateType(t);
-}
-
-static int firstArgumentPositionForType(Operation::Kind m, RuntimeSupport::ArgumentType type)
-{
- if (operateOnRuntimeCall<MethodArg1TyOperation, RuntimeSupport::ArgumentType>(m) == type)
- return 1;
- if (operateOnRuntimeCall<MethodArg2TyOperation, RuntimeSupport::ArgumentType>(m) == type)
- return 2;
- if (operateOnRuntimeCall<MethodArg3TyOperation, RuntimeSupport::ArgumentType>(m) == type)
- return 3;
- if (operateOnRuntimeCall<MethodArg4TyOperation, RuntimeSupport::ArgumentType>(m) == type)
- return 4;
- if (operateOnRuntimeCall<MethodArg5TyOperation, RuntimeSupport::ArgumentType>(m) == type)
- return 5;
- if (operateOnRuntimeCall<MethodArg6TyOperation, RuntimeSupport::ArgumentType>(m) == type)
- return 6;
- return -1;
-}
-
-unsigned CallPayload::varArgsStart(Operation::Kind m)
-{
- if (m == Meta::JSTailCall)
- return 4 - 1;
-
- int pos = firstArgumentPositionForType(m, RuntimeSupport::ArgumentType::ValueArray) - 1;
- Q_ASSERT(pos >= 0);
- return pos;
-}
-
-bool CallPayload::isVarArgsCall(Operation::Kind m)
-{
- if (m == Meta::JSTailCall)
- return true;
- if (lastArgumentIsOutputValue(m))
- return false;
- return firstArgumentPositionForType(m, RuntimeSupport::ArgumentType::ValueArray) != -1;
-}
-
-bool CallPayload::isVarArgsCall() const
-{
- return isVarArgsCall(m_callee);
-}
-
-template<typename Method>
-struct MethodsLastArgumentIsOutputValue
-{
- static constexpr bool doIt() { return Method::lastArgumentIsOutputValue; }
-};
-
-bool CallPayload::lastArgumentIsOutputValue(Operation::Kind m)
-{
- return operateOnRuntimeCall<MethodsLastArgumentIsOutputValue, bool>(m);
-}
-
-template<typename Method>
-struct MethodChangesContext
-{
- static constexpr bool doIt() { return Method::changesContext; }
-};
-
-bool CallPayload::changesContext(Operation::Kind m)
-{
- return operateOnRuntimeCall<MethodChangesContext, bool>(m);
-}
-
-template<typename Method>
-struct MethodIsPure
-{
- static constexpr bool doIt() { return Method::pure; }
-};
-
-bool CallPayload::isPure(Operation::Kind m)
-{
- return operateOnRuntimeCall<MethodIsPure, bool>(m);
-}
-
-template<typename Method>
-struct MethodCanThrow
-{
- static constexpr bool doIt() { return Method::throws; }
-};
-
-bool CallPayload::canThrow(Operation::Kind m)
-{
- switch (m) {
- case Meta::Throw: Q_FALLTHROUGH();
- case Meta::ThrowReferenceError:
- // the execution path following these instructions is already linked up to the exception handler
- return false;
- case Meta::JSIteratorNext: Q_FALLTHROUGH();
- case Meta::JSIteratorNextForYieldStar:
- // special case: see GraphBuilder::generate_IteratorNext
- return false;
- default:
- return operateOnRuntimeCall<MethodCanThrow, bool>(m);
- }
-}
-
-bool CallPayload::takesEngineAsArg(Operation::Kind m, int arg)
-{
- return untranslatedArgumentType(m, arg) == RuntimeSupport::ArgumentType::Engine;
-}
-
-bool CallPayload::takesFunctionAsArg(Operation::Kind m, int arg)
-{
- return untranslatedArgumentType(m, arg) == RuntimeSupport::ArgumentType::Function;
-}
-
-bool CallPayload::takesFrameAsArg(Operation::Kind m, int arg)
-{
- return untranslatedArgumentType(m, arg) == RuntimeSupport::ArgumentType::Frame;
-}
-
-template<typename Method>
-struct GetMethodPtr
-{
- static constexpr void *doIt() { return reinterpret_cast<void *>(&Method::call); }
-};
-
-void *CallPayload::getMethodPtr(Operation::Kind m)
-{
- return operateOnRuntimeCall<GetMethodPtr, void *>(m);
-}
-
-} // IR namespace
-} // QV4 namespace
-QT_END_NAMESPACE