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.cpp106
1 files changed, 75 insertions, 31 deletions
diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp
index b38b01c9f7..447992ebec 100644
--- a/src/qml/jsruntime/qv4string.cpp
+++ b/src/qml/jsruntime/qv4string.cpp
@@ -55,9 +55,16 @@ using namespace QV4;
void Heap::String::markObjects(Heap::Base *that, MarkStack *markStack)
{
String *s = static_cast<String *>(that);
- if (s->largestSubLength) {
- s->left->mark(markStack);
- s->right->mark(markStack);
+ if (s->subtype < StringType_Complex)
+ return;
+
+ ComplexString *cs = static_cast<ComplexString *>(s);
+ if (cs->subtype == StringType_AddedString) {
+ cs->left->mark(markStack);
+ cs->right->mark(markStack);
+ } else {
+ Q_ASSERT(cs->subtype == StringType_SubString);
+ cs->left->mark(markStack);
}
}
@@ -84,37 +91,45 @@ void Heap::String::init(const QString &t)
text = const_cast<QString &>(t).data_ptr();
text->ref.ref();
- identifier = 0;
- stringHash = UINT_MAX;
- largestSubLength = 0;
- len = text->size;
}
-void Heap::String::init(String *l, String *r)
+void Heap::ComplexString::init(String *l, String *r)
{
Base::init();
- subtype = String::StringType_Unknown;
+ subtype = String::StringType_AddedString;
left = l;
right = r;
- stringHash = UINT_MAX;
- largestSubLength = qMax(l->largestSubLength, r->largestSubLength);
- len = l->len + r->len;
- Q_ASSERT(largestSubLength <= len);
-
- if (!l->largestSubLength && l->len > largestSubLength)
- largestSubLength = l->len;
- if (!r->largestSubLength && r->len > largestSubLength)
- largestSubLength = r->len;
+ len = left->length() + right->length();
+ if (left->subtype >= StringType_Complex)
+ largestSubLength = static_cast<ComplexString *>(left)->largestSubLength;
+ else
+ largestSubLength = left->length();
+ if (right->subtype >= StringType_Complex)
+ largestSubLength = qMax(largestSubLength, static_cast<ComplexString *>(right)->largestSubLength);
+ else
+ largestSubLength = qMax(largestSubLength, right->length());
// make sure we don't get excessive depth in our strings
if (len > 256 && len >= 2*largestSubLength)
simplifyString();
}
+void Heap::ComplexString::init(Heap::String *ref, int from, int len)
+{
+ Q_ASSERT(ref->length() >= from + len);
+ Base::init();
+
+ subtype = String::StringType_SubString;
+
+ left = ref;
+ this->from = from;
+ this->len = len;
+}
+
void Heap::String::destroy() {
- if (!largestSubLength) {
+ if (text) {
internalClass->engine->memoryManager->changeUnmanagedHeapSizeUsage(qptrdiff(-text->size) * (int)sizeof(QChar));
if (!text->ref.deref())
QStringData::deallocate(text);
@@ -126,7 +141,7 @@ uint String::toUInt(bool *ok) const
{
*ok = true;
- if (subtype() == Heap::String::StringType_Unknown)
+ if (subtype() >= Heap::String::StringType_Unknown)
d()->createHashValue();
if (subtype() == Heap::String::StringType_ArrayIndex)
return d()->stringHash;
@@ -142,15 +157,15 @@ uint String::toUInt(bool *ok) const
void String::makeIdentifierImpl() const
{
- if (d()->largestSubLength)
+ if (!d()->text)
d()->simplifyString();
- Q_ASSERT(!d()->largestSubLength);
+ Q_ASSERT(d()->text);
engine()->identifierTable->identifier(this);
}
void Heap::String::simplifyString() const
{
- Q_ASSERT(largestSubLength);
+ Q_ASSERT(!text);
int l = length();
QString result(l, Qt::Uninitialized);
@@ -158,9 +173,33 @@ void Heap::String::simplifyString() const
append(this, ch);
text = result.data_ptr();
text->ref.ref();
- identifier = 0;
- largestSubLength = 0;
+ const ComplexString *cs = static_cast<const ComplexString *>(this);
+ identifier = nullptr;
+ cs->left = cs->right = nullptr;
+
internalClass->engine->memoryManager->changeUnmanagedHeapSizeUsage(qptrdiff(text->size) * (qptrdiff)sizeof(QChar));
+ subtype = StringType_Unknown;
+}
+
+bool Heap::String::startsWithUpper() const
+{
+ if (subtype == StringType_AddedString)
+ return static_cast<const Heap::ComplexString *>(this)->left->startsWithUpper();
+
+ const Heap::String *str = this;
+ int offset = 0;
+ if (subtype == StringType_SubString) {
+ const ComplexString *cs = static_cast<const Heap::ComplexString *>(this);
+ if (!cs->len)
+ return false;
+ // simplification here is not ideal, but hopefully not a common case.
+ if (cs->left->subtype >= Heap::String::StringType_Complex)
+ cs->left->simplifyString();
+ str = cs->left;
+ offset = cs->from;
+ }
+ Q_ASSERT(str->subtype < Heap::String::StringType_Complex);
+ return str->text->size > offset && QChar::isUpper(str->text->data()[offset]);
}
void Heap::String::append(const String *data, QChar *ch)
@@ -173,11 +212,16 @@ void Heap::String::append(const String *data, QChar *ch)
const String *item = worklist.back();
worklist.pop_back();
- if (item->largestSubLength) {
- worklist.push_back(item->right);
- worklist.push_back(item->left);
+ if (item->subtype == StringType_AddedString) {
+ const ComplexString *cs = static_cast<const ComplexString *>(item);
+ worklist.push_back(cs->right);
+ worklist.push_back(cs->left);
+ } else if (item->subtype == StringType_SubString) {
+ const ComplexString *cs = static_cast<const ComplexString *>(item);
+ memcpy(ch, cs->left->toQString().constData() + cs->from, cs->len*sizeof(QChar));
+ ch += cs->len;
} else {
- memcpy(ch, item->text->data(), item->text->size * sizeof(QChar));
+ memcpy(static_cast<void *>(ch), static_cast<const void *>(item->text->data()), item->text->size * sizeof(QChar));
ch += item->text->size;
}
}
@@ -185,9 +229,9 @@ void Heap::String::append(const String *data, QChar *ch)
void Heap::String::createHashValue() const
{
- if (largestSubLength)
+ if (!text)
simplifyString();
- Q_ASSERT(!largestSubLength);
+ Q_ASSERT(text);
const QChar *ch = reinterpret_cast<const QChar *>(text->data());
const QChar *end = ch + text->size;
stringHash = QV4::String::calculateHashValue(ch, end, &subtype);