diff options
Diffstat (limited to 'src/qml/jsruntime/qv4string.cpp')
-rw-r--r-- | src/qml/jsruntime/qv4string.cpp | 120 |
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); } |