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