aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4string.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/jsruntime/qv4string.cpp')
-rw-r--r--src/qml/jsruntime/qv4string.cpp120
1 files changed, 47 insertions, 73 deletions
diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp
index 223f4a4769..8b5594b43b 100644
--- a/src/qml/jsruntime/qv4string.cpp
+++ b/src/qml/jsruntime/qv4string.cpp
@@ -1,48 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qv4string_p.h"
#include "qv4value_p.h"
#include "qv4identifiertable_p.h"
#include "qv4runtime_p.h"
-#include "qv4objectproto_p.h"
-#include "qv4stringobject_p.h"
+#include <QtQml/private/qv4mm_p.h>
#include <QtCore/QHash>
#include <QtCore/private/qnumeric_p.h>
@@ -91,18 +54,14 @@ bool String::virtualIsEqualTo(Managed *t, Managed *o)
void Heap::String::init(const QString &t)
{
- Base::init();
-
+ QString mutableText(t);
+ StringOrSymbol::init(mutableText.data_ptr());
subtype = String::StringType_Unknown;
-
- text = const_cast<QString &>(t).data_ptr();
- text->ref.ref();
}
void Heap::ComplexString::init(String *l, String *r)
{
- Base::init();
-
+ StringOrSymbol::init();
subtype = String::StringType_AddedString;
left = l;
@@ -125,7 +84,7 @@ void Heap::ComplexString::init(String *l, String *r)
void Heap::ComplexString::init(Heap::String *ref, int from, int len)
{
Q_ASSERT(ref->length() >= from + len);
- Base::init();
+ StringOrSymbol::init();
subtype = String::StringType_SubString;
@@ -136,11 +95,11 @@ void Heap::ComplexString::init(Heap::String *ref, int from, int len)
void Heap::StringOrSymbol::destroy()
{
- if (text) {
- internalClass->engine->memoryManager->changeUnmanagedHeapSizeUsage(qptrdiff(-text->size) * (int)sizeof(QChar));
- if (!text->ref.deref())
- QStringData::deallocate(text);
+ if (subtype < Heap::String::StringType_AddedString) {
+ internalClass->engine->memoryManager->changeUnmanagedHeapSizeUsage(
+ qptrdiff(-text()->size) * qptrdiff(sizeof(QChar)));
}
+ text().~QStringPrivate();
Base::destroy();
}
@@ -164,27 +123,27 @@ uint String::toUInt(bool *ok) const
void String::createPropertyKeyImpl() const
{
- if (!d()->text)
+ if (d()->subtype >= Heap::String::StringType_AddedString)
d()->simplifyString();
- Q_ASSERT(d()->text);
+ Q_ASSERT(d()->subtype < Heap::String::StringType_AddedString);
engine()->identifierTable->asPropertyKey(this);
}
void Heap::String::simplifyString() const
{
- Q_ASSERT(!text);
+ Q_ASSERT(subtype >= StringType_AddedString);
int l = length();
QString result(l, Qt::Uninitialized);
QChar *ch = const_cast<QChar *>(result.constData());
append(this, ch);
- text = result.data_ptr();
- text->ref.ref();
+ text() = result.data_ptr();
const ComplexString *cs = static_cast<const ComplexString *>(this);
identifier = PropertyKey::invalid();
cs->left = cs->right = nullptr;
- internalClass->engine->memoryManager->changeUnmanagedHeapSizeUsage(qptrdiff(text->size) * (qptrdiff)sizeof(QChar));
+ internalClass->engine->memoryManager->changeUnmanagedHeapSizeUsage(
+ qptrdiff(text().size) * qptrdiff(sizeof(QChar)));
subtype = StringType_Unknown;
}
@@ -206,43 +165,58 @@ bool Heap::String::startsWithUpper() const
offset = cs->from;
}
Q_ASSERT(str->subtype < Heap::String::StringType_Complex);
- return str->text->size > offset && QChar::isUpper(str->text->data()[offset]);
+ return str->text().size > offset && QChar::isUpper(str->text().data()[offset]);
}
void Heap::String::append(const String *data, QChar *ch)
{
- std::vector<const String *> worklist;
+ // in-order visitation with explicit stack
+ // where leaf nodes are "real" strings that get appended to ch
+
+ enum StatusTag : bool { NotVisited, Visited };
+ using Pointer = QTaggedPointer<const String, StatusTag>;
+
+ std::vector<Pointer> worklist;
worklist.reserve(32);
- worklist.push_back(data);
+ worklist.push_back(Pointer(data));
while (!worklist.empty()) {
- const String *item = worklist.back();
- worklist.pop_back();
+ Pointer item = worklist.back();
+ if (item.tag() == Visited) {
+ Q_ASSERT(item->subtype == StringType_AddedString);
+ const ComplexString *cs = static_cast<const ComplexString *>(item.data());
+ worklist.pop_back();
+ worklist.push_back(Pointer(cs->right));
+ continue;
+ }
if (item->subtype == StringType_AddedString) {
- const ComplexString *cs = static_cast<const ComplexString *>(item);
- worklist.push_back(cs->right);
- worklist.push_back(cs->left);
+ // we need to keep the node in the worklist, as we still need to handle "right"
+ worklist.back().setTag(Visited);
+ const ComplexString *cs = static_cast<const ComplexString *>(item.data());
+ worklist.push_back(Pointer(cs->left));
} else if (item->subtype == StringType_SubString) {
- const ComplexString *cs = static_cast<const ComplexString *>(item);
+ worklist.pop_back();
+ const ComplexString *cs = static_cast<const ComplexString *>(item.data());
memcpy(ch, cs->left->toQString().constData() + cs->from, cs->len*sizeof(QChar));
ch += cs->len;
} else {
- memcpy(static_cast<void *>(ch), static_cast<const void *>(item->text->data()), item->text->size * sizeof(QChar));
- ch += item->text->size;
+ worklist.pop_back();
+ memcpy(static_cast<void *>(ch), item->text().data(), item->text().size * sizeof(QChar));
+ ch += item->text().size;
}
}
}
void Heap::StringOrSymbol::createHashValue() const
{
- if (!text) {
+ if (subtype >= StringType_AddedString) {
Q_ASSERT(internalClass->vtable->isString);
static_cast<const Heap::String *>(this)->simplifyString();
}
- Q_ASSERT(text);
- const QChar *ch = reinterpret_cast<const QChar *>(text->data());
- const QChar *end = ch + text->size;
+ Q_ASSERT(subtype < StringType_AddedString);
+ const QChar *ch = reinterpret_cast<const QChar *>(text().data());
+ const QChar *end = ch + text().size;
stringHash = QV4::String::calculateHashValue(ch, end, &subtype);
}