aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jit/qv4ir.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/jit/qv4ir.cpp')
-rw-r--r--src/qml/jit/qv4ir.cpp382
1 files changed, 0 insertions, 382 deletions
diff --git a/src/qml/jit/qv4ir.cpp b/src/qml/jit/qv4ir.cpp
deleted file mode 100644
index cb3eeeec60..0000000000
--- a/src/qml/jit/qv4ir.cpp
+++ /dev/null
@@ -1,382 +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 <private/qqmlglobal_p.h>
-#include "qv4ir_p.h"
-#include "qv4node_p.h"
-#include "qv4function_p.h"
-#include <qv4graph_p.h>
-#include "qv4stackframe_p.h"
-#include "qv4operation_p.h"
-#include "qv4util_p.h"
-
-#include <QtCore/qloggingcategory.h>
-#include <QtCore/qjsonobject.h>
-#include <QtCore/qjsonarray.h>
-#include <QtCore/qfile.h>
-
-QT_BEGIN_NAMESPACE
-namespace QV4 {
-namespace IR {
-
-Q_LOGGING_CATEGORY(lcJsonIR, "qt.v4.ir.json");
-Q_LOGGING_CATEGORY(lcDotIR, "qt.v4.ir.dot");
-Q_LOGGING_CATEGORY(lcVerify, "qt.v4.ir.verify");
-
-Function::Function(QV4::Function *qv4Function)
- : qv4Function(qv4Function)
- , m_graph(Graph::create(this))
- , m_dumper(nullptr)
- , m_nodeInfo(128, nullptr)
-{
-}
-
-Function::~Function()
-{
- delete m_dumper;
-}
-
-QString Function::name() const
-{
- QString name;
- if (auto n = v4Function()->name())
- name = n->toQString();
- if (name.isEmpty())
- name = QString::asprintf("%p", v4Function());
- auto loc = v4Function()->sourceLocation();
- return name + QStringLiteral(" (%1:%2:%3)").arg(loc.sourceFile, QString::number(loc.line),
- QString::number(loc.column));
-}
-
-void Function::dump(const QString &description) const
-{
- Dumper::dump(this, description);
-}
-
-void Function::dump() const
-{
- dump(QStringLiteral("Debug:"));
-}
-
-Dumper *Function::dumper() const
-{
- if (!m_dumper)
- m_dumper = new Dumper(this);
- return m_dumper;
-}
-
-Function::StringId Function::addString(const QString &s)
-{
- m_stringPool.push_back(s);
- return m_stringPool.size() - 1;
-}
-
-NodeInfo *Function::nodeInfo(Node *n, bool createIfNecessary) const
-{
- if (n->id() >= m_nodeInfo.size())
- m_nodeInfo.resize(n->id() * 2, nullptr);
-
- NodeInfo *&info = m_nodeInfo[n->id()];
- if (info == nullptr && createIfNecessary) {
- info = m_pool.New<NodeInfo>();
- info->setType(n->operation()->type());
- }
- return info;
-}
-
-void Function::copyBytecodeOffsets(Node *from, Node *to)
-{
- auto toInfo = nodeInfo(to);
- if (auto fromInfo = nodeInfo(from)) {
- toInfo->setBytecodeOffsets(fromInfo->currentInstructionOffset(),
- fromInfo->nextInstructionOffset());
- }
-}
-
-Dumper::Dumper(const Function *f)
-{
- if (!f)
- return;
-}
-
-void Dumper::dump(const Function *f, const QString &description)
-{
- if (false && lcJsonIR().isDebugEnabled()) {
- Dumper *dumper = f->dumper();
-
- qCDebug(lcJsonIR).noquote().nospace() << description + QLatin1String(":\n");
- for (const auto &line : dumper->dump(f).split('\n'))
- qCDebug(lcJsonIR).noquote().nospace() << line;
- }
-
- if (lcDotIR().isDebugEnabled())
- dot(f, description);
-}
-
-QByteArray Dumper::dump(const Function *f)
-{
- QJsonObject fo;
-
- {
- QString name;
- if (auto n = f->v4Function()->name())
- name = n->toQString();
- fo[QLatin1String("_searchKey")] = QStringLiteral("function %1").arg(name);
- if (name.isEmpty())
- name = QString::asprintf("%p", f->v4Function());
- fo[QLatin1String("name")] = name;
- }
-
- auto loc = f->v4Function()->sourceLocation();
- fo[QLatin1String("source")] = loc.sourceFile;
- fo[QLatin1String("line")] = loc.line;
- fo[QLatin1String("column")] = loc.column;
-
- {
- QJsonArray gn;
- QJsonArray ge;
- NodeCollector nodes(f->graph(), /*collectUses =*/ true);
- nodes.sortById();
- for (Node *n : nodes.reachable()) {
- gn.append(dump(n, f));
- int inputIndex = 0;
- for (Node *input : n->inputs()) {
- QJsonObject edge;
- edge[QLatin1String("from")] = int(input->id());
- edge[QLatin1String("to")] = int(n->id());
- edge[QLatin1String("index")] = inputIndex;
- if (inputIndex < n->operation()->valueInputCount()) {
- edge[QLatin1String("type")] = QLatin1String("value");
- } else if (inputIndex < n->operation()->valueInputCount()
- + n->operation()->effectInputCount()) {
- edge[QLatin1String("type")] = QLatin1String("effect");
- } else {
- edge[QLatin1String("type")] = QLatin1String("control");
- }
- Q_ASSERT(inputIndex < n->operation()->valueInputCount()
- + n->operation()->effectInputCount()
- + n->operation()->controlInputCount());
- ge.append(edge);
- ++inputIndex;
- }
- }
- QJsonObject g;
- g[QLatin1String("nodes")] = gn;
- g[QLatin1String("edges")] = ge;
- fo[QLatin1String("graph")] = g;
- }
-
- m_doc.setObject(fo);
- return m_doc.toJson(QJsonDocument::Indented);
-}
-
-QJsonValue toJSonValue(QV4::Value v)
-{
- switch (v.type()) {
- case QV4::Value::Undefined_Type: return QJsonValue(QJsonValue::Undefined);
- case QV4::Value::Null_Type: return QJsonValue(QJsonValue::Null);
- case QV4::Value::Boolean_Type: return QJsonValue(v.booleanValue());
- case QV4::Value::Integer_Type: return QJsonValue(v.int_32());
- case QV4::Value::Managed_Type:
- if (String *s = v.stringValue())
- return QJsonValue(s->toQString());
- else
- return QJsonValue(QLatin1String("<managed>"));
- default: return QJsonValue(v.doubleValue());
- }
-}
-
-QJsonValue Dumper::dump(const Node * const node, const Function *f)
-{
- QJsonObject n;
- n[QLatin1String("id")] = int(node->id());
- n[QLatin1String("kind")] = node->operation()->debugString();
- switch (node->operation()->kind()) {
- case Meta::Parameter: {
- auto info = ParameterPayload::get(*node->operation());
- n[QLatin1String("name")] = f->string(info->stringId());
- n[QLatin1String("index")] = int(info->parameterIndex());
- break;
- }
- case Meta::Constant: {
- auto info = ConstantPayload::get(*node->operation());
- n[QLatin1String("value")] = toJSonValue(info->value());
- break;
- }
- default:
- break;
- }
- return n;
-}
-
-void Dumper::dot(const Function *f, const QString &description)
-{
- static const bool skipFramestate = qEnvironmentVariableIsSet("QV4_JIT_DOT_SKIP_FRAMESTATE");
-
- auto node = [](Node *n) {
- return QStringLiteral("n%1[label=\"%1: %2%3\"];\n").arg(QString::number(n->id()),
- n->operation()->debugString(),
- n->isDead() ? QStringLiteral(" (dead)")
- : QString());
- };
-
- Graph *g = f->graph();
- QString out;
- out += QLatin1Char('\n');
- out += QStringLiteral("digraph{root=\"n%1\" label=\"%2\";"
- "node[shape=rect];"
- "edge[dir=back fontsize=10];\n")
- .arg(g->startNode()->id())
- .arg(description);
- out += node(g->startNode());
- const bool dumpUses = false; // set to true to see all nodes
- NodeCollector nodes(g, dumpUses, skipFramestate);
- for (Node *n : nodes.reachable()) {
- if (n == g->startNode())
- continue;
-
- out += node(n);
-
- unsigned inputIndex = 0;
- for (Node *input : n->inputs()) {
- if (input == nullptr)
- continue;
- out += QStringLiteral("n%2->n%1[style=").arg(QString::number(n->id()),
- QString::number(input->id()));
- if (inputIndex < n->operation()->valueInputCount() ||
- inputIndex == n->operation()->indexOfFrameStateInput()) {
- out += QStringLiteral("solid headlabel=\"%1\"").arg(inputIndex);
- } else if (inputIndex < unsigned(n->operation()->valueInputCount()
- + n->operation()->effectInputCount())) {
- out += QStringLiteral("dotted headlabel=\"%1\"").arg(inputIndex);
- } else {
- out += QStringLiteral("dashed headlabel=\"%1\"").arg(inputIndex);
- }
- out += QStringLiteral("];\n");
- ++inputIndex;
- }
- }
- out += QStringLiteral("}\n");
- qCDebug(lcDotIR).nospace().noquote() << out;
-
- QFile of(description + QStringLiteral(".dot"));
- of.open(QIODevice::WriteOnly);
- of.write(out.toUtf8());
- of.close();
-}
-
-void Function::verify() const
-{
-#ifndef QT_NO_DEBUG
- unsigned problemsFound = 0;
-
- auto verifyNodeAgainstOperation = [&problemsFound](const Node *n) {
- const Operation *op = n->operation();
- if (op->totalInputCount() != n->inputCount()) {
- ++problemsFound;
- qCDebug(lcVerify()) << "Node" << n->id() << "has" << n->inputCount()
- << "inputs, but it's operation" << op->debugString()
- << "requires" << op->totalInputCount() << "inputs";
- }
-
- if (n->opcode() == Meta::Phi || n->opcode() == Meta::EffectPhi) {
- if (n->controlInput()->opcode() != Meta::Region) {
- ++problemsFound;
- qCDebug(lcVerify()) << "Control input of phi node" << n->id() << "is not a region";
- }
- if (n->controlInput()->inputCount() + 1 != n->inputCount()) {
- ++problemsFound;
- qCDebug(lcVerify()) << "Control input of phi node" << n->id()
- << "has" << n->controlInput()->inputCount()
- << "inputs while phi node has" << n->inputCount()
- << "inputs";
- }
- }
-
- //### todo: verify outputs: value outputs are allowed to be unused, but the effect and
- // control outputs have to be linked up, except:
- //### todo: verify if no use is a nullptr, except for operations that can throw, where the
- // last one is allowed to be a nullptr when an unwind handler is missing.
- };
-
- NodeWorkList todo(graph());
- todo.enqueue(graph()->endNode());
- while (Node *n = todo.dequeueNextNodeForVisiting()) {
- todo.enqueueAllInputs(n);
- todo.enqueueAllUses(n);
-
- verifyNodeAgainstOperation(n);
- }
- //### TODO:
- if (problemsFound != 0) {
- dump(QStringLiteral("Problematic graph"));
- qFatal("Found %u problems during graph verification!", problemsFound);
- }
-#endif // QT_NO_xDEBUG
-}
-
-QString Type::debugString() const
-{
- if (isNone())
- return QStringLiteral("none");
- if (isInvalid())
- return QStringLiteral("invalid");
-
- QStringList s;
- if (m_t & Bool)
- s += QStringLiteral("boolean");
- if (m_t & Int32)
- s += QStringLiteral("int32");
- if (m_t & Double)
- s += QStringLiteral("double");
- if (m_t & Undefined)
- s += QStringLiteral("undefined");
- if (m_t & Null)
- s += QStringLiteral("null");
- if (m_t & Empty)
- s += QStringLiteral("empty");
- if (m_t & RawPointer)
- s += QStringLiteral("raw pointer");
-
- return s.join(QLatin1String(" "));
-}
-
-} // IR namespace
-} // QV4 namespace
-QT_END_NAMESPACE