diff options
author | Lars Knoll <lars.knoll@qt.io> | 2018-01-03 15:37:32 +0100 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2018-01-19 10:13:54 +0000 |
commit | 1fe206712755b0d99f91bc7897f0a705ec583f2d (patch) | |
tree | b5fee1288c60f8d9b60e7b5147ab7ebe4c6b1a2c | |
parent | 959ad9f998c340257a4027db4bed3a5639a8f48f (diff) |
Introduce a SubString String type
Use it in regexp matching. There's probably other places where
we should use this as well.
Change-Id: Ie2774acff0a5ec7b1c26c564fa40e65fecea29d4
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-rw-r--r-- | src/qml/jsruntime/qv4regexpobject.cpp | 4 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4string.cpp | 32 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4string_p.h | 10 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4stringobject.cpp | 16 |
4 files changed, 50 insertions, 12 deletions
diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp index f95719b25f..9a5afdf308 100644 --- a/src/qml/jsruntime/qv4regexpobject.cpp +++ b/src/qml/jsruntime/qv4regexpobject.cpp @@ -343,7 +343,7 @@ ReturnedValue RegExpPrototype::execFirstMatch(const FunctionObject *b, const Val if (r->value()->captureCount()) { int start = matchOffsets[0]; int end = matchOffsets[1]; - retVal = (start != -1) ? scope.engine->newString(s.mid(start, end - start))->asReturnedValue() : Encode::undefined(); + retVal = (start != -1) ? scope.engine->memoryManager->alloc<ComplexString>(str->d(), start, end - start)->asReturnedValue() : Encode::undefined(); } RegExpCtor::Data *dd = regExpCtor->d(); @@ -394,7 +394,7 @@ ReturnedValue RegExpPrototype::method_exec(const FunctionObject *b, const Value for (int i = 0; i < len; ++i) { int start = matchOffsets[i * 2]; int end = matchOffsets[i * 2 + 1]; - v = (start != -1) ? scope.engine->newString(s.mid(start, end - start))->asReturnedValue() : Encode::undefined(); + v = (start != -1) ? scope.engine->memoryManager->alloc<ComplexString>(str->d(), start, end - start)->asReturnedValue() : Encode::undefined(); array->arrayPut(i, v); } array->setArrayLengthUnchecked(len); diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp index bdfb8af3f6..932ccf13ef 100644 --- a/src/qml/jsruntime/qv4string.cpp +++ b/src/qml/jsruntime/qv4string.cpp @@ -59,8 +59,13 @@ void Heap::String::markObjects(Heap::Base *that, MarkStack *markStack) return; ComplexString *cs = static_cast<ComplexString *>(s); - cs->left->mark(markStack); - cs->right->mark(markStack); + if (cs->subtype == StringType_AddedString) { + cs->left->mark(markStack); + cs->right->mark(markStack); + } else { + Q_ASSERT(cs->subtype == StringType_SubString); + cs->left->mark(markStack); + } } DEFINE_MANAGED_VTABLE(String); @@ -111,6 +116,18 @@ void Heap::ComplexString::init(String *l, String *r) 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 (text) { internalClass->engine->memoryManager->changeUnmanagedHeapSizeUsage(qptrdiff(-text->size) * (int)sizeof(QChar)); @@ -124,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; @@ -156,7 +173,10 @@ void Heap::String::simplifyString() const append(this, ch); text = result.data_ptr(); text->ref.ref(); + const ComplexString *cs = static_cast<const ComplexString *>(this); identifier = 0; + cs->left = cs->right = nullptr; + internalClass->engine->memoryManager->changeUnmanagedHeapSizeUsage(qptrdiff(text->size) * (qptrdiff)sizeof(QChar)); subtype = StringType_Unknown; } @@ -171,10 +191,14 @@ void Heap::String::append(const String *data, QChar *ch) const String *item = worklist.back(); worklist.pop_back(); - if (item->subtype >= StringType_Complex) { + 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)); ch += item->text->size; diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h index d1b38f4336..41039bca88 100644 --- a/src/qml/jsruntime/qv4string_p.h +++ b/src/qml/jsruntime/qv4string_p.h @@ -71,6 +71,7 @@ struct Q_QML_PRIVATE_EXPORT String : Base { StringType_ArrayIndex, StringType_Unknown, StringType_AddedString, + StringType_SubString, StringType_Complex = StringType_AddedString }; @@ -124,10 +125,13 @@ Q_STATIC_ASSERT(std::is_trivial< String >::value); #ifndef V4_BOOTSTRAP struct ComplexString : String { void init(String *l, String *n); - mutable uint nestingLevel; + void init(String *ref, int from, int len); mutable String *left; mutable String *right; - mutable int largestSubLength; + union { + mutable int largestSubLength; + int from; + }; int len; }; Q_STATIC_ASSERT(std::is_trivial< ComplexString >::value); @@ -172,7 +176,7 @@ struct Q_QML_PRIVATE_EXPORT String : public Managed { return d()->hashValue(); } uint asArrayIndex() const { - if (subtype() == Heap::String::StringType_Unknown) + if (subtype() >= Heap::String::StringType_Unknown) d()->createHashValue(); Q_ASSERT(d()->subtype < Heap::String::StringType_Complex); if (subtype() == Heap::String::StringType_ArrayIndex) diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp index b4c50170cf..4cc4a5c0cb 100644 --- a/src/qml/jsruntime/qv4stringobject.cpp +++ b/src/qml/jsruntime/qv4stringobject.cpp @@ -200,6 +200,15 @@ void StringPrototype::init(ExecutionEngine *engine, Object *ctor) defineDefaultProperty(QStringLiteral("trim"), method_trim); } +static Heap::String *thisAsString(ExecutionEngine *v4, const Value *thisObject) +{ + if (String *s = thisObject->stringValue()) + return s->d(); + if (const StringObject *thisString = thisObject->as<StringObject>()) + return thisString->d()->string; + return thisObject->toString(v4); +} + static QString getThisString(ExecutionEngine *v4, const Value *thisObject) { if (String *s = thisObject->stringValue()) @@ -649,11 +658,12 @@ ReturnedValue StringPrototype::method_search(const FunctionObject *b, const Valu ReturnedValue StringPrototype::method_slice(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc) { ExecutionEngine *v4 = b->engine(); - const QString text = getThisString(v4, thisObject); + Heap::String *s = thisAsString(v4, thisObject); if (v4->hasException) return QV4::Encode::undefined(); + Q_ASSERT(s); - const double length = text.length(); + const double length = s->length(); double start = argc ? argv[0].toInteger() : 0; double end = (argc < 2 || argv[1].isUndefined()) @@ -673,7 +683,7 @@ ReturnedValue StringPrototype::method_slice(const FunctionObject *b, const Value const int intEnd = int(end); int count = qMax(0, intEnd - intStart); - return Encode(v4->newString(text.mid(intStart, count))); + return Encode(v4->memoryManager->alloc<ComplexString>(s, intStart, count)); } ReturnedValue StringPrototype::method_split(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc) |