9#include <QtQml/private/qv4mm_p.h>
10#include <QtCore/QHash>
11#include <QtCore/private/qnumeric_p.h>
15void Heap::StringOrSymbol::markObjects(Heap::Base *that, MarkStack *markStack)
17 StringOrSymbol *s =
static_cast<StringOrSymbol *>(that);
18 Heap::StringOrSymbol *id = s->identifier.asStringOrSymbol();
23void Heap::String::markObjects(Heap::Base *that, MarkStack *markStack)
25 StringOrSymbol::markObjects(that, markStack);
26 String *s =
static_cast<String *>(that);
27 if (s->subtype < StringType_Complex)
30 ComplexString *cs =
static_cast<ComplexString *>(s);
31 if (cs->subtype == StringType_AddedString) {
32 cs->left->mark(markStack);
33 cs->right->mark(markStack);
35 Q_ASSERT(cs->subtype == StringType_SubString);
36 cs->left->mark(markStack);
44bool String::virtualIsEqualTo(Managed *t, Managed *o)
49 if (!o->vtable()->isString)
52 return static_cast<String *>(t)->isEqualTo(
static_cast<String *>(o));
56void Heap::String::init(
const QString &t)
58 QString mutableText(t);
59 StringOrSymbol::init(mutableText.data_ptr());
60 subtype = String::StringType_Unknown;
63void Heap::ComplexString::init(String *l, String *r)
65 StringOrSymbol::init();
66 subtype = String::StringType_AddedString;
70 len = left->length() + right->length();
71 if (left->subtype >= StringType_Complex)
72 largestSubLength =
static_cast<ComplexString *>(left)->largestSubLength;
74 largestSubLength = left->length();
75 if (right->subtype >= StringType_Complex)
76 largestSubLength = qMax(largestSubLength,
static_cast<ComplexString *>(right)->largestSubLength);
78 largestSubLength = qMax(largestSubLength, right->length());
81 if (len > 256 && len >= 2*largestSubLength)
85void Heap::ComplexString::init(Heap::String *ref,
int from,
int len)
87 Q_ASSERT(ref->length() >= from + len);
88 StringOrSymbol::init();
90 subtype = String::StringType_SubString;
97void Heap::StringOrSymbol::destroy()
99 if (subtype < Heap::String::StringType_AddedString) {
100 internalClass->engine->memoryManager->changeUnmanagedHeapSizeUsage(
101 qptrdiff(-text()->size) * qptrdiff(
sizeof(QChar)));
103 text().~QStringPrivate();
107uint String::toUInt(
bool *ok)
const
111 if (subtype() >= Heap::String::StringType_Unknown)
112 d()->createHashValue();
113 if (subtype() == Heap::String::StringType_ArrayIndex)
114 return d()->stringHash;
117 double d = RuntimeHelpers::stringToNumber(toQString());
125void String::createPropertyKeyImpl()
const
127 if (d()->subtype >= Heap::String::StringType_AddedString)
128 d()->simplifyString();
129 Q_ASSERT(d()->subtype < Heap::String::StringType_AddedString);
130 engine()->identifierTable->asPropertyKey(
this);
133void Heap::String::simplifyString()
const
135 Q_ASSERT(subtype >= StringType_AddedString);
138 QString result(l, Qt::Uninitialized);
139 QChar *ch =
const_cast<QChar *>(result.constData());
141 text() = result.data_ptr();
142 const ComplexString *cs =
static_cast<
const ComplexString *>(
this);
143 identifier = PropertyKey::invalid();
144 cs->left = cs->right =
nullptr;
146 internalClass->engine->memoryManager->changeUnmanagedHeapSizeUsage(
147 qptrdiff(text().size) * qptrdiff(
sizeof(QChar)));
148 subtype = StringType_Unknown;
151bool Heap::String::startsWithUpper()
const
153 if (subtype == StringType_AddedString)
154 return static_cast<
const Heap::ComplexString *>(
this)->left->startsWithUpper();
156 const Heap::String *str =
this;
158 if (subtype == StringType_SubString) {
159 const ComplexString *cs =
static_cast<
const Heap::ComplexString *>(
this);
163 if (cs->left->subtype >= Heap::String::StringType_Complex)
164 cs->left->simplifyString();
168 Q_ASSERT(str->subtype < Heap::String::StringType_Complex);
169 return str->text().size > offset && QChar::isUpper(str->text().data()[offset]);
172void Heap::String::append(
const String *data, QChar *ch)
177 enum StatusTag :
bool { NotVisited, Visited };
178 using Pointer = QTaggedPointer<
const String, StatusTag>;
180 std::vector<Pointer> worklist;
181 worklist.reserve(32);
182 worklist.push_back(Pointer(data));
184 while (!worklist.empty()) {
185 Pointer item = worklist.back();
186 if (item.tag() == Visited) {
187 Q_ASSERT(item->subtype == StringType_AddedString);
188 const ComplexString *cs =
static_cast<
const ComplexString *>(item.data());
190 worklist.push_back(Pointer(cs->right));
194 if (item->subtype == StringType_AddedString) {
196 worklist.back().setTag(Visited);
197 const ComplexString *cs =
static_cast<
const ComplexString *>(item.data());
198 worklist.push_back(Pointer(cs->left));
199 }
else if (item->subtype == StringType_SubString) {
201 const ComplexString *cs =
static_cast<
const ComplexString *>(item.data());
202 memcpy(ch, cs->left->toQString().constData() + cs->from, cs->len*
sizeof(QChar));
206 memcpy(
static_cast<
void *>(ch), item->text().data(), item->text().size *
sizeof(QChar));
207 ch += item->text().size;
212void Heap::StringOrSymbol::createHashValue()
const
214 if (subtype >= StringType_AddedString) {
215 Q_ASSERT(internalClass->vtable->isString);
216 static_cast<
const Heap::String *>(
this)->simplifyString();
218 Q_ASSERT(subtype < StringType_AddedString);
219 const QChar *ch =
reinterpret_cast<
const QChar *>(text().data());
220 const QChar *end = ch + text().size;
221 stringHash = QV4::String::calculateHashValue(ch, end, &subtype);
224qint64 String::virtualGetLength(
const Managed *m)
226 return static_cast<
const String *>(m)->d()->length();
DEFINE_MANAGED_VTABLE(String)
DEFINE_MANAGED_VTABLE(StringOrSymbol)