aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-01-03 15:37:32 +0100
committerLars Knoll <lars.knoll@qt.io>2018-01-19 10:13:54 +0000
commit1fe206712755b0d99f91bc7897f0a705ec583f2d (patch)
treeb5fee1288c60f8d9b60e7b5147ab7ebe4c6b1a2c /src
parent959ad9f998c340257a4027db4bed3a5639a8f48f (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>
Diffstat (limited to 'src')
-rw-r--r--src/qml/jsruntime/qv4regexpobject.cpp4
-rw-r--r--src/qml/jsruntime/qv4string.cpp32
-rw-r--r--src/qml/jsruntime/qv4string_p.h10
-rw-r--r--src/qml/jsruntime/qv4stringobject.cpp16
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)