aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp5
-rw-r--r--src/qml/compiler/qqmlirbuilder_p.h3
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp37
-rw-r--r--src/qml/compiler/qqmltypecompiler_p.h10
-rw-r--r--src/qml/compiler/qv4codegen.cpp185
-rw-r--r--src/qml/compiler/qv4codegen_p.h14
-rw-r--r--src/qml/compiler/qv4isel_moth.cpp223
-rw-r--r--src/qml/compiler/qv4isel_moth_p.h88
-rw-r--r--src/qml/compiler/qv4isel_p.cpp118
-rw-r--r--src/qml/compiler/qv4isel_p.h84
-rw-r--r--src/qml/compiler/qv4isel_util_p.h1
-rw-r--r--src/qml/compiler/qv4jsir.cpp748
-rw-r--r--src/qml/compiler/qv4jsir_p.h221
-rw-r--r--src/qml/compiler/qv4ssa.cpp2467
-rw-r--r--src/qml/compiler/qv4ssa_p.h100
-rw-r--r--src/qml/debugger/qqmlprofilerdefinitions_p.h3
-rw-r--r--src/qml/debugger/qv4profileradapter.cpp39
-rw-r--r--src/qml/debugger/qv4profileradapter_p.h5
-rw-r--r--src/qml/doc/qtqml.qdocconf2
-rw-r--r--src/qml/doc/src/qmlfunctions.qdoc38
-rw-r--r--src/qml/jit/jit.pri2
-rw-r--r--src/qml/jit/qv4assembler.cpp131
-rw-r--r--src/qml/jit/qv4assembler_p.h373
-rw-r--r--src/qml/jit/qv4binop.cpp50
-rw-r--r--src/qml/jit/qv4binop_p.h8
-rw-r--r--src/qml/jit/qv4isel_masm.cpp437
-rw-r--r--src/qml/jit/qv4isel_masm_p.h139
-rw-r--r--src/qml/jit/qv4regalloc.cpp1292
-rw-r--r--src/qml/jit/qv4regalloc_p.h51
-rw-r--r--src/qml/jit/qv4registerinfo_p.h99
-rw-r--r--src/qml/jit/qv4targetplatform_p.h390
-rw-r--r--src/qml/jit/qv4unop.cpp35
-rw-r--r--src/qml/jit/qv4unop_p.h8
-rw-r--r--src/qml/jsapi/qjsengine.cpp42
-rw-r--r--src/qml/jsapi/qjsengine.h2
-rw-r--r--src/qml/jsapi/qjsvalue.cpp24
-rw-r--r--src/qml/jsapi/qjsvalueiterator.cpp16
-rw-r--r--src/qml/jsruntime/jsruntime.pri7
-rw-r--r--src/qml/jsruntime/qv4argumentsobject.cpp123
-rw-r--r--src/qml/jsruntime/qv4argumentsobject_p.h56
-rw-r--r--src/qml/jsruntime/qv4arraydata.cpp486
-rw-r--r--src/qml/jsruntime/qv4arraydata_p.h93
-rw-r--r--src/qml/jsruntime/qv4arrayobject.cpp191
-rw-r--r--src/qml/jsruntime/qv4arrayobject_p.h11
-rw-r--r--src/qml/jsruntime/qv4booleanobject.cpp24
-rw-r--r--src/qml/jsruntime/qv4booleanobject_p.h10
-rw-r--r--src/qml/jsruntime/qv4context.cpp341
-rw-r--r--src/qml/jsruntime/qv4context_p.h169
-rw-r--r--src/qml/jsruntime/qv4dateobject.cpp268
-rw-r--r--src/qml/jsruntime/qv4dateobject_p.h42
-rw-r--r--src/qml/jsruntime/qv4debugging.cpp34
-rw-r--r--src/qml/jsruntime/qv4debugging_p.h2
-rw-r--r--src/qml/jsruntime/qv4engine.cpp294
-rw-r--r--src/qml/jsruntime/qv4engine_p.h19
-rw-r--r--src/qml/jsruntime/qv4errorobject.cpp204
-rw-r--r--src/qml/jsruntime/qv4errorobject_p.h141
-rw-r--r--src/qml/jsruntime/qv4function.cpp5
-rw-r--r--src/qml/jsruntime/qv4function_p.h4
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp319
-rw-r--r--src/qml/jsruntime/qv4functionobject_p.h130
-rw-r--r--src/qml/jsruntime/qv4global_p.h14
-rw-r--r--src/qml/jsruntime/qv4globalobject.cpp102
-rw-r--r--src/qml/jsruntime/qv4globalobject_p.h7
-rw-r--r--src/qml/jsruntime/qv4identifier.cpp4
-rw-r--r--src/qml/jsruntime/qv4identifiertable.cpp36
-rw-r--r--src/qml/jsruntime/qv4identifiertable_p.h12
-rw-r--r--src/qml/jsruntime/qv4include.cpp51
-rw-r--r--src/qml/jsruntime/qv4internalclass.cpp63
-rw-r--r--src/qml/jsruntime/qv4internalclass_p.h3
-rw-r--r--src/qml/jsruntime/qv4jsonobject.cpp72
-rw-r--r--src/qml/jsruntime/qv4jsonobject_p.h14
-rw-r--r--src/qml/jsruntime/qv4lookup.cpp236
-rw-r--r--src/qml/jsruntime/qv4managed.cpp35
-rw-r--r--src/qml/jsruntime/qv4managed_p.h242
-rw-r--r--src/qml/jsruntime/qv4mathobject.cpp110
-rw-r--r--src/qml/jsruntime/qv4mathobject_p.h7
-rw-r--r--src/qml/jsruntime/qv4memberdata.cpp30
-rw-r--r--src/qml/jsruntime/qv4memberdata_p.h20
-rw-r--r--src/qml/jsruntime/qv4mm.cpp90
-rw-r--r--src/qml/jsruntime/qv4mm_p.h59
-rw-r--r--src/qml/jsruntime/qv4numberobject.cpp66
-rw-r--r--src/qml/jsruntime/qv4numberobject_p.h9
-rw-r--r--src/qml/jsruntime/qv4object.cpp359
-rw-r--r--src/qml/jsruntime/qv4object_p.h213
-rw-r--r--src/qml/jsruntime/qv4objectiterator.cpp80
-rw-r--r--src/qml/jsruntime/qv4objectiterator_p.h31
-rw-r--r--src/qml/jsruntime/qv4objectproto.cpp195
-rw-r--r--src/qml/jsruntime/qv4objectproto_p.h10
-rw-r--r--src/qml/jsruntime/qv4persistent_p.h2
-rw-r--r--src/qml/jsruntime/qv4profiling.cpp23
-rw-r--r--src/qml/jsruntime/qv4profiling_p.h43
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp212
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper_p.h59
-rw-r--r--src/qml/jsruntime/qv4regexp.cpp43
-rw-r--r--src/qml/jsruntime/qv4regexp_p.h95
-rw-r--r--src/qml/jsruntime/qv4regexpobject.cpp179
-rw-r--r--src/qml/jsruntime/qv4regexpobject_p.h59
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp239
-rw-r--r--src/qml/jsruntime/qv4runtime_p.h44
-rw-r--r--src/qml/jsruntime/qv4scopedvalue_p.h113
-rw-r--r--src/qml/jsruntime/qv4script.cpp126
-rw-r--r--src/qml/jsruntime/qv4script_p.h30
-rw-r--r--src/qml/jsruntime/qv4sequenceobject.cpp219
-rw-r--r--src/qml/jsruntime/qv4sequenceobject_p.h8
-rw-r--r--src/qml/jsruntime/qv4serialize.cpp8
-rw-r--r--src/qml/jsruntime/qv4string.cpp120
-rw-r--r--src/qml/jsruntime/qv4string_p.h107
-rw-r--r--src/qml/jsruntime/qv4stringobject.cpp234
-rw-r--r--src/qml/jsruntime/qv4stringobject_p.h24
-rw-r--r--src/qml/jsruntime/qv4value.cpp6
-rw-r--r--src/qml/jsruntime/qv4value_inl_p.h4
-rw-r--r--src/qml/jsruntime/qv4value_p.h12
-rw-r--r--src/qml/jsruntime/qv4variantobject.cpp68
-rw-r--r--src/qml/jsruntime/qv4variantobject_p.h24
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp50
-rw-r--r--src/qml/qml/ftw/qhashedstring_p.h2
-rw-r--r--src/qml/qml/qqml.h77
-rw-r--r--src/qml/qml/qqmlbinding.cpp38
-rw-r--r--src/qml/qml/qqmlbinding_p.h2
-rw-r--r--src/qml/qml/qqmlboundsignal.cpp2
-rw-r--r--src/qml/qml/qqmlcompiler_p.h16
-rw-r--r--src/qml/qml/qqmlcomponent.cpp116
-rw-r--r--src/qml/qml/qqmlcontextwrapper.cpp77
-rw-r--r--src/qml/qml/qqmlcontextwrapper_p.h43
-rw-r--r--src/qml/qml/qqmlcustomparser.cpp46
-rw-r--r--src/qml/qml/qqmlcustomparser_p.h10
-rw-r--r--src/qml/qml/qqmlengine.cpp8
-rw-r--r--src/qml/qml/qqmlerror.cpp11
-rw-r--r--src/qml/qml/qqmlexpression.cpp2
-rw-r--r--src/qml/qml/qqmlfileselector.cpp8
-rw-r--r--src/qml/qml/qqmlfileselector_p.h2
-rw-r--r--src/qml/qml/qqmlincubator.cpp4
-rw-r--r--src/qml/qml/qqmlinfo.cpp2
-rw-r--r--src/qml/qml/qqmljavascriptexpression.cpp2
-rw-r--r--src/qml/qml/qqmllistwrapper.cpp56
-rw-r--r--src/qml/qml/qqmllistwrapper_p.h28
-rw-r--r--src/qml/qml/qqmllocale.cpp298
-rw-r--r--src/qml/qml/qqmllocale_p.h24
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp33
-rw-r--r--src/qml/qml/qqmlproperty.cpp9
-rw-r--r--src/qml/qml/qqmltypeloader.cpp23
-rw-r--r--src/qml/qml/qqmltypeloader_p.h1
-rw-r--r--src/qml/qml/qqmltypewrapper.cpp73
-rw-r--r--src/qml/qml/qqmltypewrapper_p.h33
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp214
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper_p.h22
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp2
-rw-r--r--src/qml/qml/qqmlxmlhttprequest.cpp589
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp659
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions_p.h31
-rw-r--r--src/qml/qml/v8/qv4domerrors_p.h6
-rw-r--r--src/qml/qml/v8/qv8engine.cpp43
-rw-r--r--src/qml/qml/v8/qv8engine_p.h10
-rw-r--r--src/qml/types/qqmlconnections.cpp53
-rw-r--r--src/qml/types/qqmlconnections_p.h4
-rw-r--r--src/qml/types/qqmldelegatemodel.cpp250
-rw-r--r--src/qml/types/qqmldelegatemodel_p_p.h25
-rw-r--r--src/qml/types/qqmlinstantiator.cpp4
-rw-r--r--src/qml/types/qqmllistmodel.cpp272
-rw-r--r--src/qml/types/qqmllistmodel_p.h33
-rw-r--r--src/qml/types/qqmllistmodel_p_p.h16
-rw-r--r--src/qml/types/qquickworkerscript.cpp12
-rw-r--r--src/qml/util/qqmladaptormodel.cpp62
-rw-r--r--src/qml/util/qqmlchangeset.cpp112
-rw-r--r--src/qml/util/qqmlchangeset_p.h35
-rw-r--r--src/qml/util/qqmllistcompositor.cpp44
-rw-r--r--src/qml/util/qqmllistcompositor_p.h10
167 files changed, 10033 insertions, 8305 deletions
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index 28a4e23a37..f02e92ceb2 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -558,9 +558,8 @@ IRBuilder::IRBuilder(const QSet<QString> &illegalNames)
{
}
-bool IRBuilder::generateFromQml(const QString &code, const QString &url, const QString &urlString, Document *output)
+bool IRBuilder::generateFromQml(const QString &code, const QString &url, Document *output)
{
- this->url = url;
QQmlJS::AST::UiProgram *program = 0;
{
QQmlJS::Lexer lexer(&output->jsParserEngine);
@@ -574,7 +573,7 @@ bool IRBuilder::generateFromQml(const QString &code, const QString &url, const Q
foreach (const QQmlJS::DiagnosticMessage &m, parser.diagnosticMessages()) {
if (m.isWarning()) {
- qWarning("%s:%d : %s", qPrintable(urlString), m.loc.startLine, qPrintable(m.message));
+ qWarning("%s:%d : %s", qPrintable(url), m.loc.startLine, qPrintable(m.message));
continue;
}
diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h
index 3438af425c..1aac878776 100644
--- a/src/qml/compiler/qqmlirbuilder_p.h
+++ b/src/qml/compiler/qqmlirbuilder_p.h
@@ -343,7 +343,7 @@ struct Q_QML_PRIVATE_EXPORT IRBuilder : public QQmlJS::AST::Visitor
Q_DECLARE_TR_FUNCTIONS(QQmlCodeGenerator)
public:
IRBuilder(const QSet<QString> &illegalNames);
- bool generateFromQml(const QString &code, const QString &url, const QString &urlString, Document *output);
+ bool generateFromQml(const QString &code, const QString &url, Document *output);
static bool isSignalPropertyName(const QString &name);
@@ -420,7 +420,6 @@ public:
QQmlJS::MemoryPool *pool;
QString sourceCode;
- QString url;
QV4::Compiler::JSUnitGenerator *jsGenerator;
};
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index 60a0829b9b..e2636a57c3 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -298,7 +298,7 @@ bool QQmlTypeCompiler::compile()
void QQmlTypeCompiler::recordError(const QQmlError &error)
{
QQmlError e = error;
- e.setUrl(compiledData->url);
+ e.setUrl(url());
errors << e;
}
@@ -378,9 +378,9 @@ QHash<int, QHash<int, int> > *QQmlTypeCompiler::objectIndexToIdPerComponent()
return &compiledData->objectIndexToIdPerComponent;
}
-QHash<int, QQmlCompiledData::CustomParserData> *QQmlTypeCompiler::customParserData()
+QHash<int, QBitArray> *QQmlTypeCompiler::customParserBindings()
{
- return &compiledData->customParserData;
+ return &compiledData->customParserBindings;
}
QQmlJS::MemoryPool *QQmlTypeCompiler::memoryPool()
@@ -398,11 +398,6 @@ const QV4::Compiler::StringTableGenerator *QQmlTypeCompiler::stringPool() const
return &document->jsGenerator.stringTable;
}
-void QQmlTypeCompiler::setCustomParserBindings(const QVector<int> &bindings)
-{
- compiledData->customParserBindings = bindings;
-}
-
void QQmlTypeCompiler::setDeferredBindingsPerObject(const QHash<int, QBitArray> &deferredBindingsPerObject)
{
compiledData->deferredBindingsPerObject = deferredBindingsPerObject;
@@ -1720,7 +1715,7 @@ QQmlPropertyValidator::QQmlPropertyValidator(QQmlTypeCompiler *typeCompiler)
, customParsers(typeCompiler->customParserCache())
, propertyCaches(typeCompiler->propertyCaches())
, objectIndexToIdPerComponent(*typeCompiler->objectIndexToIdPerComponent())
- , customParserData(typeCompiler->customParserData())
+ , customParserBindingsPerObject(typeCompiler->customParserBindings())
, _seenObjectWithId(false)
{
}
@@ -1729,7 +1724,6 @@ bool QQmlPropertyValidator::validate()
{
if (!validateObject(qmlUnit->indexOfRootObject, /*instantiatingBinding*/0))
return false;
- compiler->setCustomParserBindings(customParserBindings);
compiler->setDeferredBindingsPerObject(deferredBindingsPerObject);
return true;
}
@@ -1739,13 +1733,6 @@ const QQmlImports &QQmlPropertyValidator::imports() const
return *compiler->imports();
}
-QQmlBinding::Identifier QQmlPropertyValidator::bindingIdentifier(const QV4::CompiledData::Binding *binding, QQmlCustomParser *)
-{
- const int id = customParserBindings.count();
- customParserBindings.append(binding->value.compiledScriptIndex);
- return id;
-}
-
QString QQmlPropertyValidator::bindingAsString(int objectIndex, const QV4::CompiledData::Binding *binding) const
{
const QmlIR::Object *object = compiler->qmlObjects()->value(objectIndex);
@@ -2016,11 +2003,11 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
if (customParser && !customBindings.isEmpty()) {
customParser->clearErrors();
customParser->compiler = this;
- QQmlCompiledData::CustomParserData data;
- data.bindings = customParserBindings;
- data.compilationArtifact = customParser->compile(qmlUnit, customBindings);
+ customParser->imports = compiler->imports();
+ customParser->verifyBindings(qmlUnit, customBindings);
customParser->compiler = 0;
- customParserData->insert(objectIndex, data);
+ customParser->imports = (QQmlImports*)0;
+ customParserBindingsPerObject->insert(objectIndex, customParserBindings);
const QList<QQmlError> parserErrors = customParser->errors();
if (!parserErrors.isEmpty()) {
foreach (QQmlError error, parserErrors)
@@ -2166,7 +2153,7 @@ bool QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCa
#endif // QT_NO_DATESTRING
case QVariant::Point: {
bool ok = false;
- QQmlStringConverters::pointFFromString(binding->valueAsString(&qmlUnit->header), &ok).toPoint();
+ QQmlStringConverters::pointFFromString(binding->valueAsString(&qmlUnit->header), &ok);
if (!ok) {
recordError(binding->valueLocation, tr("Invalid property assignment: point expected"));
return false;
@@ -2184,7 +2171,7 @@ bool QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCa
break;
case QVariant::Size: {
bool ok = false;
- QQmlStringConverters::sizeFFromString(binding->valueAsString(&qmlUnit->header), &ok).toSize();
+ QQmlStringConverters::sizeFFromString(binding->valueAsString(&qmlUnit->header), &ok);
if (!ok) {
recordError(binding->valueLocation, tr("Invalid property assignment: size expected"));
return false;
@@ -2202,7 +2189,7 @@ bool QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCa
break;
case QVariant::Rect: {
bool ok = false;
- QQmlStringConverters::rectFFromString(binding->valueAsString(&qmlUnit->header), &ok).toRect();
+ QQmlStringConverters::rectFFromString(binding->valueAsString(&qmlUnit->header), &ok);
if (!ok) {
recordError(binding->valueLocation, tr("Invalid property assignment: rect expected"));
return false;
@@ -2257,7 +2244,7 @@ bool QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *propertyCa
// generate single literal value assignment to a list property if required
if (property->propType == qMetaTypeId<QList<qreal> >()) {
if (binding->type != QV4::CompiledData::Binding::Type_Number) {
- recordError(binding->valueLocation, tr("Invalid property assignment: real or array of reals expected"));
+ recordError(binding->valueLocation, tr("Invalid property assignment: number or array of numbers expected"));
return false;
}
break;
diff --git a/src/qml/compiler/qqmltypecompiler_p.h b/src/qml/compiler/qqmltypecompiler_p.h
index fb8ac94fcd..caf1f93923 100644
--- a/src/qml/compiler/qqmltypecompiler_p.h
+++ b/src/qml/compiler/qqmltypecompiler_p.h
@@ -84,7 +84,7 @@ public:
const QV4::CompiledData::QmlUnit *qmlUnit() const;
- QUrl url() const { return compiledData->url; }
+ QUrl url() const { return typeData->finalUrl(); }
QQmlEnginePrivate *enginePrivate() const { return engine; }
const QQmlImports *imports() const;
QHash<int, QQmlCompiledData::TypeReference *> *resolvedTypes();
@@ -96,11 +96,10 @@ public:
QVector<QByteArray> *vmeMetaObjects() const;
QHash<int, int> *objectIndexToIdForRoot();
QHash<int, QHash<int, int> > *objectIndexToIdPerComponent();
- QHash<int, QQmlCompiledData::CustomParserData> *customParserData();
+ QHash<int, QBitArray> *customParserBindings();
QQmlJS::MemoryPool *memoryPool();
QStringRef newStringRef(const QString &string);
const QV4::Compiler::StringTableGenerator *stringPool() const;
- void setCustomParserBindings(const QVector<int> &bindings);
void setDeferredBindingsPerObject(const QHash<int, QBitArray> &deferredBindingsPerObject);
const QHash<int, QQmlCustomParser*> &customParserCache() const { return customParsers; }
@@ -282,7 +281,6 @@ public:
// Re-implemented for QQmlCustomParser
virtual const QQmlImports &imports() const;
- virtual QQmlBinding::Identifier bindingIdentifier(const QV4::CompiledData::Binding *binding, QQmlCustomParser *parser);
virtual QString bindingAsString(int objectIndex, const QV4::CompiledData::Binding *binding) const;
private:
@@ -300,8 +298,7 @@ private:
const QHash<int, QQmlCustomParser*> &customParsers;
const QVector<QQmlPropertyCache *> &propertyCaches;
const QHash<int, QHash<int, int> > objectIndexToIdPerComponent;
- QHash<int, QQmlCompiledData::CustomParserData> *customParserData;
- QVector<int> customParserBindings;
+ QHash<int, QBitArray> *customParserBindingsPerObject;
QHash<int, QBitArray> deferredBindingsPerObject;
bool _seenObjectWithId;
@@ -394,6 +391,7 @@ private:
virtual void visitClosure(QV4::IR::Closure *closure);
virtual void visitTemp(QV4::IR::Temp *) {}
+ virtual void visitArgLocal(QV4::IR::ArgLocal *) {}
virtual void visitMove(QV4::IR::Move *s) {
s->source->accept(this);
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index fdc4d5c9f2..2d45543305 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -487,11 +487,9 @@ void Codegen::leaveEnvironment()
_env = _env->parent;
}
-void Codegen::enterLoop(Statement *node, IR::BasicBlock *startBlock, IR::BasicBlock *breakBlock, IR::BasicBlock *continueBlock)
+void Codegen::enterLoop(Statement *node, IR::BasicBlock *breakBlock, IR::BasicBlock *continueBlock)
{
- if (startBlock)
- startBlock->markAsGroupStart();
- _loop = new Loop(node, startBlock, breakBlock, continueBlock, _loop);
+ _loop = new Loop(node, breakBlock, continueBlock, _loop);
_loop->labelledStatement = _labelledStatement; // consume the enclosing labelled statement
_loop->scopeAndFinally = _scopeAndFinally;
_labelledStatement = 0;
@@ -509,8 +507,8 @@ IR::Expr *Codegen::member(IR::Expr *base, const QString *name)
if (hasError)
return 0;
- if (base->asTemp() /*|| base->asName()*/)
- return _block->MEMBER(base->asTemp(), name);
+ if (base->asTemp() || base->asArgLocal())
+ return _block->MEMBER(base, name);
else {
const unsigned t = _block->newTemp();
move(_block->TEMP(t), base);
@@ -523,25 +521,26 @@ IR::Expr *Codegen::subscript(IR::Expr *base, IR::Expr *index)
if (hasError)
return 0;
- if (! base->asTemp()) {
+ if (! base->asTemp() || base->asArgLocal()) {
const unsigned t = _block->newTemp();
move(_block->TEMP(t), base);
base = _block->TEMP(t);
}
- if (! index->asTemp()) {
+ if (! index->asTemp() || index->asArgLocal()) {
const unsigned t = _block->newTemp();
move(_block->TEMP(t), index);
index = _block->TEMP(t);
}
- Q_ASSERT(base->asTemp() && index->asTemp());
+ Q_ASSERT(base->asTemp() || base->asArgLocal());
+ Q_ASSERT(index->asTemp() || index->asArgLocal());
return _block->SUBSCRIPT(base->asTemp(), index->asTemp());
}
IR::Expr *Codegen::argument(IR::Expr *expr)
{
- if (expr && ! expr->asTemp()) {
+ if (expr && !expr->asTemp() && !expr->asArgLocal()) {
const unsigned t = _block->newTemp();
move(_block->TEMP(t), expr);
expr = _block->TEMP(t);
@@ -555,7 +554,7 @@ IR::Expr *Codegen::reference(IR::Expr *expr)
if (hasError)
return 0;
- if (expr && !expr->asTemp() && !expr->asName() && !expr->asMember() && !expr->asSubscript()) {
+ if (expr && !expr->asTemp() && !expr->asArgLocal() && !expr->asName() && !expr->asMember() && !expr->asSubscript()) {
const unsigned t = _block->newTemp();
move(_block->TEMP(t), expr);
expr = _block->TEMP(t);
@@ -591,13 +590,13 @@ IR::Expr *Codegen::unop(IR::AluOp op, IR::Expr *expr)
}
}
}
- if (! expr->asTemp()) {
+ if (!expr->asTemp() && !expr->asArgLocal()) {
const unsigned t = _block->newTemp();
move(_block->TEMP(t), expr);
expr = _block->TEMP(t);
}
- Q_ASSERT(expr->asTemp());
- return _block->UNOP(op, expr->asTemp());
+ Q_ASSERT(expr->asTemp() || expr->asArgLocal());
+ return _block->UNOP(op, expr);
}
IR::Expr *Codegen::binop(IR::AluOp op, IR::Expr *left, IR::Expr *right)
@@ -655,20 +654,20 @@ IR::Expr *Codegen::binop(IR::AluOp op, IR::Expr *left, IR::Expr *right)
}
}
- if (!left->asTemp()) {
+ if (!left->asTemp() && !left->asArgLocal()) {
const unsigned t = _block->newTemp();
move(_block->TEMP(t), left);
left = _block->TEMP(t);
}
- if (!right->asTemp()) {
+ if (!right->asTemp() && !right->asArgLocal()) {
const unsigned t = _block->newTemp();
move(_block->TEMP(t), right);
right = _block->TEMP(t);
}
- Q_ASSERT(left->asTemp());
- Q_ASSERT(right->asTemp());
+ Q_ASSERT(left->asTemp() || left->asArgLocal());
+ Q_ASSERT(right->asTemp() || right->asArgLocal());
return _block->BINOP(op, left, right);
}
@@ -693,12 +692,12 @@ void Codegen::move(IR::Expr *target, IR::Expr *source, IR::AluOp op)
return;
}
- if (!source->asTemp() && !source->asConst() && !target->asTemp()) {
+ if (!source->asTemp() && !source->asConst() && !target->asTemp() && !source->asArgLocal() && !target->asArgLocal()) {
unsigned t = _block->newTemp();
_block->MOVE(_block->TEMP(t), source);
source = _block->TEMP(t);
}
- if (source->asConst() && !target->asTemp()) {
+ if (source->asConst() && !target->asTemp() && !target->asArgLocal()) {
unsigned t = _block->newTemp();
_block->MOVE(_block->TEMP(t), source);
source = _block->TEMP(t);
@@ -749,7 +748,7 @@ void Codegen::statement(ExpressionNode *ast)
if (r.format == ex) {
if (r->asCall()) {
_block->EXP(*r); // the nest nx representation for calls is EXP(CALL(c..))
- } else if (r->asTemp()) {
+ } else if (r->asTemp() || r->asArgLocal()) {
// there is nothing to do
} else {
unsigned t = _block->newTemp();
@@ -1065,7 +1064,7 @@ bool Codegen::visit(ArrayLiteral *ast)
current = arg;
IR::Expr *exp = *expr;
- if (exp->asTemp() || exp->asConst()) {
+ if (exp->asTemp() || expr->asArgLocal() || exp->asConst()) {
current->expr = exp;
} else {
unsigned value = _block->newTemp();
@@ -1126,13 +1125,13 @@ bool Codegen::visit(BinaryExpression *ast)
if (ast->op == QSOperator::And) {
if (_expr.accept(cx)) {
- IR::BasicBlock *iftrue = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *iftrue = _function->newBasicBlock(exceptionHandler());
condition(ast->left, iftrue, _expr.iffalse);
_block = iftrue;
condition(ast->right, _expr.iftrue, _expr.iffalse);
} else {
- IR::BasicBlock *iftrue = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
- IR::BasicBlock *endif = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *iftrue = _function->newBasicBlock(exceptionHandler());
+ IR::BasicBlock *endif = _function->newBasicBlock(exceptionHandler());
const unsigned r = _block->newTemp();
@@ -1148,13 +1147,13 @@ bool Codegen::visit(BinaryExpression *ast)
return false;
} else if (ast->op == QSOperator::Or) {
if (_expr.accept(cx)) {
- IR::BasicBlock *iffalse = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *iffalse = _function->newBasicBlock(exceptionHandler());
condition(ast->left, _expr.iftrue, iffalse);
_block = iffalse;
condition(ast->right, _expr.iftrue, _expr.iffalse);
} else {
- IR::BasicBlock *iffalse = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
- IR::BasicBlock *endif = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *iffalse = _function->newBasicBlock(exceptionHandler());
+ IR::BasicBlock *endif = _function->newBasicBlock(exceptionHandler());
const unsigned r = _block->newTemp();
move(_block->TEMP(r), *expression(ast->left));
@@ -1236,7 +1235,7 @@ bool Codegen::visit(BinaryExpression *ast)
case QSOperator::Lt:
case QSOperator::StrictEqual:
case QSOperator::StrictNotEqual: {
- if (!left->asTemp() && !left->asConst()) {
+ if (!left->asTemp() && !left->asArgLocal() && !left->asConst()) {
const unsigned t = _block->newTemp();
move(_block->TEMP(t), left);
left = _block->TEMP(t);
@@ -1270,7 +1269,7 @@ bool Codegen::visit(BinaryExpression *ast)
case QSOperator::RShift:
case QSOperator::Sub:
case QSOperator::URShift: {
- if (!left->asTemp() && !left->asConst()) {
+ if (!left->asTemp() && !left->asArgLocal() && !left->asConst()) {
const unsigned t = _block->newTemp();
move(_block->TEMP(t), left);
left = _block->TEMP(t);
@@ -1317,9 +1316,9 @@ bool Codegen::visit(ConditionalExpression *ast)
if (hasError)
return true;
- IR::BasicBlock *iftrue = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
- IR::BasicBlock *iffalse = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
- IR::BasicBlock *endif = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *iftrue = _function->newBasicBlock(exceptionHandler());
+ IR::BasicBlock *iffalse = _function->newBasicBlock(exceptionHandler());
+ IR::BasicBlock *endif = _function->newBasicBlock(exceptionHandler());
const unsigned t = _block->newTemp();
@@ -1347,8 +1346,8 @@ bool Codegen::visit(DeleteExpression *ast)
IR::Expr* expr = *expression(ast->expression);
// Temporaries cannot be deleted
- IR::Temp *t = expr->asTemp();
- if (t && t->index < static_cast<unsigned>(_env->members.size())) {
+ IR::ArgLocal *al = expr->asArgLocal();
+ if (al && al->index < static_cast<unsigned>(_env->members.size())) {
// Trying to delete a function argument might throw.
if (_function->isStrict) {
throwSyntaxError(ast->deleteToken, QStringLiteral("Delete of an unqualified identifier in strict mode."));
@@ -1375,7 +1374,9 @@ bool Codegen::visit(DeleteExpression *ast)
_expr.code = _block->CONST(IR::BoolType, 1);
return false;
}
- if (expr->asTemp() && expr->asTemp()->index >= static_cast<unsigned>(_env->members.size())) {
+ if (expr->asTemp() ||
+ (expr->asArgLocal() &&
+ expr->asArgLocal()->index >= static_cast<unsigned>(_env->members.size()))) {
_expr.code = _block->CONST(IR::BoolType, 1);
return false;
}
@@ -1435,10 +1436,10 @@ IR::Expr *Codegen::identifier(const QString &name, int line, int col)
int index = e->findMember(name);
Q_ASSERT (index < e->members.size());
if (index != -1) {
- IR::Temp *t = _block->LOCAL(index, scope);
+ IR::ArgLocal *al = _block->LOCAL(index, scope);
if (name == QStringLiteral("arguments") || name == QStringLiteral("eval"))
- t->isArgumentsOrEval = true;
- return t;
+ al->isArgumentsOrEval = true;
+ return al;
}
const int argIdx = f->indexOfArgument(&name);
if (argIdx != -1)
@@ -1497,7 +1498,7 @@ bool Codegen::visit(NewExpression *ast)
Result base = expression(ast->expression);
IR::Expr *expr = *base;
- if (expr && !expr->asTemp() && !expr->asName() && !expr->asMember()) {
+ if (expr && !expr->asTemp() && !expr->asArgLocal() && !expr->asName() && !expr->asMember()) {
const unsigned t = _block->newTemp();
move(_block->TEMP(t), expr);
expr = _block->TEMP(t);
@@ -1513,7 +1514,7 @@ bool Codegen::visit(NewMemberExpression *ast)
Result base = expression(ast->base);
IR::Expr *expr = *base;
- if (expr && !expr->asTemp() && !expr->asName() && !expr->asMember()) {
+ if (expr && !expr->asTemp() && !expr->asArgLocal() && !expr->asName() && !expr->asMember()) {
const unsigned t = _block->newTemp();
move(_block->TEMP(t), expr);
expr = _block->TEMP(t);
@@ -1947,8 +1948,8 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast,
IR::Function *function = _module->newFunction(name, _function);
int functionIndex = _module->functions.count() - 1;
- IR::BasicBlock *entryBlock = function->newBasicBlock(groupStartBlock(), 0);
- IR::BasicBlock *exitBlock = function->newBasicBlock(groupStartBlock(), 0, IR::Function::DontInsertBlock);
+ IR::BasicBlock *entryBlock = function->newBasicBlock(0);
+ IR::BasicBlock *exitBlock = function->newBasicBlock(0, IR::Function::DontInsertBlock);
function->hasDirectEval = _env->hasDirectEval || _env->compilationMode == EvalCode;
function->usesArgumentsObject = _env->parent && (_env->usesArgumentsObject == Environment::ArgumentsObjectUsed);
function->usesThis = _env->usesThis;
@@ -2162,11 +2163,11 @@ bool Codegen::visit(DoWhileStatement *ast)
if (hasError)
return true;
- IR::BasicBlock *loopbody = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
- IR::BasicBlock *loopcond = _function->newBasicBlock(loopbody, exceptionHandler());
- IR::BasicBlock *loopend = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *loopbody = _function->newBasicBlock(exceptionHandler());
+ IR::BasicBlock *loopcond = _function->newBasicBlock(exceptionHandler());
+ IR::BasicBlock *loopend = _function->newBasicBlock(exceptionHandler());
- enterLoop(ast, loopbody, loopend, loopcond);
+ enterLoop(ast, loopend, loopcond);
_block->JUMP(loopbody);
@@ -2212,9 +2213,9 @@ bool Codegen::visit(ForEachStatement *ast)
if (hasError)
return true;
- IR::BasicBlock *foreachin = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
- IR::BasicBlock *foreachbody = _function->newBasicBlock(foreachin, exceptionHandler());
- IR::BasicBlock *foreachend = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *foreachin = _function->newBasicBlock(exceptionHandler());
+ IR::BasicBlock *foreachbody = _function->newBasicBlock(exceptionHandler());
+ IR::BasicBlock *foreachend = _function->newBasicBlock(exceptionHandler());
int objectToIterateOn = _block->newTemp();
move(_block->TEMP(objectToIterateOn), *expression(ast->expression));
@@ -2224,7 +2225,7 @@ bool Codegen::visit(ForEachStatement *ast)
int iterator = _block->newTemp();
move(_block->TEMP(iterator), _block->CALL(_block->NAME(IR::Name::builtin_foreach_iterator_object, 0, 0), args));
- enterLoop(ast, foreachin, foreachend, foreachin);
+ enterLoop(ast, foreachend, foreachin);
_block->JUMP(foreachin);
_block = foreachbody;
@@ -2252,15 +2253,15 @@ bool Codegen::visit(ForStatement *ast)
if (hasError)
return true;
- IR::BasicBlock *forcond = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
- IR::BasicBlock *forbody = _function->newBasicBlock(forcond, exceptionHandler());
- IR::BasicBlock *forstep = _function->newBasicBlock(forcond, exceptionHandler());
- IR::BasicBlock *forend = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *forcond = _function->newBasicBlock(exceptionHandler());
+ IR::BasicBlock *forbody = _function->newBasicBlock(exceptionHandler());
+ IR::BasicBlock *forstep = _function->newBasicBlock(exceptionHandler());
+ IR::BasicBlock *forend = _function->newBasicBlock(exceptionHandler());
statement(ast->initialiser);
_block->JUMP(forcond);
- enterLoop(ast, forcond, forend, forstep);
+ enterLoop(ast, forend, forstep);
_block = forcond;
if (ast->condition)
@@ -2288,9 +2289,9 @@ bool Codegen::visit(IfStatement *ast)
if (hasError)
return true;
- IR::BasicBlock *iftrue = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
- IR::BasicBlock *iffalse = ast->ko ? _function->newBasicBlock(groupStartBlock(), exceptionHandler()) : 0;
- IR::BasicBlock *endif = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *iftrue = _function->newBasicBlock(exceptionHandler());
+ IR::BasicBlock *iffalse = ast->ko ? _function->newBasicBlock(exceptionHandler()) : 0;
+ IR::BasicBlock *endif = _function->newBasicBlock(exceptionHandler());
condition(ast->expression, iftrue, ast->ko ? iffalse : endif);
@@ -2335,8 +2336,8 @@ bool Codegen::visit(LabelledStatement *ast)
AST::cast<AST::LocalForEachStatement *>(ast->statement)) {
statement(ast->statement); // labelledStatement will be associated with the ast->statement's loop.
} else {
- IR::BasicBlock *breakBlock = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
- enterLoop(ast->statement, 0, breakBlock, /*continueBlock*/ 0);
+ IR::BasicBlock *breakBlock = _function->newBasicBlock(exceptionHandler());
+ enterLoop(ast->statement, breakBlock, /*continueBlock*/ 0);
statement(ast->statement);
_block->JUMP(breakBlock);
_block = breakBlock;
@@ -2351,9 +2352,9 @@ bool Codegen::visit(LocalForEachStatement *ast)
if (hasError)
return true;
- IR::BasicBlock *foreachin = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
- IR::BasicBlock *foreachbody = _function->newBasicBlock(foreachin, exceptionHandler());
- IR::BasicBlock *foreachend = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *foreachin = _function->newBasicBlock(exceptionHandler());
+ IR::BasicBlock *foreachbody = _function->newBasicBlock(exceptionHandler());
+ IR::BasicBlock *foreachend = _function->newBasicBlock(exceptionHandler());
variableDeclaration(ast->declaration);
@@ -2364,7 +2365,7 @@ bool Codegen::visit(LocalForEachStatement *ast)
move(_block->TEMP(iterator), _block->CALL(_block->NAME(IR::Name::builtin_foreach_iterator_object, 0, 0), args));
_block->JUMP(foreachin);
- enterLoop(ast, foreachin, foreachend, foreachin);
+ enterLoop(ast, foreachend, foreachin);
_block = foreachbody;
int temp = _block->newTemp();
@@ -2391,15 +2392,15 @@ bool Codegen::visit(LocalForStatement *ast)
if (hasError)
return true;
- IR::BasicBlock *forcond = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
- IR::BasicBlock *forbody = _function->newBasicBlock(forcond, exceptionHandler());
- IR::BasicBlock *forstep = _function->newBasicBlock(forcond, exceptionHandler());
- IR::BasicBlock *forend = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *forcond = _function->newBasicBlock(exceptionHandler());
+ IR::BasicBlock *forbody = _function->newBasicBlock(exceptionHandler());
+ IR::BasicBlock *forstep = _function->newBasicBlock(exceptionHandler());
+ IR::BasicBlock *forend = _function->newBasicBlock(exceptionHandler());
variableDeclarationList(ast->declarations);
_block->JUMP(forcond);
- enterLoop(ast, forcond, forend, forstep);
+ enterLoop(ast, forend, forstep);
_block = forcond;
if (ast->condition)
@@ -2446,22 +2447,22 @@ bool Codegen::visit(SwitchStatement *ast)
if (hasError)
return true;
- IR::BasicBlock *switchend = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *switchend = _function->newBasicBlock(exceptionHandler());
if (ast->block) {
Result lhs = expression(ast->expression);
- IR::BasicBlock *switchcond = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *switchcond = _function->newBasicBlock(exceptionHandler());
_block->JUMP(switchcond);
IR::BasicBlock *previousBlock = 0;
QHash<Node *, IR::BasicBlock *> blockMap;
- enterLoop(ast, 0, switchend, 0);
+ enterLoop(ast, switchend, 0);
for (CaseClauses *it = ast->block->clauses; it; it = it->next) {
CaseClause *clause = it->clause;
- _block = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ _block = _function->newBasicBlock(exceptionHandler());
blockMap[clause] = _block;
if (previousBlock && !previousBlock->isTerminated())
@@ -2474,7 +2475,7 @@ bool Codegen::visit(SwitchStatement *ast)
}
if (ast->block->defaultClause) {
- _block = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ _block = _function->newBasicBlock(exceptionHandler());
blockMap[ast->block->defaultClause] = _block;
if (previousBlock && !previousBlock->isTerminated())
@@ -2489,7 +2490,7 @@ bool Codegen::visit(SwitchStatement *ast)
for (CaseClauses *it = ast->block->moreClauses; it; it = it->next) {
CaseClause *clause = it->clause;
- _block = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ _block = _function->newBasicBlock(exceptionHandler());
blockMap[clause] = _block;
if (previousBlock && !previousBlock->isTerminated())
@@ -2510,7 +2511,7 @@ bool Codegen::visit(SwitchStatement *ast)
CaseClause *clause = it->clause;
Result rhs = expression(clause->expression);
IR::BasicBlock *iftrue = blockMap[clause];
- IR::BasicBlock *iffalse = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *iffalse = _function->newBasicBlock(exceptionHandler());
cjump(binop(IR::OpStrictEqual, *lhs, *rhs), iftrue, iffalse);
_block = iffalse;
}
@@ -2519,7 +2520,7 @@ bool Codegen::visit(SwitchStatement *ast)
CaseClause *clause = it->clause;
Result rhs = expression(clause->expression);
IR::BasicBlock *iftrue = blockMap[clause];
- IR::BasicBlock *iffalse = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *iffalse = _function->newBasicBlock(exceptionHandler());
cjump(binop(IR::OpStrictEqual, *lhs, *rhs), iftrue, iffalse);
_block = iffalse;
}
@@ -2568,16 +2569,16 @@ bool Codegen::visit(TryStatement *ast)
IR::BasicBlock *finallyBody = 0;
IR::BasicBlock *catchBody = 0;
IR::BasicBlock *catchExceptionHandler = 0;
- IR::BasicBlock *end = _function->newBasicBlock(groupStartBlock(), surroundingExceptionHandler, IR::Function::DontInsertBlock);
+ IR::BasicBlock *end = _function->newBasicBlock(surroundingExceptionHandler, IR::Function::DontInsertBlock);
if (ast->finallyExpression)
- finallyBody = _function->newBasicBlock(groupStartBlock(), surroundingExceptionHandler, IR::Function::DontInsertBlock);
+ finallyBody = _function->newBasicBlock(surroundingExceptionHandler, IR::Function::DontInsertBlock);
if (ast->catchExpression) {
// exception handler for the catch body
- catchExceptionHandler = _function->newBasicBlock(groupStartBlock(), 0, IR::Function::DontInsertBlock);
+ catchExceptionHandler = _function->newBasicBlock(0, IR::Function::DontInsertBlock);
pushExceptionHandler(catchExceptionHandler);
- catchBody = _function->newBasicBlock(groupStartBlock(), catchExceptionHandler, IR::Function::DontInsertBlock);
+ catchBody = _function->newBasicBlock(catchExceptionHandler, IR::Function::DontInsertBlock);
popExceptionHandler();
pushExceptionHandler(catchBody);
} else {
@@ -2585,7 +2586,7 @@ bool Codegen::visit(TryStatement *ast)
pushExceptionHandler(finallyBody);
}
- IR::BasicBlock *tryBody = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *tryBody = _function->newBasicBlock(exceptionHandler());
_block->JUMP(tryBody);
ScopeAndFinally tcf(_scopeAndFinally, ast->finallyExpression);
@@ -2690,11 +2691,11 @@ bool Codegen::visit(WhileStatement *ast)
if (hasError)
return true;
- IR::BasicBlock *whilecond = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
- IR::BasicBlock *whilebody = _function->newBasicBlock(whilecond, exceptionHandler());
- IR::BasicBlock *whileend = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *whilecond = _function->newBasicBlock(exceptionHandler());
+ IR::BasicBlock *whilebody = _function->newBasicBlock(exceptionHandler());
+ IR::BasicBlock *whileend = _function->newBasicBlock(exceptionHandler());
- enterLoop(ast, whilecond, whileend, whilecond);
+ enterLoop(ast, whileend, whilecond);
_block->JUMP(whilecond);
_block = whilecond;
@@ -2718,7 +2719,7 @@ bool Codegen::visit(WithStatement *ast)
_function->hasWith = true;
// need an exception handler for with to cleanup the with scope
- IR::BasicBlock *withExceptionHandler = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *withExceptionHandler = _function->newBasicBlock(exceptionHandler());
withExceptionHandler->EXP(withExceptionHandler->CALL(withExceptionHandler->NAME(IR::Name::builtin_pop_scope, 0, 0), 0));
if (!exceptionHandler())
withExceptionHandler->EXP(withExceptionHandler->CALL(withExceptionHandler->NAME(IR::Name::builtin_rethrow, 0, 0), 0));
@@ -2727,7 +2728,7 @@ bool Codegen::visit(WithStatement *ast)
pushExceptionHandler(withExceptionHandler);
- IR::BasicBlock *withBlock = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *withBlock = _function->newBasicBlock(exceptionHandler());
_block->JUMP(withBlock);
_block = withBlock;
@@ -2748,7 +2749,7 @@ bool Codegen::visit(WithStatement *ast)
_block->EXP(_block->CALL(_block->NAME(IR::Name::builtin_pop_scope, 0, 0), 0));
popExceptionHandler();
- IR::BasicBlock *next = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
+ IR::BasicBlock *next = _function->newBasicBlock(exceptionHandler());
_block->JUMP(next);
_block = next;
@@ -2798,8 +2799,8 @@ bool Codegen::throwSyntaxErrorOnEvalOrArgumentsInStrictMode(IR::Expr *expr, cons
if (IR::Name *n = expr->asName()) {
if (*n->id != QLatin1String("eval") && *n->id != QLatin1String("arguments"))
return false;
- } else if (IR::Temp *t = expr->asTemp()) {
- if (!t->isArgumentsOrEval)
+ } else if (IR::ArgLocal *al = expr->asArgLocal()) {
+ if (!al->isArgumentsOrEval)
return false;
} else {
return false;
diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h
index 0d52fb83fa..cbe8301c09 100644
--- a/src/qml/compiler/qv4codegen_p.h
+++ b/src/qml/compiler/qv4codegen_p.h
@@ -256,28 +256,20 @@ protected:
struct Loop {
AST::LabelledStatement *labelledStatement;
AST::Statement *node;
- QV4::IR::BasicBlock *groupStartBlock;
QV4::IR::BasicBlock *breakBlock;
QV4::IR::BasicBlock *continueBlock;
Loop *parent;
ScopeAndFinally *scopeAndFinally;
- Loop(AST::Statement *node, QV4::IR::BasicBlock *groupStartBlock, QV4::IR::BasicBlock *breakBlock, QV4::IR::BasicBlock *continueBlock, Loop *parent)
- : labelledStatement(0), node(node), groupStartBlock(groupStartBlock), breakBlock(breakBlock), continueBlock(continueBlock), parent(parent) {}
+ Loop(AST::Statement *node, QV4::IR::BasicBlock *breakBlock, QV4::IR::BasicBlock *continueBlock, Loop *parent)
+ : labelledStatement(0), node(node), breakBlock(breakBlock), continueBlock(continueBlock), parent(parent) {}
};
void enterEnvironment(AST::Node *node);
void leaveEnvironment();
- void enterLoop(AST::Statement *node, QV4::IR::BasicBlock *startBlock, QV4::IR::BasicBlock *breakBlock, QV4::IR::BasicBlock *continueBlock);
+ void enterLoop(AST::Statement *node, QV4::IR::BasicBlock *breakBlock, QV4::IR::BasicBlock *continueBlock);
void leaveLoop();
- QV4::IR::BasicBlock *groupStartBlock() const
- {
- for (Loop *it = _loop; it; it = it->parent)
- if (it->groupStartBlock)
- return it->groupStartBlock;
- return 0;
- }
QV4::IR::BasicBlock *exceptionHandler() const
{
if (_exceptionHandlers.isEmpty())
diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp
index 9288008632..7c67ae2301 100644
--- a/src/qml/compiler/qv4isel_moth.cpp
+++ b/src/qml/compiler/qv4isel_moth.cpp
@@ -168,22 +168,30 @@ inline bool isBoolType(IR::Expr *e)
*/
class AllocateStackSlots: protected ConvertTemps
{
- const QVector<IR::LifeTimeInterval> _intervals;
- QVector<const IR::LifeTimeInterval *> _unhandled;
- QVector<const IR::LifeTimeInterval *> _live;
+ IR::LifeTimeIntervals::Ptr _intervals;
+ QVector<IR::LifeTimeInterval *> _unhandled;
+ QVector<IR::LifeTimeInterval *> _live;
QBitArray _slotIsInUse;
IR::Function *_function;
+ int defPosition(IR::Stmt *s) const
+ {
+ return usePosition(s) + 1;
+ }
+
+ int usePosition(IR::Stmt *s) const
+ {
+ return _intervals->positionForStatement(s);
+ }
+
public:
- AllocateStackSlots(const QVector<IR::LifeTimeInterval> &intervals)
+ AllocateStackSlots(const IR::LifeTimeIntervals::Ptr &intervals)
: _intervals(intervals)
- , _slotIsInUse(intervals.size(), false)
+ , _slotIsInUse(intervals->size(), false)
, _function(0)
{
_live.reserve(8);
- _unhandled.reserve(_intervals.size());
- for (int i = _intervals.size() - 1; i >= 0; --i)
- _unhandled.append(&_intervals.at(i));
+ _unhandled = _intervals->intervals();
}
void forFunction(IR::Function *function)
@@ -219,8 +227,6 @@ protected:
virtual void process(IR::Stmt *s)
{
- Q_ASSERT(s->id > 0);
-
// qDebug("L%d statement %d:", _currentBasicBlock->index, s->id);
if (IR::Phi *phi = s->asPhi()) {
@@ -229,7 +235,7 @@ protected:
// purge ranges no longer alive:
for (int i = 0; i < _live.size(); ) {
const IR::LifeTimeInterval *lti = _live.at(i);
- if (lti->end() < s->id) {
+ if (lti->end() < usePosition(s)) {
// qDebug() << "\t - moving temp" << lti->temp().index << "to handled, freeing slot" << _stackSlotForTemp[lti->temp().index];
_live.remove(i);
Q_ASSERT(_slotIsInUse[_stackSlotForTemp[lti->temp().index]]);
@@ -242,8 +248,8 @@ protected:
// active new ranges:
while (!_unhandled.isEmpty()) {
- const IR::LifeTimeInterval *lti = _unhandled.last();
- if (lti->start() > s->id)
+ IR::LifeTimeInterval *lti = _unhandled.last();
+ if (lti->start() > defPosition(s))
break; // we're done
Q_ASSERT(!_stackSlotForTemp.contains(lti->temp().index));
_stackSlotForTemp[lti->temp().index] = allocateFreeSlot();
@@ -286,7 +292,7 @@ protected:
int i = _unhandled.size() - 1;
for (; i >= 0; --i) {
- const IR::LifeTimeInterval *lti = _unhandled[i];
+ IR::LifeTimeInterval *lti = _unhandled[i];
if (lti->temp() == t) {
_live.append(lti);
_unhandled.remove(i);
@@ -322,9 +328,8 @@ InstructionSelection::InstructionSelection(QQmlEnginePrivate *qmlEngine, QV4::Ex
, _codeNext(0)
, _codeEnd(0)
, _currentStatement(0)
-{
- compilationUnit = new CompilationUnit;
-}
+ , compilationUnit(new CompilationUnit)
+{}
InstructionSelection::~InstructionSelection()
{
@@ -453,10 +458,10 @@ QV4::CompiledData::CompilationUnit *InstructionSelection::backendCompileStep()
int i = 0;
foreach (IR::Function *irFunction, irModule->functions)
compilationUnit->codeRefs[i++] = codeRefs[irFunction];
- return compilationUnit;
+ return compilationUnit.take();
}
-void InstructionSelection::callValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result)
+void InstructionSelection::callValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result)
{
Instruction::CallValue call;
prepareCallArgs(args, call.argc);
@@ -467,7 +472,7 @@ void InstructionSelection::callValue(IR::Temp *value, IR::ExprList *args, IR::Te
}
void InstructionSelection::callProperty(IR::Expr *base, const QString &name, IR::ExprList *args,
- IR::Temp *result)
+ IR::Expr *result)
{
if (useFastLookups) {
Instruction::CallPropertyLookup call;
@@ -490,7 +495,7 @@ void InstructionSelection::callProperty(IR::Expr *base, const QString &name, IR:
}
void InstructionSelection::callSubscript(IR::Expr *base, IR::Expr *index, IR::ExprList *args,
- IR::Temp *result)
+ IR::Expr *result)
{
// call the property on the loaded base
Instruction::CallElement call;
@@ -502,7 +507,7 @@ void InstructionSelection::callSubscript(IR::Expr *base, IR::Expr *index, IR::Ex
addInstruction(call);
}
-void InstructionSelection::convertType(IR::Temp *source, IR::Temp *target)
+void InstructionSelection::convertType(IR::Expr *source, IR::Expr *target)
{
// FIXME: do something more useful with this info
if (target->type & IR::NumberType && !(source->type & IR::NumberType))
@@ -513,14 +518,14 @@ void InstructionSelection::convertType(IR::Temp *source, IR::Temp *target)
void InstructionSelection::constructActivationProperty(IR::Name *func,
IR::ExprList *args,
- IR::Temp *result)
+ IR::Expr *target)
{
if (useFastLookups && func->global) {
Instruction::ConstructGlobalLookup call;
call.index = registerGlobalGetterLookup(*func->id);
prepareCallArgs(args, call.argc);
call.callData = callDataStart();
- call.result = getResultParam(result);
+ call.result = getResultParam(target);
addInstruction(call);
return;
}
@@ -528,11 +533,11 @@ void InstructionSelection::constructActivationProperty(IR::Name *func,
create.name = registerString(*func->id);
prepareCallArgs(args, create.argc);
create.callData = callDataStart();
- create.result = getResultParam(result);
+ create.result = getResultParam(target);
addInstruction(create);
}
-void InstructionSelection::constructProperty(IR::Temp *base, const QString &name, IR::ExprList *args, IR::Temp *result)
+void InstructionSelection::constructProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr *target)
{
if (useFastLookups) {
Instruction::ConstructPropertyLookup call;
@@ -540,7 +545,7 @@ void InstructionSelection::constructProperty(IR::Temp *base, const QString &name
call.index = registerGetterLookup(name);
prepareCallArgs(args, call.argc);
call.callData = callDataStart();
- call.result = getResultParam(result);
+ call.result = getResultParam(target);
addInstruction(call);
return;
}
@@ -549,101 +554,101 @@ void InstructionSelection::constructProperty(IR::Temp *base, const QString &name
create.name = registerString(name);
prepareCallArgs(args, create.argc);
create.callData = callDataStart();
- create.result = getResultParam(result);
+ create.result = getResultParam(target);
addInstruction(create);
}
-void InstructionSelection::constructValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result)
+void InstructionSelection::constructValue(IR::Expr *value, IR::ExprList *args, IR::Expr *target)
{
Instruction::CreateValue create;
create.func = getParam(value);
prepareCallArgs(args, create.argc);
create.callData = callDataStart();
- create.result = getResultParam(result);
+ create.result = getResultParam(target);
addInstruction(create);
}
-void InstructionSelection::loadThisObject(IR::Temp *temp)
+void InstructionSelection::loadThisObject(IR::Expr *e)
{
Instruction::LoadThis load;
- load.result = getResultParam(temp);
+ load.result = getResultParam(e);
addInstruction(load);
}
-void InstructionSelection::loadQmlIdArray(IR::Temp *temp)
+void InstructionSelection::loadQmlIdArray(IR::Expr *e)
{
Instruction::LoadQmlIdArray load;
- load.result = getResultParam(temp);
+ load.result = getResultParam(e);
addInstruction(load);
}
-void InstructionSelection::loadQmlImportedScripts(IR::Temp *temp)
+void InstructionSelection::loadQmlImportedScripts(IR::Expr *e)
{
Instruction::LoadQmlImportedScripts load;
- load.result = getResultParam(temp);
+ load.result = getResultParam(e);
addInstruction(load);
}
-void InstructionSelection::loadQmlContextObject(IR::Temp *temp)
+void InstructionSelection::loadQmlContextObject(IR::Expr *e)
{
Instruction::LoadQmlContextObject load;
- load.result = getResultParam(temp);
+ load.result = getResultParam(e);
addInstruction(load);
}
-void InstructionSelection::loadQmlScopeObject(IR::Temp *temp)
+void InstructionSelection::loadQmlScopeObject(IR::Expr *e)
{
Instruction::LoadQmlScopeObject load;
- load.result = getResultParam(temp);
+ load.result = getResultParam(e);
addInstruction(load);
}
-void InstructionSelection::loadQmlSingleton(const QString &name, IR::Temp *temp)
+void InstructionSelection::loadQmlSingleton(const QString &name, IR::Expr *e)
{
Instruction::LoadQmlSingleton load;
- load.result = getResultParam(temp);
+ load.result = getResultParam(e);
load.name = registerString(name);
addInstruction(load);
}
-void InstructionSelection::loadConst(IR::Const *sourceConst, IR::Temp *targetTemp)
+void InstructionSelection::loadConst(IR::Const *sourceConst, IR::Expr *e)
{
Q_ASSERT(sourceConst);
Instruction::MoveConst move;
move.source = convertToValue(sourceConst).asReturnedValue();
- move.result = getResultParam(targetTemp);
+ move.result = getResultParam(e);
addInstruction(move);
}
-void InstructionSelection::loadString(const QString &str, IR::Temp *targetTemp)
+void InstructionSelection::loadString(const QString &str, IR::Expr *target)
{
Instruction::LoadRuntimeString load;
load.stringId = registerString(str);
- load.result = getResultParam(targetTemp);
+ load.result = getResultParam(target);
addInstruction(load);
}
-void InstructionSelection::loadRegexp(IR::RegExp *sourceRegexp, IR::Temp *targetTemp)
+void InstructionSelection::loadRegexp(IR::RegExp *sourceRegexp, IR::Expr *target)
{
Instruction::LoadRegExp load;
load.regExpId = registerRegExp(sourceRegexp);
- load.result = getResultParam(targetTemp);
+ load.result = getResultParam(target);
addInstruction(load);
}
-void InstructionSelection::getActivationProperty(const IR::Name *name, IR::Temp *temp)
+void InstructionSelection::getActivationProperty(const IR::Name *name, IR::Expr *target)
{
if (useFastLookups && name->global) {
Instruction::GetGlobalLookup load;
load.index = registerGlobalGetterLookup(*name->id);
- load.result = getResultParam(temp);
+ load.result = getResultParam(target);
addInstruction(load);
return;
}
Instruction::LoadName load;
load.name = registerString(*name->id);
- load.result = getResultParam(temp);
+ load.result = getResultParam(target);
addInstruction(load);
}
@@ -655,7 +660,7 @@ void InstructionSelection::setActivationProperty(IR::Expr *source, const QString
addInstruction(store);
}
-void InstructionSelection::initClosure(IR::Closure *closure, IR::Temp *target)
+void InstructionSelection::initClosure(IR::Closure *closure, IR::Expr *target)
{
int id = closure->value;
Instruction::LoadClosure load;
@@ -664,7 +669,7 @@ void InstructionSelection::initClosure(IR::Closure *closure, IR::Temp *target)
addInstruction(load);
}
-void InstructionSelection::getProperty(IR::Expr *base, const QString &name, IR::Temp *target)
+void InstructionSelection::getProperty(IR::Expr *base, const QString &name, IR::Expr *target)
{
if (useFastLookups) {
Instruction::GetLookup load;
@@ -708,7 +713,7 @@ void InstructionSelection::setQObjectProperty(IR::Expr *source, IR::Expr *target
addInstruction(store);
}
-void InstructionSelection::getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, IR::Temp *target)
+void InstructionSelection::getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, IR::Expr *target)
{
if (attachedPropertiesId != 0) {
Instruction::LoadAttachedQObjectProperty load;
@@ -726,7 +731,7 @@ void InstructionSelection::getQObjectProperty(IR::Expr *base, int propertyIndex,
}
}
-void InstructionSelection::getElement(IR::Expr *base, IR::Expr *index, IR::Temp *target)
+void InstructionSelection::getElement(IR::Expr *base, IR::Expr *index, IR::Expr *target)
{
if (useFastLookups) {
Instruction::LoadElementLookup load;
@@ -763,92 +768,92 @@ void InstructionSelection::setElement(IR::Expr *source, IR::Expr *targetBase,
addInstruction(store);
}
-void InstructionSelection::copyValue(IR::Temp *sourceTemp, IR::Temp *targetTemp)
+void InstructionSelection::copyValue(IR::Expr *source, IR::Expr *target)
{
Instruction::Move move;
- move.source = getParam(sourceTemp);
- move.result = getResultParam(targetTemp);
+ move.source = getParam(source);
+ move.result = getResultParam(target);
if (move.source != move.result)
addInstruction(move);
}
-void InstructionSelection::swapValues(IR::Temp *sourceTemp, IR::Temp *targetTemp)
+void InstructionSelection::swapValues(IR::Expr *source, IR::Expr *target)
{
Instruction::SwapTemps swap;
- swap.left = getParam(sourceTemp);
- swap.right = getParam(targetTemp);
+ swap.left = getParam(source);
+ swap.right = getParam(target);
addInstruction(swap);
}
-void InstructionSelection::unop(IR::AluOp oper, IR::Temp *sourceTemp, IR::Temp *targetTemp)
+void InstructionSelection::unop(IR::AluOp oper, IR::Expr *source, IR::Expr *target)
{
switch (oper) {
case IR::OpIfTrue:
Q_ASSERT(!"unreachable"); break;
case IR::OpNot: {
// ### enabling this fails in some cases, where apparently the value is not a bool at runtime
- if (0 && isBoolType(sourceTemp)) {
+ if (0 && isBoolType(source)) {
Instruction::UNotBool unot;
- unot.source = getParam(sourceTemp);
- unot.result = getResultParam(targetTemp);
+ unot.source = getParam(source);
+ unot.result = getResultParam(target);
addInstruction(unot);
return;
}
Instruction::UNot unot;
- unot.source = getParam(sourceTemp);
- unot.result = getResultParam(targetTemp);
+ unot.source = getParam(source);
+ unot.result = getResultParam(target);
addInstruction(unot);
return;
}
case IR::OpUMinus: {
Instruction::UMinus uminus;
- uminus.source = getParam(sourceTemp);
- uminus.result = getResultParam(targetTemp);
+ uminus.source = getParam(source);
+ uminus.result = getResultParam(target);
addInstruction(uminus);
return;
}
case IR::OpUPlus: {
- if (isNumberType(sourceTemp)) {
+ if (isNumberType(source)) {
// use a move
Instruction::Move move;
- move.source = getParam(sourceTemp);
- move.result = getResultParam(targetTemp);
+ move.source = getParam(source);
+ move.result = getResultParam(target);
if (move.source != move.result)
addInstruction(move);
return;
}
Instruction::UPlus uplus;
- uplus.source = getParam(sourceTemp);
- uplus.result = getResultParam(targetTemp);
+ uplus.source = getParam(source);
+ uplus.result = getResultParam(target);
addInstruction(uplus);
return;
}
case IR::OpCompl: {
// ### enabling this fails in some cases, where apparently the value is not a int at runtime
- if (0 && isIntegerType(sourceTemp)) {
+ if (0 && isIntegerType(source)) {
Instruction::UComplInt unot;
- unot.source = getParam(sourceTemp);
- unot.result = getResultParam(targetTemp);
+ unot.source = getParam(source);
+ unot.result = getResultParam(target);
addInstruction(unot);
return;
}
Instruction::UCompl ucompl;
- ucompl.source = getParam(sourceTemp);
- ucompl.result = getResultParam(targetTemp);
+ ucompl.source = getParam(source);
+ ucompl.result = getResultParam(target);
addInstruction(ucompl);
return;
}
case IR::OpIncrement: {
Instruction::Increment inc;
- inc.source = getParam(sourceTemp);
- inc.result = getResultParam(targetTemp);
+ inc.source = getParam(source);
+ inc.result = getResultParam(target);
addInstruction(inc);
return;
}
case IR::OpDecrement: {
Instruction::Decrement dec;
- dec.source = getParam(sourceTemp);
- dec.result = getResultParam(targetTemp);
+ dec.source = getParam(source);
+ dec.result = getResultParam(target);
addInstruction(dec);
return;
}
@@ -858,12 +863,12 @@ void InstructionSelection::unop(IR::AluOp oper, IR::Temp *sourceTemp, IR::Temp *
Q_ASSERT(!"unreachable");
}
-void InstructionSelection::binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target)
+void InstructionSelection::binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *target)
{
binopHelper(oper, leftSource, rightSource, target);
}
-Param InstructionSelection::binopHelper(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target)
+Param InstructionSelection::binopHelper(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *target)
{
if (oper == IR::OpAdd) {
Instruction::Add add;
@@ -1103,7 +1108,7 @@ void InstructionSelection::visitRet(IR::Ret *s)
addInstruction(ret);
}
-void InstructionSelection::callBuiltinInvalid(IR::Name *func, IR::ExprList *args, IR::Temp *result)
+void InstructionSelection::callBuiltinInvalid(IR::Name *func, IR::ExprList *args, IR::Expr *result)
{
if (useFastLookups && func->global) {
Instruction::CallGlobalLookup call;
@@ -1123,7 +1128,7 @@ void InstructionSelection::callBuiltinInvalid(IR::Name *func, IR::ExprList *args
}
void InstructionSelection::callBuiltinTypeofMember(IR::Expr *base, const QString &name,
- IR::Temp *result)
+ IR::Expr *result)
{
Instruction::CallBuiltinTypeofMember call;
call.base = getParam(base);
@@ -1133,7 +1138,7 @@ void InstructionSelection::callBuiltinTypeofMember(IR::Expr *base, const QString
}
void InstructionSelection::callBuiltinTypeofSubscript(IR::Expr *base, IR::Expr *index,
- IR::Temp *result)
+ IR::Expr *result)
{
Instruction::CallBuiltinTypeofSubscript call;
call.base = getParam(base);
@@ -1142,7 +1147,7 @@ void InstructionSelection::callBuiltinTypeofSubscript(IR::Expr *base, IR::Expr *
addInstruction(call);
}
-void InstructionSelection::callBuiltinTypeofName(const QString &name, IR::Temp *result)
+void InstructionSelection::callBuiltinTypeofName(const QString &name, IR::Expr *result)
{
Instruction::CallBuiltinTypeofName call;
call.name = registerString(name);
@@ -1150,7 +1155,7 @@ void InstructionSelection::callBuiltinTypeofName(const QString &name, IR::Temp *
addInstruction(call);
}
-void InstructionSelection::callBuiltinTypeofValue(IR::Expr *value, IR::Temp *result)
+void InstructionSelection::callBuiltinTypeofValue(IR::Expr *value, IR::Expr *result)
{
Instruction::CallBuiltinTypeofValue call;
call.value = getParam(value);
@@ -1158,7 +1163,7 @@ void InstructionSelection::callBuiltinTypeofValue(IR::Expr *value, IR::Temp *res
addInstruction(call);
}
-void InstructionSelection::callBuiltinDeleteMember(IR::Temp *base, const QString &name, IR::Temp *result)
+void InstructionSelection::callBuiltinDeleteMember(IR::Expr *base, const QString &name, IR::Expr *result)
{
Instruction::CallBuiltinDeleteMember call;
call.base = getParam(base);
@@ -1167,8 +1172,8 @@ void InstructionSelection::callBuiltinDeleteMember(IR::Temp *base, const QString
addInstruction(call);
}
-void InstructionSelection::callBuiltinDeleteSubscript(IR::Temp *base, IR::Expr *index,
- IR::Temp *result)
+void InstructionSelection::callBuiltinDeleteSubscript(IR::Expr *base, IR::Expr *index,
+ IR::Expr *result)
{
Instruction::CallBuiltinDeleteSubscript call;
call.base = getParam(base);
@@ -1177,7 +1182,7 @@ void InstructionSelection::callBuiltinDeleteSubscript(IR::Temp *base, IR::Expr *
addInstruction(call);
}
-void InstructionSelection::callBuiltinDeleteName(const QString &name, IR::Temp *result)
+void InstructionSelection::callBuiltinDeleteName(const QString &name, IR::Expr *result)
{
Instruction::CallBuiltinDeleteName call;
call.name = registerString(name);
@@ -1185,7 +1190,7 @@ void InstructionSelection::callBuiltinDeleteName(const QString &name, IR::Temp *
addInstruction(call);
}
-void InstructionSelection::callBuiltinDeleteValue(IR::Temp *result)
+void InstructionSelection::callBuiltinDeleteValue(IR::Expr *result)
{
Instruction::MoveConst move;
move.source = QV4::Encode(false);
@@ -1217,7 +1222,7 @@ void InstructionSelection::callBuiltinReThrow()
}
}
-void InstructionSelection::callBuiltinUnwindException(IR::Temp *result)
+void InstructionSelection::callBuiltinUnwindException(IR::Expr *result)
{
Instruction::CallBuiltinUnwindException call;
call.result = getResultParam(result);
@@ -1232,7 +1237,7 @@ void InstructionSelection::callBuiltinPushCatchScope(const QString &exceptionNam
addInstruction(call);
}
-void InstructionSelection::callBuiltinForeachIteratorObject(IR::Expr *arg, IR::Temp *result)
+void InstructionSelection::callBuiltinForeachIteratorObject(IR::Expr *arg, IR::Expr *result)
{
Instruction::CallBuiltinForeachIteratorObject call;
call.arg = getParam(arg);
@@ -1240,7 +1245,7 @@ void InstructionSelection::callBuiltinForeachIteratorObject(IR::Expr *arg, IR::T
addInstruction(call);
}
-void InstructionSelection::callBuiltinForeachNextPropertyname(IR::Temp *arg, IR::Temp *result)
+void InstructionSelection::callBuiltinForeachNextPropertyname(IR::Expr *arg, IR::Expr *result)
{
Instruction::CallBuiltinForeachNextPropertyName call;
call.arg = getParam(arg);
@@ -1248,7 +1253,7 @@ void InstructionSelection::callBuiltinForeachNextPropertyname(IR::Temp *arg, IR:
addInstruction(call);
}
-void InstructionSelection::callBuiltinPushWithScope(IR::Temp *arg)
+void InstructionSelection::callBuiltinPushWithScope(IR::Expr *arg)
{
Instruction::CallBuiltinPushScope call;
call.arg = getParam(arg);
@@ -1269,7 +1274,7 @@ void InstructionSelection::callBuiltinDeclareVar(bool deletable, const QString &
addInstruction(call);
}
-void InstructionSelection::callBuiltinDefineArray(IR::Temp *result, IR::ExprList *args)
+void InstructionSelection::callBuiltinDefineArray(IR::Expr *result, IR::ExprList *args)
{
Instruction::CallBuiltinDefineArray call;
prepareCallArgs(args, call.argc, &call.args);
@@ -1277,7 +1282,7 @@ void InstructionSelection::callBuiltinDefineArray(IR::Temp *result, IR::ExprList
addInstruction(call);
}
-void InstructionSelection::callBuiltinDefineObjectLiteral(IR::Temp *result, int keyValuePairCount, IR::ExprList *keyValuePairs, IR::ExprList *arrayEntries, bool needSparseArray)
+void InstructionSelection::callBuiltinDefineObjectLiteral(IR::Expr *result, int keyValuePairCount, IR::ExprList *keyValuePairs, IR::ExprList *arrayEntries, bool needSparseArray)
{
int argLocation = outgoingArgumentTempStart();
@@ -1397,7 +1402,7 @@ void InstructionSelection::callBuiltinDefineObjectLiteral(IR::Temp *result, int
addInstruction(call);
}
-void InstructionSelection::callBuiltinSetupArgumentObject(IR::Temp *result)
+void InstructionSelection::callBuiltinSetupArgumentObject(IR::Expr *result)
{
Instruction::CallBuiltinSetupArgumentsObject call;
call.result = getResultParam(result);
@@ -1475,16 +1480,22 @@ Param InstructionSelection::getParam(IR::Expr *e) {
return Param::createConstant(idx);
} else if (IR::Temp *t = e->asTemp()) {
switch (t->kind) {
- case IR::Temp::Formal:
- case IR::Temp::ScopedFormal: return Param::createArgument(t->index, t->scope);
- case IR::Temp::Local: return Param::createLocal(t->index);
- case IR::Temp::ScopedLocal: return Param::createScopedLocal(t->index, t->scope);
case IR::Temp::StackSlot:
return Param::createTemp(t->index);
default:
Q_UNREACHABLE();
return Param();
}
+ } else if (IR::ArgLocal *al = e->asArgLocal()) {
+ switch (al->kind) {
+ case IR::ArgLocal::Formal:
+ case IR::ArgLocal::ScopedFormal: return Param::createArgument(al->index, al->scope);
+ case IR::ArgLocal::Local: return Param::createLocal(al->index);
+ case IR::ArgLocal::ScopedLocal: return Param::createScopedLocal(al->index, al->scope);
+ default:
+ Q_UNREACHABLE();
+ return Param();
+ }
} else {
Q_UNIMPLEMENTED();
return Param();
diff --git a/src/qml/compiler/qv4isel_moth_p.h b/src/qml/compiler/qv4isel_moth_p.h
index 0aa1972fb4..2fdb7c007c 100644
--- a/src/qml/compiler/qv4isel_moth_p.h
+++ b/src/qml/compiler/qv4isel_moth_p.h
@@ -80,60 +80,60 @@ protected:
virtual void visitCJump(IR::CJump *);
virtual void visitRet(IR::Ret *);
- virtual void callBuiltinInvalid(IR::Name *func, IR::ExprList *args, IR::Temp *result);
- virtual void callBuiltinTypeofMember(IR::Expr *base, const QString &name, IR::Temp *result);
- virtual void callBuiltinTypeofSubscript(IR::Expr *base, IR::Expr *index, IR::Temp *result);
- virtual void callBuiltinTypeofName(const QString &name, IR::Temp *result);
- virtual void callBuiltinTypeofValue(IR::Expr *value, IR::Temp *result);
- virtual void callBuiltinDeleteMember(IR::Temp *base, const QString &name, IR::Temp *result);
- virtual void callBuiltinDeleteSubscript(IR::Temp *base, IR::Expr *index, IR::Temp *result);
- virtual void callBuiltinDeleteName(const QString &name, IR::Temp *result);
- virtual void callBuiltinDeleteValue(IR::Temp *result);
+ virtual void callBuiltinInvalid(IR::Name *func, IR::ExprList *args, IR::Expr *result);
+ virtual void callBuiltinTypeofMember(IR::Expr *base, const QString &name, IR::Expr *result);
+ virtual void callBuiltinTypeofSubscript(IR::Expr *base, IR::Expr *index, IR::Expr *result);
+ virtual void callBuiltinTypeofName(const QString &name, IR::Expr *result);
+ virtual void callBuiltinTypeofValue(IR::Expr *value, IR::Expr *result);
+ virtual void callBuiltinDeleteMember(IR::Expr *base, const QString &name, IR::Expr *result);
+ virtual void callBuiltinDeleteSubscript(IR::Expr *base, IR::Expr *index, IR::Expr *result);
+ virtual void callBuiltinDeleteName(const QString &name, IR::Expr *result);
+ virtual void callBuiltinDeleteValue(IR::Expr *result);
virtual void callBuiltinThrow(IR::Expr *arg);
virtual void callBuiltinReThrow();
- virtual void callBuiltinUnwindException(IR::Temp *);
+ virtual void callBuiltinUnwindException(IR::Expr *);
virtual void callBuiltinPushCatchScope(const QString &exceptionName);
- virtual void callBuiltinForeachIteratorObject(IR::Expr *arg, IR::Temp *result);
- virtual void callBuiltinForeachNextPropertyname(IR::Temp *arg, IR::Temp *result);
- virtual void callBuiltinPushWithScope(IR::Temp *arg);
+ virtual void callBuiltinForeachIteratorObject(IR::Expr *arg, IR::Expr *result);
+ virtual void callBuiltinForeachNextPropertyname(IR::Expr *arg, IR::Expr *result);
+ virtual void callBuiltinPushWithScope(IR::Expr *arg);
virtual void callBuiltinPopScope();
virtual void callBuiltinDeclareVar(bool deletable, const QString &name);
- virtual void callBuiltinDefineArray(IR::Temp *result, IR::ExprList *args);
- virtual void callBuiltinDefineObjectLiteral(IR::Temp *result, int keyValuePairCount, IR::ExprList *keyValuePairs, IR::ExprList *arrayEntries, bool needSparseArray);
- virtual void callBuiltinSetupArgumentObject(IR::Temp *result);
+ virtual void callBuiltinDefineArray(IR::Expr *result, IR::ExprList *args);
+ virtual void callBuiltinDefineObjectLiteral(IR::Expr *result, int keyValuePairCount, IR::ExprList *keyValuePairs, IR::ExprList *arrayEntries, bool needSparseArray);
+ virtual void callBuiltinSetupArgumentObject(IR::Expr *result);
virtual void callBuiltinConvertThisToObject();
- virtual void callValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result);
- virtual void callProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Temp *result);
- virtual void callSubscript(IR::Expr *base, IR::Expr *index, IR::ExprList *args, IR::Temp *result);
- virtual void convertType(IR::Temp *source, IR::Temp *target);
- virtual void constructActivationProperty(IR::Name *func, IR::ExprList *args, IR::Temp *result);
- virtual void constructProperty(IR::Temp *base, const QString &name, IR::ExprList *args, IR::Temp *result);
- virtual void constructValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result);
- virtual void loadThisObject(IR::Temp *temp);
- virtual void loadQmlIdArray(IR::Temp *temp);
- virtual void loadQmlImportedScripts(IR::Temp *temp);
- virtual void loadQmlContextObject(IR::Temp *temp);
- virtual void loadQmlScopeObject(IR::Temp *temp);
- virtual void loadQmlSingleton(const QString &name, IR::Temp *temp);
- virtual void loadConst(IR::Const *sourceConst, IR::Temp *targetTemp);
- virtual void loadString(const QString &str, IR::Temp *targetTemp);
- virtual void loadRegexp(IR::RegExp *sourceRegexp, IR::Temp *targetTemp);
- virtual void getActivationProperty(const IR::Name *name, IR::Temp *temp);
+ virtual void callValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result);
+ virtual void callProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr *result);
+ virtual void callSubscript(IR::Expr *base, IR::Expr *index, IR::ExprList *args, IR::Expr *result);
+ virtual void convertType(IR::Expr *source, IR::Expr *target);
+ virtual void constructActivationProperty(IR::Name *func, IR::ExprList *args, IR::Expr *result);
+ virtual void constructProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr *result);
+ virtual void constructValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result);
+ virtual void loadThisObject(IR::Expr *e);
+ virtual void loadQmlIdArray(IR::Expr *e);
+ virtual void loadQmlImportedScripts(IR::Expr *e);
+ virtual void loadQmlContextObject(IR::Expr *e);
+ virtual void loadQmlScopeObject(IR::Expr *e);
+ virtual void loadQmlSingleton(const QString &name, IR::Expr *e);
+ virtual void loadConst(IR::Const *sourceConst, IR::Expr *e);
+ virtual void loadString(const QString &str, IR::Expr *target);
+ virtual void loadRegexp(IR::RegExp *sourceRegexp, IR::Expr *target);
+ virtual void getActivationProperty(const IR::Name *name, IR::Expr *target);
virtual void setActivationProperty(IR::Expr *source, const QString &targetName);
- virtual void initClosure(IR::Closure *closure, IR::Temp *target);
- virtual void getProperty(IR::Expr *base, const QString &name, IR::Temp *target);
+ virtual void initClosure(IR::Closure *closure, IR::Expr *target);
+ virtual void getProperty(IR::Expr *base, const QString &name, IR::Expr *target);
virtual void setProperty(IR::Expr *source, IR::Expr *targetBase, const QString &targetName);
virtual void setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex);
- virtual void getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, IR::Temp *target);
- virtual void getElement(IR::Expr *base, IR::Expr *index, IR::Temp *target);
+ virtual void getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, IR::Expr *target);
+ virtual void getElement(IR::Expr *base, IR::Expr *index, IR::Expr *target);
virtual void setElement(IR::Expr *source, IR::Expr *targetBase, IR::Expr *targetIndex);
- virtual void copyValue(IR::Temp *sourceTemp, IR::Temp *targetTemp);
- virtual void swapValues(IR::Temp *sourceTemp, IR::Temp *targetTemp);
- virtual void unop(IR::AluOp oper, IR::Temp *sourceTemp, IR::Temp *targetTemp);
- virtual void binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target);
+ virtual void copyValue(IR::Expr *source, IR::Expr *target);
+ virtual void swapValues(IR::Expr *source, IR::Expr *target);
+ virtual void unop(IR::AluOp oper, IR::Expr *source, IR::Expr *target);
+ virtual void binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *target);
private:
- Param binopHelper(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target);
+ Param binopHelper(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *target);
struct Instruction {
#define MOTH_INSTR_DATA_TYPEDEF(I, FMT) typedef InstrData<Instr::I> I;
@@ -145,7 +145,7 @@ private:
Param getParam(IR::Expr *e);
- Param getResultParam(IR::Temp *result)
+ Param getResultParam(IR::Expr *result)
{
if (result)
return getParam(result);
@@ -184,7 +184,7 @@ private:
QSet<IR::Jump *> _removableJumps;
IR::Stmt *_currentStatement;
- CompilationUnit *compilationUnit;
+ QScopedPointer<CompilationUnit> compilationUnit;
QHash<IR::Function *, QByteArray> codeRefs;
};
diff --git a/src/qml/compiler/qv4isel_p.cpp b/src/qml/compiler/qv4isel_p.cpp
index 429688090c..1aa0c4dad8 100644
--- a/src/qml/compiler/qv4isel_p.cpp
+++ b/src/qml/compiler/qv4isel_p.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtQml module of the Qt Toolkit.
@@ -93,54 +93,54 @@ QV4::CompiledData::CompilationUnit *EvalInstructionSelection::compile(bool gener
void IRDecoder::visitMove(IR::Move *s)
{
if (IR::Name *n = s->target->asName()) {
- if (s->source->asTemp() || s->source->asConst()) {
+ if (s->source->asTemp() || s->source->asConst() || s->source->asArgLocal()) {
setActivationProperty(s->source, *n->id);
return;
}
- } else if (IR::Temp *t = s->target->asTemp()) {
+ } else if (s->target->asTemp() || s->target->asArgLocal()) {
if (IR::Name *n = s->source->asName()) {
if (n->id && *n->id == QStringLiteral("this")) // TODO: `this' should be a builtin.
- loadThisObject(t);
+ loadThisObject(s->target);
else if (n->builtin == IR::Name::builtin_qml_id_array)
- loadQmlIdArray(t);
+ loadQmlIdArray(s->target);
else if (n->builtin == IR::Name::builtin_qml_context_object)
- loadQmlContextObject(t);
+ loadQmlContextObject(s->target);
else if (n->builtin == IR::Name::builtin_qml_scope_object)
- loadQmlScopeObject(t);
+ loadQmlScopeObject(s->target);
else if (n->builtin == IR::Name::builtin_qml_imported_scripts_object)
- loadQmlImportedScripts(t);
+ loadQmlImportedScripts(s->target);
else if (n->qmlSingleton)
- loadQmlSingleton(*n->id, t);
+ loadQmlSingleton(*n->id, s->target);
else
- getActivationProperty(n, t);
+ getActivationProperty(n, s->target);
return;
} else if (IR::Const *c = s->source->asConst()) {
- loadConst(c, t);
+ loadConst(c, s->target);
return;
- } else if (IR::Temp *t2 = s->source->asTemp()) {
+ } else if (s->source->asTemp() || s->source->asArgLocal()) {
if (s->swap)
- swapValues(t2, t);
+ swapValues(s->source, s->target);
else
- copyValue(t2, t);
+ copyValue(s->source, s->target);
return;
} else if (IR::String *str = s->source->asString()) {
- loadString(*str->value, t);
+ loadString(*str->value, s->target);
return;
} else if (IR::RegExp *re = s->source->asRegExp()) {
- loadRegexp(re, t);
+ loadRegexp(re, s->target);
return;
} else if (IR::Closure *clos = s->source->asClosure()) {
- initClosure(clos, t);
+ initClosure(clos, s->target);
return;
} else if (IR::New *ctor = s->source->asNew()) {
if (Name *func = ctor->base->asName()) {
- constructActivationProperty(func, ctor->args, t);
+ constructActivationProperty(func, ctor->args, s->target);
return;
} else if (IR::Member *member = ctor->base->asMember()) {
- constructProperty(member->base->asTemp(), *member->name, ctor->args, t);
+ constructProperty(member->base, *member->name, ctor->args, s->target);
return;
- } else if (IR::Temp *value = ctor->base->asTemp()) {
- constructValue(value, ctor->args, t);
+ } else if (ctor->base->asTemp() || ctor->base->asArgLocal()) {
+ constructValue(ctor->base, ctor->args, s->target);
return;
}
} else if (IR::Member *m = s->source->asMember()) {
@@ -162,46 +162,44 @@ void IRDecoder::visitMove(IR::Move *s)
captureRequired = false;
}
}
- getQObjectProperty(m->base, m->property->coreIndex, captureRequired, attachedPropertiesId, t);
+ getQObjectProperty(m->base, m->property->coreIndex, captureRequired, attachedPropertiesId, s->target);
#endif // V4_BOOTSTRAP
return;
- } else if (m->base->asTemp() || m->base->asConst()) {
- getProperty(m->base, *m->name, t);
+ } else if (m->base->asTemp() || m->base->asConst() || m->base->asArgLocal()) {
+ getProperty(m->base, *m->name, s->target);
return;
}
} else if (IR::Subscript *ss = s->source->asSubscript()) {
- getElement(ss->base, ss->index, t);
+ getElement(ss->base, ss->index, s->target);
return;
} else if (IR::Unop *u = s->source->asUnop()) {
- if (IR::Temp *e = u->expr->asTemp()) {
- unop(u->op, e, t);
- return;
- }
+ unop(u->op, u->expr, s->target);
+ return;
} else if (IR::Binop *b = s->source->asBinop()) {
- binop(b->op, b->left, b->right, t);
+ binop(b->op, b->left, b->right, s->target);
return;
} else if (IR::Call *c = s->source->asCall()) {
if (c->base->asName()) {
- callBuiltin(c, t);
+ callBuiltin(c, s->target);
return;
} else if (Member *member = c->base->asMember()) {
- callProperty(member->base, *member->name, c->args, t);
+ callProperty(member->base, *member->name, c->args, s->target);
return;
} else if (Subscript *ss = c->base->asSubscript()) {
- callSubscript(ss->base, ss->index, c->args, t);
+ callSubscript(ss->base, ss->index, c->args, s->target);
return;
- } else if (IR::Temp *value = c->base->asTemp()) {
- callValue(value, c->args, t);
+ } else if (c->base->asTemp() || c->base->asArgLocal()) {
+ callValue(c->base, c->args, s->target);
return;
}
} else if (IR::Convert *c = s->source->asConvert()) {
- Q_ASSERT(c->expr->asTemp());
- convertType(c->expr->asTemp(), t);
+ Q_ASSERT(c->expr->asTemp() || c->expr->asArgLocal());
+ convertType(c->expr, s->target);
return;
}
} else if (IR::Member *m = s->target->asMember()) {
- if (m->base->asTemp() || m->base->asConst()) {
- if (s->source->asTemp() || s->source->asConst()) {
+ if (m->base->asTemp() || m->base->asConst() || m->base->asArgLocal()) {
+ if (s->source->asTemp() || s->source->asConst() || s->source->asArgLocal()) {
Q_ASSERT(m->kind != IR::Member::MemberOfEnum);
const int attachedPropertiesId = m->attachedPropertiesIdOrEnumValue;
if (m->property && attachedPropertiesId == 0) {
@@ -218,7 +216,7 @@ void IRDecoder::visitMove(IR::Move *s)
}
}
} else if (IR::Subscript *ss = s->target->asSubscript()) {
- if (s->source->asTemp() || s->source->asConst()) {
+ if (s->source->asTemp() || s->source->asConst() || s->source->asArgLocal()) {
setElement(s->source, ss->base, ss->index);
return;
}
@@ -226,7 +224,7 @@ void IRDecoder::visitMove(IR::Move *s)
// For anything else...:
Q_UNIMPLEMENTED();
- s->dump(qout, IR::Stmt::MIR);
+ IRPrinter(&qout).print(s);
qout << endl;
Q_ASSERT(!"TODO");
}
@@ -241,22 +239,22 @@ void IRDecoder::visitExp(IR::Exp *s)
// These are calls where the result is ignored.
if (c->base->asName()) {
callBuiltin(c, 0);
- } else if (Temp *value = c->base->asTemp()) {
- callValue(value, c->args, 0);
+ } else if (c->base->asTemp() || c->base->asArgLocal() || c->base->asConst()) {
+ callValue(c->base, c->args, 0);
} else if (Member *member = c->base->asMember()) {
- Q_ASSERT(member->base->asTemp());
- callProperty(member->base->asTemp(), *member->name, c->args, 0);
+ Q_ASSERT(member->base->asTemp() || member->base->asArgLocal());
+ callProperty(member->base, *member->name, c->args, 0);
} else if (Subscript *s = c->base->asSubscript()) {
callSubscript(s->base, s->index, c->args, 0);
} else {
- Q_UNIMPLEMENTED();
+ Q_UNREACHABLE();
}
} else {
- Q_UNIMPLEMENTED();
+ Q_UNREACHABLE();
}
}
-void IRDecoder::callBuiltin(IR::Call *call, IR::Temp *result)
+void IRDecoder::callBuiltin(IR::Call *call, Expr *result)
{
IR::Name *baseName = call->base->asName();
Q_ASSERT(baseName != 0);
@@ -276,7 +274,9 @@ void IRDecoder::callBuiltin(IR::Call *call, IR::Temp *result)
} else if (IR::Name *n = call->args->expr->asName()) {
callBuiltinTypeofName(*n->id, result);
return;
- } else if (call->args->expr->asTemp() || call->args->expr->asConst()){
+ } else if (call->args->expr->asTemp() ||
+ call->args->expr->asConst() ||
+ call->args->expr->asArgLocal()) {
callBuiltinTypeofValue(call->args->expr, result);
return;
}
@@ -284,15 +284,16 @@ void IRDecoder::callBuiltin(IR::Call *call, IR::Temp *result)
case IR::Name::builtin_delete: {
if (IR::Member *m = call->args->expr->asMember()) {
- callBuiltinDeleteMember(m->base->asTemp(), *m->name, result);
+ callBuiltinDeleteMember(m->base, *m->name, result);
return;
} else if (IR::Subscript *ss = call->args->expr->asSubscript()) {
- callBuiltinDeleteSubscript(ss->base->asTemp(), ss->index, result);
+ callBuiltinDeleteSubscript(ss->base, ss->index, result);
return;
} else if (IR::Name *n = call->args->expr->asName()) {
callBuiltinDeleteName(*n->id, result);
return;
- } else if (call->args->expr->asTemp()){
+ } else if (call->args->expr->asTemp() ||
+ call->args->expr->asArgLocal()) {
// TODO: should throw in strict mode
callBuiltinDeleteValue(result);
return;
@@ -301,7 +302,7 @@ void IRDecoder::callBuiltin(IR::Call *call, IR::Temp *result)
case IR::Name::builtin_throw: {
IR::Expr *arg = call->args->expr;
- Q_ASSERT(arg->asTemp() || arg->asConst());
+ Q_ASSERT(arg->asTemp() || arg->asConst() || arg->asArgLocal());
callBuiltinThrow(arg);
} return;
@@ -326,14 +327,15 @@ void IRDecoder::callBuiltin(IR::Call *call, IR::Temp *result)
} return;
case IR::Name::builtin_foreach_next_property_name: {
- IR::Temp *arg = call->args->expr->asTemp();
+ IR::Expr *arg = call->args->expr;
Q_ASSERT(arg != 0);
callBuiltinForeachNextPropertyname(arg, result);
} return;
case IR::Name::builtin_push_with_scope: {
- IR::Temp *arg = call->args->expr->asTemp();
- Q_ASSERT(arg != 0);
- callBuiltinPushWithScope(arg);
+ if (call->args->expr->asTemp() || call->args->expr->asArgLocal())
+ callBuiltinPushWithScope(call->args->expr);
+ else
+ Q_UNIMPLEMENTED();
} return;
case IR::Name::builtin_pop_scope:
@@ -402,7 +404,7 @@ void IRDecoder::callBuiltin(IR::Call *call, IR::Temp *result)
}
Q_UNIMPLEMENTED();
- call->dump(qout); qout << endl;
+ IRPrinter(&qout).print(call); qout << endl;
Q_ASSERT(!"TODO!");
Q_UNREACHABLE();
}
diff --git a/src/qml/compiler/qv4isel_p.h b/src/qml/compiler/qv4isel_p.h
index 74e6ba8200..cbfc21c211 100644
--- a/src/qml/compiler/qv4isel_p.h
+++ b/src/qml/compiler/qv4isel_p.h
@@ -112,60 +112,60 @@ public: // visitor methods for StmtVisitor:
virtual void visitExp(IR::Exp *s);
public: // to implement by subclasses:
- virtual void callBuiltinInvalid(IR::Name *func, IR::ExprList *args, IR::Temp *result) = 0;
- virtual void callBuiltinTypeofMember(IR::Expr *base, const QString &name, IR::Temp *result) = 0;
- virtual void callBuiltinTypeofSubscript(IR::Expr *base, IR::Expr *index, IR::Temp *result) = 0;
- virtual void callBuiltinTypeofName(const QString &name, IR::Temp *result) = 0;
- virtual void callBuiltinTypeofValue(IR::Expr *value, IR::Temp *result) = 0;
- virtual void callBuiltinDeleteMember(IR::Temp *base, const QString &name, IR::Temp *result) = 0;
- virtual void callBuiltinDeleteSubscript(IR::Temp *base, IR::Expr *index, IR::Temp *result) = 0;
- virtual void callBuiltinDeleteName(const QString &name, IR::Temp *result) = 0;
- virtual void callBuiltinDeleteValue(IR::Temp *result) = 0;
+ virtual void callBuiltinInvalid(IR::Name *func, IR::ExprList *args, IR::Expr *result) = 0;
+ virtual void callBuiltinTypeofMember(IR::Expr *base, const QString &name, IR::Expr *result) = 0;
+ virtual void callBuiltinTypeofSubscript(IR::Expr *base, IR::Expr *index, IR::Expr *result) = 0;
+ virtual void callBuiltinTypeofName(const QString &name, IR::Expr *result) = 0;
+ virtual void callBuiltinTypeofValue(IR::Expr *value, IR::Expr *result) = 0;
+ virtual void callBuiltinDeleteMember(IR::Expr *base, const QString &name, IR::Expr *result) = 0;
+ virtual void callBuiltinDeleteSubscript(IR::Expr *base, IR::Expr *index, IR::Expr *result) = 0;
+ virtual void callBuiltinDeleteName(const QString &name, IR::Expr *result) = 0;
+ virtual void callBuiltinDeleteValue(IR::Expr *result) = 0;
virtual void callBuiltinThrow(IR::Expr *arg) = 0;
virtual void callBuiltinReThrow() = 0;
- virtual void callBuiltinUnwindException(IR::Temp *) = 0;
+ virtual void callBuiltinUnwindException(IR::Expr *) = 0;
virtual void callBuiltinPushCatchScope(const QString &exceptionName) = 0;
- virtual void callBuiltinForeachIteratorObject(IR::Expr *arg, IR::Temp *result) = 0;
- virtual void callBuiltinForeachNextPropertyname(IR::Temp *arg, IR::Temp *result) = 0;
- virtual void callBuiltinPushWithScope(IR::Temp *arg) = 0;
+ virtual void callBuiltinForeachIteratorObject(IR::Expr *arg, IR::Expr *result) = 0;
+ virtual void callBuiltinForeachNextPropertyname(IR::Expr *arg, IR::Expr *result) = 0;
+ virtual void callBuiltinPushWithScope(IR::Expr *arg) = 0;
virtual void callBuiltinPopScope() = 0;
virtual void callBuiltinDeclareVar(bool deletable, const QString &name) = 0;
- virtual void callBuiltinDefineArray(IR::Temp *result, IR::ExprList *args) = 0;
- virtual void callBuiltinDefineObjectLiteral(IR::Temp *result, int keyValuePairCount, IR::ExprList *keyValuePairs, IR::ExprList *arrayEntries, bool needSparseArray) = 0;
- virtual void callBuiltinSetupArgumentObject(IR::Temp *result) = 0;
+ virtual void callBuiltinDefineArray(IR::Expr *result, IR::ExprList *args) = 0;
+ virtual void callBuiltinDefineObjectLiteral(IR::Expr *result, int keyValuePairCount, IR::ExprList *keyValuePairs, IR::ExprList *arrayEntries, bool needSparseArray) = 0;
+ virtual void callBuiltinSetupArgumentObject(IR::Expr *result) = 0;
virtual void callBuiltinConvertThisToObject() = 0;
- virtual void callValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result) = 0;
- virtual void callProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Temp *result) = 0;
- virtual void callSubscript(IR::Expr *base, IR::Expr *index, IR::ExprList *args, IR::Temp *result) = 0;
- virtual void convertType(IR::Temp *source, IR::Temp *target) = 0;
- virtual void constructActivationProperty(IR::Name *func, IR::ExprList *args, IR::Temp *result) = 0;
- virtual void constructProperty(IR::Temp *base, const QString &name, IR::ExprList *args, IR::Temp *result) = 0;
- virtual void constructValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result) = 0;
- virtual void loadThisObject(IR::Temp *temp) = 0;
- virtual void loadQmlIdArray(IR::Temp *temp) = 0;
- virtual void loadQmlImportedScripts(IR::Temp *temp) = 0;
- virtual void loadQmlContextObject(IR::Temp *temp) = 0;
- virtual void loadQmlScopeObject(IR::Temp *temp) = 0;
- virtual void loadQmlSingleton(const QString &name, IR::Temp *temp) = 0;
- virtual void loadConst(IR::Const *sourceConst, IR::Temp *targetTemp) = 0;
- virtual void loadString(const QString &str, IR::Temp *targetTemp) = 0;
- virtual void loadRegexp(IR::RegExp *sourceRegexp, IR::Temp *targetTemp) = 0;
- virtual void getActivationProperty(const IR::Name *name, IR::Temp *temp) = 0;
+ virtual void callValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result) = 0;
+ virtual void callProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr *result) = 0;
+ virtual void callSubscript(IR::Expr *base, IR::Expr *index, IR::ExprList *args, IR::Expr *result) = 0;
+ virtual void convertType(IR::Expr *source, IR::Expr *target) = 0;
+ virtual void constructActivationProperty(IR::Name *func, IR::ExprList *args, IR::Expr *result) = 0;
+ virtual void constructProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr *result) = 0;
+ virtual void constructValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result) = 0;
+ virtual void loadThisObject(IR::Expr *target) = 0;
+ virtual void loadQmlIdArray(IR::Expr *target) = 0;
+ virtual void loadQmlImportedScripts(IR::Expr *target) = 0;
+ virtual void loadQmlContextObject(IR::Expr *target) = 0;
+ virtual void loadQmlScopeObject(IR::Expr *target) = 0;
+ virtual void loadQmlSingleton(const QString &name, IR::Expr *target) = 0;
+ virtual void loadConst(IR::Const *sourceConst, IR::Expr *target) = 0;
+ virtual void loadString(const QString &str, IR::Expr *target) = 0;
+ virtual void loadRegexp(IR::RegExp *sourceRegexp, IR::Expr *target) = 0;
+ virtual void getActivationProperty(const IR::Name *name, IR::Expr *target) = 0;
virtual void setActivationProperty(IR::Expr *source, const QString &targetName) = 0;
- virtual void initClosure(IR::Closure *closure, IR::Temp *target) = 0;
- virtual void getProperty(IR::Expr *base, const QString &name, IR::Temp *target) = 0;
- virtual void getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, IR::Temp *targetTemp) = 0;
+ virtual void initClosure(IR::Closure *closure, IR::Expr *target) = 0;
+ virtual void getProperty(IR::Expr *base, const QString &name, IR::Expr *target) = 0;
+ virtual void getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, IR::Expr *target) = 0;
virtual void setProperty(IR::Expr *source, IR::Expr *targetBase, const QString &targetName) = 0;
virtual void setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex) = 0;
- virtual void getElement(IR::Expr *base, IR::Expr *index, IR::Temp *target) = 0;
+ virtual void getElement(IR::Expr *base, IR::Expr *index, IR::Expr *target) = 0;
virtual void setElement(IR::Expr *source, IR::Expr *targetBase, IR::Expr *targetIndex) = 0;
- virtual void copyValue(IR::Temp *sourceTemp, IR::Temp *targetTemp) = 0;
- virtual void swapValues(IR::Temp *sourceTemp, IR::Temp *targetTemp) = 0;
- virtual void unop(IR::AluOp oper, IR::Temp *sourceTemp, IR::Temp *targetTemp) = 0;
- virtual void binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target) = 0;
+ virtual void copyValue(IR::Expr *source, IR::Expr *target) = 0;
+ virtual void swapValues(IR::Expr *source, IR::Expr *target) = 0;
+ virtual void unop(IR::AluOp oper, IR::Expr *source, IR::Expr *target) = 0;
+ virtual void binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *target) = 0;
protected:
- virtual void callBuiltin(IR::Call *c, IR::Temp *result);
+ virtual void callBuiltin(IR::Call *c, IR::Expr *result);
IR::Function *_function; // subclass needs to set
};
diff --git a/src/qml/compiler/qv4isel_util_p.h b/src/qml/compiler/qv4isel_util_p.h
index 09b98a18d1..483e0eb8b4 100644
--- a/src/qml/compiler/qv4isel_util_p.h
+++ b/src/qml/compiler/qv4isel_util_p.h
@@ -153,6 +153,7 @@ protected:
virtual void visitRegExp(IR::RegExp *) {}
virtual void visitName(IR::Name *) {}
virtual void visitTemp(IR::Temp *e) { renumber(e); }
+ virtual void visitArgLocal(IR::ArgLocal *) {}
virtual void visitClosure(IR::Closure *) {}
virtual void visitConvert(IR::Convert *e) { e->expr->accept(this); }
virtual void visitUnop(IR::Unop *e) { e->expr->accept(this); }
diff --git a/src/qml/compiler/qv4jsir.cpp b/src/qml/compiler/qv4jsir.cpp
index f81985c07d..4b26ff20b7 100644
--- a/src/qml/compiler/qv4jsir.cpp
+++ b/src/qml/compiler/qv4jsir.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtQml module of the Qt Toolkit.
@@ -45,6 +45,8 @@
#ifndef V4_BOOTSTRAP
#include <private/qqmlpropertycache_p.h>
#endif
+
+#include <QtCore/QBuffer>
#include <QtCore/qtextstream.h>
#include <QtCore/qdebug.h>
#include <QtCore/qset.h>
@@ -231,6 +233,7 @@ struct RemoveSharedExpressions: IR::StmtVisitor, IR::ExprVisitor
virtual void visitRegExp(RegExp *) {}
virtual void visitName(Name *) {}
virtual void visitTemp(Temp *) {}
+ virtual void visitArgLocal(ArgLocal *) {}
virtual void visitClosure(Closure *) {}
virtual void visitConvert(Convert *e)
@@ -275,104 +278,6 @@ struct RemoveSharedExpressions: IR::StmtVisitor, IR::ExprVisitor
}
};
-static QString dumpStart(const Expr *e) {
- if (e->type == UnknownType)
-// return QStringLiteral("**UNKNOWN**");
- return QString();
-
- QString result = typeName(e->type);
-#ifndef V4_BOOTSTRAP
- const Temp *temp = const_cast<Expr*>(e)->asTemp();
- if (e->type == QObjectType && temp && temp->memberResolver.isQObjectResolver) {
- result += QLatin1Char('<');
- result += QString::fromUtf8(static_cast<QQmlPropertyCache*>(temp->memberResolver.data)->className());
- result += QLatin1Char('>');
- }
-#endif
- result += QLatin1Char('{');
- return result;
-}
-
-static const char *dumpEnd(const Expr *e) {
- if (e->type == UnknownType)
- return "";
- else
- return "}";
-}
-
-void Const::dump(QTextStream &out) const
-{
- if (type != UndefinedType && type != NullType)
- out << dumpStart(this);
- switch (type) {
- case QV4::IR::UndefinedType:
- out << "undefined";
- break;
- case QV4::IR::NullType:
- out << "null";
- break;
- case QV4::IR::BoolType:
- out << (value ? "true" : "false");
- break;
- case QV4::IR::MissingType:
- out << "missing";
- break;
- default:
- if (int(value) == 0 && int(value) == value) {
- if (isNegative(value))
- out << "-0";
- else
- out << "0";
- } else {
- out << QString::number(value, 'g', 16);
- }
- break;
- }
- if (type != UndefinedType && type != NullType)
- out << dumpEnd(this);
-}
-
-void String::dump(QTextStream &out) const
-{
- out << '"' << escape(*value) << '"';
-}
-
-QString String::escape(const QString &s)
-{
- QString r;
- for (int i = 0; i < s.length(); ++i) {
- const QChar ch = s.at(i);
- if (ch == QLatin1Char('\n'))
- r += QStringLiteral("\\n");
- else if (ch == QLatin1Char('\r'))
- r += QStringLiteral("\\r");
- else if (ch == QLatin1Char('\\'))
- r += QStringLiteral("\\\\");
- else if (ch == QLatin1Char('"'))
- r += QStringLiteral("\\\"");
- else if (ch == QLatin1Char('\''))
- r += QStringLiteral("\\'");
- else
- r += ch;
- }
- return r;
-}
-
-void RegExp::dump(QTextStream &out) const
-{
- char f[3];
- int i = 0;
- if (flags & RegExp_Global)
- f[i++] = 'g';
- if (flags & RegExp_IgnoreCase)
- f[i++] = 'i';
- if (flags & RegExp_Multiline)
- f[i++] = 'm';
- f[i] = 0;
-
- out << '/' << *value << '/' << f;
-}
-
void Name::initGlobal(const QString *id, quint32 line, quint32 column)
{
this->id = id;
@@ -453,185 +358,11 @@ static const char *builtin_to_string(Name::Builtin b)
return "builtin_(###FIXME)";
};
-void Name::dump(QTextStream &out) const
-{
- if (id)
- out << *id;
- else
- out << builtin_to_string(builtin);
-}
-
-void Temp::dump(QTextStream &out) const
-{
- out << dumpStart(this);
- switch (kind) {
- case Formal: out << '#' << index; break;
- case ScopedFormal: out << '#' << index
- << '@' << scope; break;
- case Local: out << '$' << index; break;
- case ScopedLocal: out << '$' << index
- << '@' << scope; break;
- case VirtualRegister: out << '%' << index; break;
- case PhysicalRegister: out << (type == DoubleType ? "fp" : "r")
- << index; break;
- case StackSlot: out << '&' << index; break;
- default: out << "INVALID";
- }
- out << dumpEnd(this);
-}
-
bool operator<(const Temp &t1, const Temp &t2) Q_DECL_NOTHROW
{
if (t1.kind < t2.kind) return true;
if (t1.kind > t2.kind) return false;
- if (t1.index < t2.index) return true;
- if (t1.index > t2.index) return false;
- return t1.scope < t2.scope;
-}
-
-void Closure::dump(QTextStream &out) const
-{
- QString name = functionName ? *functionName : QString();
- if (name.isEmpty())
- name.sprintf("%x", value);
- out << "closure(" << name << ')';
-}
-
-void Convert::dump(QTextStream &out) const
-{
- out << dumpStart(this);
- out << "convert(";
- expr->dump(out);
- out << ')' << dumpEnd(this);
-}
-
-void Unop::dump(QTextStream &out) const
-{
- out << dumpStart(this) << opname(op);
- expr->dump(out);
- out << dumpEnd(this);
-}
-
-void Binop::dump(QTextStream &out) const
-{
- out << dumpStart(this);
- left->dump(out);
- out << ' ' << opname(op) << ' ';
- right->dump(out);
- out << dumpEnd(this);
-}
-
-void Call::dump(QTextStream &out) const
-{
- base->dump(out);
- out << '(';
- for (ExprList *it = args; it; it = it->next) {
- if (it != args)
- out << ", ";
- it->expr->dump(out);
- }
- out << ')';
-}
-
-void New::dump(QTextStream &out) const
-{
- out << "new ";
- base->dump(out);
- out << '(';
- for (ExprList *it = args; it; it = it->next) {
- if (it != args)
- out << ", ";
- it->expr->dump(out);
- }
- out << ')';
-}
-
-void Subscript::dump(QTextStream &out) const
-{
- base->dump(out);
- out << '[';
- index->dump(out);
- out << ']';
-}
-
-void Member::dump(QTextStream &out) const
-{
- if (kind != MemberOfEnum && attachedPropertiesIdOrEnumValue != 0 && !base->asTemp())
- out << "[[attached property from " << attachedPropertiesIdOrEnumValue << "]]";
- else
- base->dump(out);
- out << '.' << *name;
-#ifndef V4_BOOTSTRAP
- if (property)
- out << " (meta-property " << property->coreIndex << " <" << QMetaType::typeName(property->propType) << ">)";
-#endif
-}
-
-void Exp::dump(QTextStream &out, Mode)
-{
- out << "(void) ";
- expr->dump(out);
- out << ';';
-}
-
-void Move::dump(QTextStream &out, Mode mode)
-{
- Q_UNUSED(mode);
-
- target->dump(out);
- out << ' ';
- if (swap)
- out << "<=> ";
- else
- out << "= ";
-// if (source->type != target->type)
-// out << typeName(source->type) << "_to_" << typeName(target->type) << '(';
- source->dump(out);
-// if (source->type != target->type)
-// out << ')';
- out << ';';
-}
-
-void Jump::dump(QTextStream &out, Mode mode)
-{
- Q_UNUSED(mode);
- out << "goto " << 'L' << target->index() << ';';
-}
-
-void CJump::dump(QTextStream &out, Mode mode)
-{
- Q_UNUSED(mode);
- out << "if (";
- cond->dump(out);
- if (mode == HIR)
- out << ") goto " << 'L' << iftrue->index() << "; else goto " << 'L' << iffalse->index() << ';';
- else
- out << ") goto " << 'L' << iftrue->index() << ";";
-}
-
-void Ret::dump(QTextStream &out, Mode)
-{
- out << "return";
- if (expr) {
- out << ' ';
- expr->dump(out);
- }
- out << ';';
-}
-
-void Phi::dump(QTextStream &out, Stmt::Mode mode)
-{
- Q_UNUSED(mode);
-
- targetTemp->dump(out);
- out << " = phi(";
- for (int i = 0, ei = d->incoming.size(); i < ei; ++i) {
- if (i > 0)
- out << ", ";
- if (d->incoming[i])
- d->incoming[i]->dump(out);
- }
- out << ");";
+ return t1.index < t2.index;
}
Function *Module::newFunction(const QString &name, Function *outer)
@@ -680,6 +411,7 @@ Function::Function(Module *module, Function *outer, const QString &name)
, line(-1)
, column(-1)
, _allBasicBlocks(0)
+ , _statementCount(0)
{
this->name = newString(name);
_basicBlocks.reserve(8);
@@ -704,9 +436,9 @@ const QString *Function::newString(const QString &text)
return &*strings.insert(text);
}
-BasicBlock *Function::newBasicBlock(BasicBlock *containingLoop, BasicBlock *catchBlock, BasicBlockInsertMode mode)
+BasicBlock *Function::newBasicBlock(BasicBlock *catchBlock, BasicBlockInsertMode mode)
{
- BasicBlock *block = new BasicBlock(this, containingLoop, catchBlock);
+ BasicBlock *block = new BasicBlock(this, catchBlock);
return mode == InsertBlock ? addBasicBlock(block) : block;
}
@@ -734,21 +466,6 @@ int Function::liveBasicBlocksCount() const
return count;
}
-void Function::dump(QTextStream &out, Stmt::Mode mode)
-{
- QString n = name ? *name : QString();
- if (n.isEmpty())
- n.sprintf("%p", this);
- out << "function " << n << "() {" << endl;
- foreach (const QString *formal, formals)
- out << "\treceive " << *formal << ';' << endl;
- foreach (const QString *local, locals)
- out << "\tlocal " << *local << ';' << endl;
- foreach (BasicBlock *bb, basicBlocks())
- bb->dump(out, mode);
- out << '}' << endl;
-}
-
void Function::removeSharedExpressions()
{
RemoveSharedExpressions removeSharedExpressions;
@@ -793,23 +510,23 @@ Temp *BasicBlock::TEMP(unsigned index)
{
Q_ASSERT(!isRemoved());
Temp *e = function->New<Temp>();
- e->init(Temp::VirtualRegister, index, 0);
+ e->init(Temp::VirtualRegister, index);
return e;
}
-Temp *BasicBlock::ARG(unsigned index, unsigned scope)
+ArgLocal *BasicBlock::ARG(unsigned index, unsigned scope)
{
Q_ASSERT(!isRemoved());
- Temp *e = function->New<Temp>();
- e->init(scope ? Temp::ScopedFormal : Temp::Formal, index, scope);
+ ArgLocal *e = function->New<ArgLocal>();
+ e->init(scope ? ArgLocal::ScopedFormal : ArgLocal::Formal, index, scope);
return e;
}
-Temp *BasicBlock::LOCAL(unsigned index, unsigned scope)
+ArgLocal *BasicBlock::LOCAL(unsigned index, unsigned scope)
{
Q_ASSERT(!isRemoved());
- Temp *e = function->New<Temp>();
- e->init(scope ? Temp::ScopedLocal : Temp::Local, index, scope);
+ ArgLocal *e = function->New<ArgLocal>();
+ e->init(scope ? ArgLocal::ScopedLocal : ArgLocal::Local, index, scope);
return e;
}
@@ -949,7 +666,7 @@ Stmt *BasicBlock::EXP(Expr *expr)
if (isTerminated())
return 0;
- Exp *s = function->New<Exp>();
+ Exp *s = function->NewStmt<Exp>();
s->init(expr);
appendStatement(s);
return s;
@@ -961,7 +678,7 @@ Stmt *BasicBlock::MOVE(Expr *target, Expr *source)
if (isTerminated())
return 0;
- Move *s = function->New<Move>();
+ Move *s = function->NewStmt<Move>();
s->init(target, source);
appendStatement(s);
return s;
@@ -973,7 +690,7 @@ Stmt *BasicBlock::JUMP(BasicBlock *target)
if (isTerminated())
return 0;
- Jump *s = function->New<Jump>();
+ Jump *s = function->NewStmt<Jump>();
s->init(target);
appendStatement(s);
@@ -997,7 +714,7 @@ Stmt *BasicBlock::CJUMP(Expr *cond, BasicBlock *iftrue, BasicBlock *iffalse)
return JUMP(iftrue);
}
- CJump *s = function->New<CJump>();
+ CJump *s = function->NewStmt<CJump>();
s->init(cond, iftrue, iffalse);
appendStatement(s);
@@ -1022,29 +739,12 @@ Stmt *BasicBlock::RET(Temp *expr)
if (isTerminated())
return 0;
- Ret *s = function->New<Ret>();
+ Ret *s = function->NewStmt<Ret>();
s->init(expr);
appendStatement(s);
return s;
}
-void BasicBlock::dump(QTextStream &out, Stmt::Mode mode)
-{
- out << 'L' << index() << ':';
- if (catchBlock)
- out << " (catchBlock L" << catchBlock->index() << ")";
- out << endl;
- foreach (Stmt *s, statements()) {
- out << '\t';
- s->dump(out, mode);
-
- if (s->location.isValid())
- out << " // line: " << s->location.startLine << " ; column: " << s->location.startColumn;
-
- out << endl;
- }
-}
-
void BasicBlock::setStatements(const QVector<Stmt *> &newStatements)
{
Q_ASSERT(!isRemoved());
@@ -1071,6 +771,14 @@ void BasicBlock::prependStatement(Stmt *stmt)
_statements.prepend(stmt);
}
+void BasicBlock::prependStatements(const QVector<Stmt *> &stmts)
+{
+ Q_ASSERT(!isRemoved());
+ QVector<Stmt *> newStmts = stmts;
+ newStmts += _statements;
+ _statements = newStmts;
+}
+
void BasicBlock::insertStatementBefore(Stmt *before, Stmt *newStmt)
{
int idx = _statements.indexOf(before);
@@ -1156,6 +864,11 @@ void CloneExpr::visitTemp(Temp *e)
cloned = cloneTemp(e, block->function);
}
+void CloneExpr::visitArgLocal(ArgLocal *e)
+{
+ cloned = cloneArgLocal(e, block->function);
+}
+
void CloneExpr::visitClosure(Closure *e)
{
cloned = block->CLOSURE(e->value);
@@ -1197,6 +910,401 @@ void CloneExpr::visitMember(Member *e)
cloned = block->MEMBER(clonedBase, e->name, e->property, e->kind, e->attachedPropertiesIdOrEnumValue);
}
+IRPrinter::IRPrinter(QTextStream *out)
+ : out(out)
+ , printElse(true)
+{
+}
+
+IRPrinter::~IRPrinter()
+{
+}
+
+void IRPrinter::print(Stmt *s)
+{
+ s->accept(this);
+}
+
+void IRPrinter::print(const Expr &e)
+{
+ const_cast<Expr *>(&e)->accept(this);
+}
+
+void IRPrinter::print(Expr *e)
+{
+ e->accept(this);
+}
+
+void IRPrinter::print(Function *f)
+{
+ QString n = f->name ? *f->name : QString();
+ if (n.isEmpty())
+ n.sprintf("%p", f);
+ *out << "function " << n << '(';
+
+ for (int i = 0; i < f->formals.size(); ++i) {
+ if (i != 0)
+ *out << ", ";
+ *out << *f->formals.at(i);
+ }
+ *out << ')' << endl
+ << '{' << endl;
+
+ foreach (const QString *local, f->locals)
+ *out << " var " << *local << ';' << endl;
+
+ foreach (BasicBlock *bb, f->basicBlocks())
+ if (!bb->isRemoved())
+ print(bb);
+ *out << '}' << endl;
+}
+
+void IRPrinter::print(BasicBlock *bb)
+{
+ bool prevPrintElse = false;
+ std::swap(printElse, prevPrintElse);
+ printBlockStart(bb);
+
+ foreach (Stmt *s, bb->statements()) {
+ QByteArray str;
+ QBuffer buf(&str);
+ buf.open(QIODevice::WriteOnly);
+ QTextStream os(&buf);
+ QTextStream *prevOut = &os;
+ std::swap(out, prevOut);
+ addStmtNr(s);
+ s->accept(this);
+ if (s->location.isValid()) {
+ out->flush();
+ for (int i = 58 - str.length(); i > 0; --i)
+ *out << ' ';
+ *out << " // line: " << s->location.startLine << " column: " << s->location.startColumn;
+ }
+
+ out->flush();
+ std::swap(out, prevOut);
+
+ *out << " " << str;
+ *out << endl;
+
+ if (s->asCJump()) {
+ *out << " else goto L" << s->asCJump()->iffalse->index() << ";" << endl;
+ }
+ }
+
+ std::swap(printElse, prevPrintElse);
+}
+
+void IRPrinter::visitExp(Exp *s)
+{
+ *out << "(void) ";
+ s->expr->accept(this);
+ *out << ';';
+}
+
+void IRPrinter::visitMove(Move *s)
+{
+ s->target->accept(this);
+ *out << ' ';
+ if (s->swap)
+ *out << "<=> ";
+ else
+ *out << "= ";
+ s->source->accept(this);
+ *out << ';';
+}
+
+void IRPrinter::visitJump(Jump *s)
+{
+ *out << "goto L" << s->target->index() << ';';
+}
+
+void IRPrinter::visitCJump(CJump *s)
+{
+ *out << "if (";
+ s->cond->accept(this);
+ *out << ") goto L" << s->iftrue->index() << ';';
+ if (printElse)
+ *out << " else goto L" << s->iffalse->index() << ';';
+}
+
+void IRPrinter::visitRet(Ret *s)
+{
+ *out << "return";
+ if (s->expr) {
+ *out << ' ';
+ s->expr->accept(this);
+ }
+ *out << ';';
+}
+
+void IRPrinter::visitPhi(Phi *s)
+{
+ s->targetTemp->accept(this);
+ *out << " = phi(";
+ for (int i = 0, ei = s->d->incoming.size(); i < ei; ++i) {
+ if (i > 0)
+ *out << ", ";
+ if (s->d->incoming[i])
+ s->d->incoming[i]->accept(this);
+ }
+ *out << ");";
+}
+
+void IRPrinter::visitConst(Const *e)
+{
+ if (e->type != UndefinedType && e->type != NullType)
+ *out << dumpStart(e);
+ switch (e->type) {
+ case QV4::IR::UndefinedType:
+ *out << "undefined";
+ break;
+ case QV4::IR::NullType:
+ *out << "null";
+ break;
+ case QV4::IR::BoolType:
+ *out << (e->value ? "true" : "false");
+ break;
+ case QV4::IR::MissingType:
+ *out << "missing";
+ break;
+ default:
+ if (int(e->value) == 0 && int(e->value) == e->value) {
+ if (isNegative(e->value))
+ *out << "-0";
+ else
+ *out << "0";
+ } else {
+ *out << QString::number(e->value, 'g', 16);
+ }
+ break;
+ }
+ if (e->type != UndefinedType && e->type != NullType)
+ *out << dumpEnd(e);
+}
+
+void IRPrinter::visitString(String *e)
+{
+ *out << '"' << escape(*e->value) << '"';
+}
+
+void IRPrinter::visitRegExp(RegExp *e)
+{
+ char f[3];
+ int i = 0;
+ if (e->flags & RegExp::RegExp_Global)
+ f[i++] = 'g';
+ if (e->flags & RegExp::RegExp_IgnoreCase)
+ f[i++] = 'i';
+ if (e->flags & RegExp::RegExp_Multiline)
+ f[i++] = 'm';
+ f[i] = 0;
+
+ *out << '/' << *e->value << '/' << f;
+}
+
+void IRPrinter::visitName(Name *e)
+{
+ if (e->id)
+ *out << *e->id;
+ else
+ *out << builtin_to_string(e->builtin);
+}
+
+void IRPrinter::visitTemp(Temp *e)
+{
+ *out << dumpStart(e);
+ switch (e->kind) {
+ case Temp::VirtualRegister: *out << '%' << e->index; break;
+ case Temp::PhysicalRegister: *out << (e->type == DoubleType ? "fp" : "r")
+ << e->index; break;
+ case Temp::StackSlot: *out << '&' << e->index; break;
+ default: *out << "INVALID";
+ }
+ *out << dumpEnd(e);
+}
+
+void IRPrinter::visitArgLocal(ArgLocal *e)
+{
+ *out << dumpStart(e);
+ switch (e->kind) {
+ case ArgLocal::Formal: *out << '#' << e->index; break;
+ case ArgLocal::ScopedFormal: *out << '#' << e->index
+ << '@' << e->scope; break;
+ case ArgLocal::Local: *out << '$' << e->index; break;
+ case ArgLocal::ScopedLocal: *out << '$' << e->index
+ << '@' << e->scope; break;
+ default: *out << "INVALID";
+ }
+ *out << dumpEnd(e);
+}
+
+void IRPrinter::visitClosure(Closure *e)
+{
+ QString name = e->functionName ? *e->functionName : QString();
+ if (name.isEmpty())
+ name.sprintf("%x", e->value);
+ *out << "closure(" << name << ')';
+}
+
+void IRPrinter::visitConvert(Convert *e)
+{
+ *out << dumpStart(e);
+ *out << "convert(";
+ e->expr->accept(this);
+ *out << ')' << dumpEnd(e);
+}
+
+void IRPrinter::visitUnop(Unop *e)
+{
+ *out << dumpStart(e) << opname(e->op);
+ e->expr->accept(this);
+ *out << dumpEnd(e);
+}
+
+void IRPrinter::visitBinop(Binop *e)
+{
+ *out << dumpStart(e);
+ e->left->accept(this);
+ *out << ' ' << opname(e->op) << ' ';
+ e->right->accept(this);
+ *out << dumpEnd(e);
+}
+
+void IRPrinter::visitCall(Call *e)
+{
+ e->base->accept(this);
+ *out << '(';
+ for (ExprList *it = e->args; it; it = it->next) {
+ if (it != e->args)
+ *out << ", ";
+ it->expr->accept(this);
+ }
+ *out << ')';
+}
+
+void IRPrinter::visitNew(New *e)
+{
+ *out << "new ";
+ e->base->accept(this);
+ *out << '(';
+ for (ExprList *it = e->args; it; it = it->next) {
+ if (it != e->args)
+ *out << ", ";
+ it->expr->accept(this);
+ }
+ *out << ')';
+}
+
+void IRPrinter::visitSubscript(Subscript *e)
+{
+ e->base->accept(this);
+ *out << '[';
+ e->index->accept(this);
+ *out << ']';
+}
+
+void IRPrinter::visitMember(Member *e)
+{
+ if (e->kind != Member::MemberOfEnum
+ && e->attachedPropertiesIdOrEnumValue != 0 && !e->base->asTemp())
+ *out << "[[attached property from " << e->attachedPropertiesIdOrEnumValue << "]]";
+ else
+ e->base->accept(this);
+ *out << '.' << *e->name;
+#ifndef V4_BOOTSTRAP
+ if (e->property)
+ *out << " (meta-property " << e->property->coreIndex
+ << " <" << QMetaType::typeName(e->property->propType)
+ << ">)";
+#endif
+}
+
+QString IRPrinter::escape(const QString &s)
+{
+ QString r;
+ for (int i = 0; i < s.length(); ++i) {
+ const QChar ch = s.at(i);
+ if (ch == QLatin1Char('\n'))
+ r += QStringLiteral("\\n");
+ else if (ch == QLatin1Char('\r'))
+ r += QStringLiteral("\\r");
+ else if (ch == QLatin1Char('\\'))
+ r += QStringLiteral("\\\\");
+ else if (ch == QLatin1Char('"'))
+ r += QStringLiteral("\\\"");
+ else if (ch == QLatin1Char('\''))
+ r += QStringLiteral("\\'");
+ else
+ r += ch;
+ }
+ return r;
+}
+
+void IRPrinter::addStmtNr(Stmt *s)
+{
+ if (s->id() >= 0)
+ *out << s->id() << ": ";
+}
+
+QString IRPrinter::dumpStart(const Expr *e)
+{
+ if (e->type == UnknownType)
+ return QString();
+
+ QString result = typeName(e->type);
+#ifndef V4_BOOTSTRAP
+ const Temp *temp = const_cast<Expr*>(e)->asTemp();
+ if (e->type == QObjectType && temp && temp->memberResolver.isQObjectResolver) {
+ result += QLatin1Char('<');
+ result += QString::fromUtf8(static_cast<QQmlPropertyCache*>(temp->memberResolver.data)->className());
+ result += QLatin1Char('>');
+ }
+#endif
+ result += QLatin1Char('{');
+ return result;
+}
+
+const char *IRPrinter::dumpEnd(const Expr *e)
+{
+ if (e->type == UnknownType)
+ return "";
+ else
+ return "}";
+}
+
+void IRPrinter::printBlockStart(BasicBlock *bb)
+{
+ if (bb->isRemoved()) {
+ *out << "(block has been removed)";
+ return;
+ }
+
+ QByteArray str;
+ str.append('L');
+ str.append(QByteArray::number(bb->index()));
+ str.append(':');
+ if (bb->catchBlock) {
+ str.append(" (exception handler L");
+ str.append(QByteArray::number(bb->catchBlock->index()));
+ str.append(')');
+ }
+ for (int i = 66 - str.length(); i; --i)
+ str.append(' ');
+ *out << str;
+
+ *out << "// predecessor blocks:";
+ foreach (BasicBlock *in, bb->in)
+ *out << " L" << in->index();
+ if (bb->in.isEmpty())
+ *out << " (none)";
+ if (BasicBlock *container = bb->containingGroup())
+ *out << "; container block: L" << container->index();
+ if (bb->isGroupStart())
+ *out << "; group start";
+ *out << endl;
+}
+
} // end of namespace IR
} // end of namespace QV4
diff --git a/src/qml/compiler/qv4jsir_p.h b/src/qml/compiler/qv4jsir_p.h
index 9eff90dd30..606313d0c1 100644
--- a/src/qml/compiler/qv4jsir_p.h
+++ b/src/qml/compiler/qv4jsir_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtQml module of the Qt Toolkit.
@@ -108,6 +108,7 @@ struct String;
struct RegExp;
struct Name;
struct Temp;
+struct ArgLocal;
struct Closure;
struct Convert;
struct Unop;
@@ -210,6 +211,7 @@ struct ExprVisitor {
virtual void visitRegExp(RegExp *) = 0;
virtual void visitName(Name *) = 0;
virtual void visitTemp(Temp *) = 0;
+ virtual void visitArgLocal(ArgLocal *) = 0;
virtual void visitClosure(Closure *) = 0;
virtual void visitConvert(Convert *) = 0;
virtual void visitUnop(Unop *) = 0;
@@ -260,6 +262,7 @@ struct Q_AUTOTEST_EXPORT Expr {
virtual RegExp *asRegExp() { return 0; }
virtual Name *asName() { return 0; }
virtual Temp *asTemp() { return 0; }
+ virtual ArgLocal *asArgLocal() { return 0; }
virtual Closure *asClosure() { return 0; }
virtual Convert *asConvert() { return 0; }
virtual Unop *asUnop() { return 0; }
@@ -268,7 +271,6 @@ struct Q_AUTOTEST_EXPORT Expr {
virtual New *asNew() { return 0; }
virtual Subscript *asSubscript() { return 0; }
virtual Member *asMember() { return 0; }
- virtual void dump(QTextStream &out) const = 0;
};
struct ExprList {
@@ -295,8 +297,6 @@ struct Const: Expr {
virtual void accept(ExprVisitor *v) { v->visitConst(this); }
virtual Const *asConst() { return this; }
-
- virtual void dump(QTextStream &out) const;
};
struct String: Expr {
@@ -309,9 +309,6 @@ struct String: Expr {
virtual void accept(ExprVisitor *v) { v->visitString(this); }
virtual String *asString() { return this; }
-
- virtual void dump(QTextStream &out) const;
- static QString escape(const QString &s);
};
struct RegExp: Expr {
@@ -333,8 +330,6 @@ struct RegExp: Expr {
virtual void accept(ExprVisitor *v) { v->visitRegExp(this); }
virtual RegExp *asRegExp() { return this; }
-
- virtual void dump(QTextStream &out) const;
};
struct Name: Expr {
@@ -376,60 +371,85 @@ struct Name: Expr {
virtual void accept(ExprVisitor *v) { v->visitName(this); }
virtual bool isLValue() { return true; }
virtual Name *asName() { return this; }
-
- virtual void dump(QTextStream &out) const;
};
struct Q_AUTOTEST_EXPORT Temp: Expr {
enum Kind {
- Formal = 0,
- ScopedFormal,
- Local,
- ScopedLocal,
+ Invalid = 0,
VirtualRegister,
PhysicalRegister,
StackSlot
};
- unsigned index;
- unsigned scope : 27; // how many scopes outside the current one?
- unsigned kind : 3;
- unsigned isArgumentsOrEval : 1;
- unsigned isReadOnly : 1;
+ unsigned index : 28;
+ unsigned kind : 3;
+ unsigned isReadOnly : 1;
// Used when temp is used as base in member expression
MemberExpressionResolver memberResolver;
- void init(unsigned kind, unsigned index, unsigned scope)
- {
- Q_ASSERT((kind == ScopedLocal && scope != 0) ||
- (kind == ScopedFormal && scope != 0) ||
- (scope == 0));
+ Temp()
+ : index((1 << 28) - 1)
+ , kind(Invalid)
+ , isReadOnly(0)
+ {}
+ void init(unsigned kind, unsigned index)
+ {
this->kind = kind;
this->index = index;
- this->scope = scope;
- this->isArgumentsOrEval = false;
this->isReadOnly = false;
}
+ bool isInvalid() const { return kind == Invalid; }
virtual void accept(ExprVisitor *v) { v->visitTemp(this); }
virtual bool isLValue() { return !isReadOnly; }
virtual Temp *asTemp() { return this; }
-
- virtual void dump(QTextStream &out) const;
};
inline bool operator==(const Temp &t1, const Temp &t2) Q_DECL_NOTHROW
-{ return t1.index == t2.index && t1.scope == t2.scope && t1.kind == t2.kind && t1.type == t2.type; }
+{ return t1.index == t2.index && t1.kind == t2.kind && t1.type == t2.type; }
inline bool operator!=(const Temp &t1, const Temp &t2) Q_DECL_NOTHROW
{ return !(t1 == t2); }
inline uint qHash(const Temp &t, uint seed = 0) Q_DECL_NOTHROW
-{ return t.index ^ (t.kind | (t.scope << 3)) ^ seed; }
+{ return t.index ^ t.kind ^ seed; }
bool operator<(const Temp &t1, const Temp &t2) Q_DECL_NOTHROW;
+struct Q_AUTOTEST_EXPORT ArgLocal: Expr {
+ enum Kind {
+ Formal = 0,
+ ScopedFormal,
+ Local,
+ ScopedLocal
+ };
+
+ unsigned index;
+ unsigned scope : 29; // how many scopes outside the current one?
+ unsigned kind : 2;
+ unsigned isArgumentsOrEval : 1;
+
+ void init(unsigned kind, unsigned index, unsigned scope)
+ {
+ Q_ASSERT((kind == ScopedLocal && scope != 0) ||
+ (kind == ScopedFormal && scope != 0) ||
+ (scope == 0));
+
+ this->kind = kind;
+ this->index = index;
+ this->scope = scope;
+ this->isArgumentsOrEval = false;
+ }
+
+ virtual void accept(ExprVisitor *v) { v->visitArgLocal(this); }
+ virtual bool isLValue() { return true; }
+ virtual ArgLocal *asArgLocal() { return this; }
+
+ bool operator==(const ArgLocal &other) const
+ { return index == other.index && scope == other.scope && kind == other.kind; }
+};
+
struct Closure: Expr {
int value; // index in _module->functions
const QString *functionName;
@@ -442,8 +462,6 @@ struct Closure: Expr {
virtual void accept(ExprVisitor *v) { v->visitClosure(this); }
virtual Closure *asClosure() { return this; }
-
- virtual void dump(QTextStream &out) const;
};
struct Convert: Expr {
@@ -457,8 +475,6 @@ struct Convert: Expr {
virtual void accept(ExprVisitor *v) { v->visitConvert(this); }
virtual Convert *asConvert() { return this; }
-
- virtual void dump(QTextStream &out) const;
};
struct Unop: Expr {
@@ -473,8 +489,6 @@ struct Unop: Expr {
virtual void accept(ExprVisitor *v) { v->visitUnop(this); }
virtual Unop *asUnop() { return this; }
-
- virtual void dump(QTextStream &out) const;
};
struct Binop: Expr {
@@ -491,8 +505,6 @@ struct Binop: Expr {
virtual void accept(ExprVisitor *v) { v->visitBinop(this); }
virtual Binop *asBinop() { return this; }
-
- virtual void dump(QTextStream &out) const;
};
struct Call: Expr {
@@ -513,8 +525,6 @@ struct Call: Expr {
virtual void accept(ExprVisitor *v) { v->visitCall(this); }
virtual Call *asCall() { return this; }
-
- virtual void dump(QTextStream &out) const;
};
struct New: Expr {
@@ -535,8 +545,6 @@ struct New: Expr {
virtual void accept(ExprVisitor *v) { v->visitNew(this); }
virtual New *asNew() { return this; }
-
- virtual void dump(QTextStream &out) const;
};
struct Subscript: Expr {
@@ -552,8 +560,6 @@ struct Subscript: Expr {
virtual void accept(ExprVisitor *v) { v->visitSubscript(this); }
virtual bool isLValue() { return true; }
virtual Subscript *asSubscript() { return this; }
-
- virtual void dump(QTextStream &out) const;
};
struct Member: Expr {
@@ -605,25 +611,20 @@ struct Member: Expr {
virtual void accept(ExprVisitor *v) { v->visitMember(this); }
virtual bool isLValue() { return true; }
virtual Member *asMember() { return this; }
-
- virtual void dump(QTextStream &out) const;
};
struct Stmt {
- enum Mode {
- HIR,
- MIR
- };
-
struct Data {
QVector<Expr *> incoming; // used by Phi nodes
};
+ enum { InvalidId = -1 };
+
Data *d;
- int id;
QQmlJS::AST::SourceLocation location;
- Stmt(): d(0), id(-1) {}
+ explicit Stmt(int id): d(0), _id(id) {}
+
virtual ~Stmt()
{
#ifdef Q_CC_MSVC
@@ -641,7 +642,8 @@ struct Stmt {
virtual CJump *asCJump() { return 0; }
virtual Ret *asRet() { return 0; }
virtual Phi *asPhi() { return 0; }
- virtual void dump(QTextStream &out, Mode mode = HIR) = 0;
+
+ int id() const { return _id; }
private: // For memory management in BasicBlock
friend struct BasicBlock;
@@ -649,11 +651,17 @@ private: // For memory management in BasicBlock
delete d;
d = 0;
}
+
+private:
+ friend struct Function;
+ int _id;
};
struct Exp: Stmt {
Expr *expr;
+ Exp(int id): Stmt(id) {}
+
void init(Expr *expr)
{
this->expr = expr;
@@ -662,7 +670,6 @@ struct Exp: Stmt {
virtual void accept(StmtVisitor *v) { v->visitExp(this); }
virtual Exp *asExp() { return this; }
- virtual void dump(QTextStream &out, Mode);
};
struct Move: Stmt {
@@ -670,6 +677,8 @@ struct Move: Stmt {
Expr *source;
bool swap;
+ Move(int id): Stmt(id) {}
+
void init(Expr *target, Expr *source)
{
this->target = target;
@@ -680,12 +689,13 @@ struct Move: Stmt {
virtual void accept(StmtVisitor *v) { v->visitMove(this); }
virtual Move *asMove() { return this; }
- virtual void dump(QTextStream &out, Mode mode = HIR);
};
struct Jump: Stmt {
BasicBlock *target;
+ Jump(int id): Stmt(id) {}
+
void init(BasicBlock *target)
{
this->target = target;
@@ -695,8 +705,6 @@ struct Jump: Stmt {
virtual void accept(StmtVisitor *v) { v->visitJump(this); }
virtual Jump *asJump() { return this; }
-
- virtual void dump(QTextStream &out, Mode mode);
};
struct CJump: Stmt {
@@ -704,6 +712,8 @@ struct CJump: Stmt {
BasicBlock *iftrue;
BasicBlock *iffalse;
+ CJump(int id): Stmt(id) {}
+
void init(Expr *cond, BasicBlock *iftrue, BasicBlock *iffalse)
{
this->cond = cond;
@@ -715,13 +725,13 @@ struct CJump: Stmt {
virtual void accept(StmtVisitor *v) { v->visitCJump(this); }
virtual CJump *asCJump() { return this; }
-
- virtual void dump(QTextStream &out, Mode mode);
};
struct Ret: Stmt {
Expr *expr;
+ Ret(int id): Stmt(id) {}
+
void init(Expr *expr)
{
this->expr = expr;
@@ -731,17 +741,15 @@ struct Ret: Stmt {
virtual void accept(StmtVisitor *v) { v->visitRet(this); }
virtual Ret *asRet() { return this; }
-
- virtual void dump(QTextStream &out, Mode);
};
struct Phi: Stmt {
Temp *targetTemp;
+ Phi(int id): Stmt(id) {}
+
virtual void accept(StmtVisitor *v) { v->visitPhi(this); }
virtual Phi *asPhi() { return this; }
-
- virtual void dump(QTextStream &out, Mode mode);
};
struct Q_QML_PRIVATE_EXPORT Module {
@@ -775,10 +783,10 @@ public:
QVector<BasicBlock *> out;
QQmlJS::AST::SourceLocation nextLocation;
- BasicBlock(Function *function, BasicBlock *containingLoop, BasicBlock *catcher)
+ BasicBlock(Function *function, BasicBlock *catcher)
: function(function)
, catchBlock(catcher)
- , _containingGroup(containingLoop)
+ , _containingGroup(0)
, _index(-1)
, _isExceptionHandler(false)
, _groupStart(false)
@@ -812,6 +820,7 @@ public:
void appendStatement(Stmt *statement);
void prependStatement(Stmt *stmt);
+ void prependStatements(const QVector<Stmt *> &stmts);
void insertStatementBefore(Stmt *before, Stmt *newStmt);
void insertStatementBefore(int index, Stmt *newStmt);
void insertStatementBeforeTerminator(Stmt *stmt);
@@ -841,8 +850,8 @@ public:
unsigned newTemp();
Temp *TEMP(unsigned kind);
- Temp *ARG(unsigned index, unsigned scope);
- Temp *LOCAL(unsigned index, unsigned scope);
+ ArgLocal *ARG(unsigned index, unsigned scope);
+ ArgLocal *LOCAL(unsigned index, unsigned scope);
Expr *CONST(Type type, double value);
Expr *STRING(const QString *value);
@@ -871,8 +880,6 @@ public:
Stmt *CJUMP(Expr *cond, BasicBlock *iftrue, BasicBlock *iffalse);
Stmt *RET(Temp *expr);
- void dump(QTextStream &out, Stmt::Mode mode = Stmt::HIR);
-
BasicBlock *containingGroup() const
{
Q_ASSERT(!isRemoved());
@@ -994,7 +1001,10 @@ struct Function {
PropertyDependencyMap contextObjectPropertyDependencies;
PropertyDependencyMap scopeObjectPropertyDependencies;
- template <typename _Tp> _Tp *New() { return new (pool->allocate(sizeof(_Tp))) _Tp(); }
+ template <typename T> T *New() { return new (pool->allocate(sizeof(T))) T(); }
+ template <typename T> T *NewStmt() {
+ return new (pool->allocate(sizeof(T))) T(getNewStatementId());
+ }
Function(Module *module, Function *outer, const QString &name);
~Function();
@@ -1004,7 +1014,7 @@ struct Function {
DontInsertBlock
};
- BasicBlock *newBasicBlock(BasicBlock *containingLoop, BasicBlock *catchBlock, BasicBlockInsertMode mode = InsertBlock);
+ BasicBlock *newBasicBlock(BasicBlock *catchBlock, BasicBlockInsertMode mode = InsertBlock);
const QString *newString(const QString &text);
void RECEIVE(const QString &name) { formals.append(newString(name)); }
@@ -1024,8 +1034,6 @@ struct Function {
int liveBasicBlocksCount() const;
- void dump(QTextStream &out, Stmt::Mode mode = Stmt::HIR);
-
void removeSharedExpressions();
int indexOfArgument(const QStringRef &string) const;
@@ -1036,9 +1044,13 @@ struct Function {
void setScheduledBlocks(const QVector<BasicBlock *> &scheduled);
void renumberBasicBlocks();
+ unsigned getNewStatementId() { return _statementCount++; }
+ unsigned statementCount() const { return _statementCount; }
+
private:
QVector<BasicBlock *> _basicBlocks;
QVector<BasicBlock *> *_allBasicBlocks;
+ unsigned _statementCount;
};
class CloneExpr: protected IR::ExprVisitor
@@ -1088,12 +1100,20 @@ public:
static Temp *cloneTemp(Temp *t, Function *f)
{
Temp *newTemp = f->New<Temp>();
- newTemp->init(t->kind, t->index, t->scope);
+ newTemp->init(t->kind, t->index);
newTemp->type = t->type;
newTemp->memberResolver = t->memberResolver;
return newTemp;
}
+ static ArgLocal *cloneArgLocal(ArgLocal *argLocal, Function *f)
+ {
+ ArgLocal *newArgLocal = f->New<ArgLocal>();
+ newArgLocal->init(argLocal->kind, argLocal->index, argLocal->scope);
+ newArgLocal->type = argLocal->type;
+ return newArgLocal;
+ }
+
protected:
IR::ExprList *clone(IR::ExprList *list);
@@ -1102,6 +1122,7 @@ protected:
virtual void visitRegExp(RegExp *);
virtual void visitName(Name *);
virtual void visitTemp(Temp *);
+ virtual void visitArgLocal(ArgLocal *);
virtual void visitClosure(Closure *);
virtual void visitConvert(Convert *);
virtual void visitUnop(Unop *);
@@ -1116,6 +1137,54 @@ private:
IR::Expr *cloned;
};
+class IRPrinter: public StmtVisitor, public ExprVisitor
+{
+public:
+ IRPrinter(QTextStream *out);
+ virtual ~IRPrinter();
+
+ void print(Stmt *s);
+ void print(Expr *e);
+ void print(const Expr &e);
+
+ virtual void print(Function *f);
+ virtual void print(BasicBlock *bb);
+
+ virtual void visitExp(Exp *s);
+ virtual void visitMove(Move *s);
+ virtual void visitJump(Jump *s);
+ virtual void visitCJump(CJump *s);
+ virtual void visitRet(Ret *s);
+ virtual void visitPhi(Phi *s);
+
+ virtual void visitConst(Const *e);
+ virtual void visitString(String *e);
+ virtual void visitRegExp(RegExp *e);
+ virtual void visitName(Name *e);
+ virtual void visitTemp(Temp *e);
+ virtual void visitArgLocal(ArgLocal *e);
+ virtual void visitClosure(Closure *e);
+ virtual void visitConvert(Convert *e);
+ virtual void visitUnop(Unop *e);
+ virtual void visitBinop(Binop *e);
+ virtual void visitCall(Call *e);
+ virtual void visitNew(New *e);
+ virtual void visitSubscript(Subscript *e);
+ virtual void visitMember(Member *e);
+
+ static QString escape(const QString &s);
+
+protected:
+ virtual void addStmtNr(Stmt *s);
+ QString dumpStart(const Expr *e);
+ const char *dumpEnd(const Expr *e);
+ void printBlockStart(BasicBlock *bb);
+
+protected:
+ QTextStream *out;
+ bool printElse;
+};
+
} // end of namespace IR
} // end of namespace QV4
diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp
index d7dbfac50b..8488d6eb2b 100644
--- a/src/qml/compiler/qv4ssa.cpp
+++ b/src/qml/compiler/qv4ssa.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtQml module of the Qt Toolkit.
@@ -39,9 +39,10 @@
**
****************************************************************************/
-#ifndef QT_NO_DEBUG
-# define _LIBCPP_DEBUG2 0
-#endif // QT_NO_DEBUG
+// When building with debug code, the macro below will enable debug helpers when using libc++.
+// For example, the std::vector<T>::operator[] will use _LIBCPP_ASSERT to check if the index is
+// within the array bounds. Note that this only works reliably with OSX 10.9 or later.
+//#define _LIBCPP_DEBUG2 2
#include "qv4ssa_p.h"
#include "qv4isel_util_p.h"
@@ -50,7 +51,6 @@
#include <QtCore/QCoreApplication>
#include <QtCore/QStringList>
#include <QtCore/QSet>
-#include <QtCore/QBuffer>
#include <QtCore/QLinkedList>
#include <QtCore/QStack>
#include <qv4runtime_p.h>
@@ -69,102 +69,20 @@ using namespace IR;
namespace {
+#ifdef QT_NO_DEBUG
+enum { DoVerification = 0 };
+#else
+enum { DoVerification = 1 };
+#endif
+
Q_GLOBAL_STATIC_WITH_ARGS(QTextStream, qout, (stderr, QIODevice::WriteOnly));
#define qout *qout()
void showMeTheCode(IR::Function *function)
{
static bool showCode = !qgetenv("QV4_SHOW_IR").isNull();
- if (showCode) {
- QVector<Stmt *> code;
- QHash<Stmt *, BasicBlock *> leader;
-
- foreach (BasicBlock *block, function->basicBlocks()) {
- if (block->isRemoved() || block->isEmpty())
- continue;
- leader.insert(block->statements().first(), block);
- foreach (Stmt *s, block->statements()) {
- code.append(s);
- }
- }
-
- QString name;
- if (function->name && !function->name->isEmpty())
- name = *function->name;
- else
- name.sprintf("%p", function);
-
- qout << "function " << name << "(";
- for (int i = 0; i < function->formals.size(); ++i) {
- if (i != 0)
- qout << ", ";
- qout << *function->formals.at(i);
- }
- qout << ")" << endl
- << "{" << endl;
-
- foreach (const QString *local, function->locals) {
- qout << " var " << *local << ';' << endl;
- }
-
- for (int i = 0; i < code.size(); ++i) {
- Stmt *s = code.at(i);
- Q_ASSERT(s);
-
- if (BasicBlock *bb = leader.value(s)) {
- qout << endl;
- QByteArray str;
- str.append('L');
- str.append(QByteArray::number(bb->index()));
- str.append(':');
- if (bb->catchBlock) {
- str.append(" (exception handler L");
- str.append(QByteArray::number(bb->catchBlock->index()));
- str.append(')');
- }
- for (int i = 66 - str.length(); i; --i)
- str.append(' ');
- qout << str;
- qout << "// predecessor blocks:";
- foreach (BasicBlock *in, bb->in)
- qout << " L" << in->index();
- if (bb->in.isEmpty())
- qout << "(none)";
- if (BasicBlock *container = bb->containingGroup())
- qout << "; container block: L" << container->index();
- if (bb->isGroupStart())
- qout << "; group start";
- qout << endl;
- }
- Stmt *n = (i + 1) < code.size() ? code.at(i + 1) : 0;
-
- QByteArray str;
- QBuffer buf(&str);
- buf.open(QIODevice::WriteOnly);
- QTextStream out(&buf);
- if (s->id > 0)
- out << s->id << ": ";
- s->dump(out, Stmt::MIR);
- if (s->location.isValid()) {
- out.flush();
- for (int i = 58 - str.length(); i > 0; --i)
- out << ' ';
- out << " // line: " << s->location.startLine << " column: " << s->location.startColumn;
- }
-
- out.flush();
-
- qout << " " << str;
- qout << endl;
-
- if (n && s->asCJump()) {
- qout << " else goto L" << s->asCJump()->iffalse->index() << ";" << endl;
- }
- }
-
- qout << "}" << endl
- << endl;
- }
+ if (showCode)
+ IRPrinter(&qout).print(function);
}
class ProcessedBlocks
@@ -190,29 +108,6 @@ public:
}
};
-inline bool unescapableTemp(Temp *t, IR::Function *f)
-{
- switch (t->kind) {
- case Temp::Formal:
- case Temp::ScopedFormal:
- case Temp::ScopedLocal:
- return false;
- case Temp::Local:
- return !f->variablesCanEscape();
- default:
- return true;
- }
-}
-
-inline Temp *unescapableTemp(Expr *e, IR::Function *f)
-{
- Temp *t = e->asTemp();
- if (!t)
- return 0;
-
- return unescapableTemp(t, f) ? t : 0;
-}
-
class BasicBlockSet
{
typedef std::vector<int> Numbers;
@@ -237,7 +132,7 @@ public:
const_iterator(const BasicBlockSet &set, bool end)
: set(set)
{
- if (end) {
+ if (end || !set.function) {
if (set.blockNumbers)
numberIt = set.blockNumbers->end();
else
@@ -274,10 +169,11 @@ public:
public:
BasicBlock *operator*() const
{
+
if (set.blockNumbers) {
return set.function->basicBlock(*numberIt);
} else {
- Q_ASSERT(flagIt <= INT_MAX);
+ Q_ASSERT(flagIt <= static_cast<size_t>(set.function->basicBlockCount()));
return set.function->basicBlock(static_cast<int>(flagIt));
}
}
@@ -332,6 +228,8 @@ public:
void insert(BasicBlock *bb)
{
+ Q_ASSERT(function);
+
if (blockFlags) {
(*blockFlags)[bb->index()] = true;
return;
@@ -358,31 +256,42 @@ public:
const_iterator begin() const { return const_iterator(*this, false); }
const_iterator end() const { return const_iterator(*this, true); }
- QList<BasicBlock *> values() const
+ void collectValues(std::vector<BasicBlock *> &bbs) const
{
- QList<BasicBlock *> result;
+ Q_ASSERT(function);
for (const_iterator it = begin(), eit = end(); it != eit; ++it)
- result.append(*it);
-
- return result;
+ bbs.push_back(*it);
}
};
-class DominatorTree {
+class DominatorTree
+{
+ enum {
+ DebugDominatorFrontiers = 0,
+ DebugImmediateDominators = 0
+ };
+
typedef int BasicBlockIndex;
enum { InvalidBasicBlockIndex = -1 };
+ struct Data
+ {
+ int N;
+ std::vector<int> dfnum; // BasicBlock index -> dfnum
+ std::vector<int> vertex;
+ std::vector<BasicBlockIndex> parent; // BasicBlock index -> parent BasicBlock index
+ std::vector<BasicBlockIndex> ancestor; // BasicBlock index -> ancestor BasicBlock index
+ std::vector<BasicBlockIndex> best; // BasicBlock index -> best BasicBlock index
+ std::vector<BasicBlockIndex> semi; // BasicBlock index -> semi dominator BasicBlock index
+ std::vector<BasicBlockIndex> samedom; // BasicBlock index -> same dominator BasicBlock index
+
+ Data(): N(0) {}
+ };
+
IR::Function *function;
- int N;
- std::vector<int> dfnum; // BasicBlock index -> dfnum
- std::vector<int> vertex;
- std::vector<BasicBlockIndex> parent; // BasicBlock index -> parent BasicBlock index
- std::vector<BasicBlockIndex> ancestor; // BasicBlock index -> ancestor BasicBlock index
- std::vector<BasicBlockIndex> best; // BasicBlock index -> best BasicBlock index
- std::vector<BasicBlockIndex> semi; // BasicBlock index -> semi dominator BasicBlock index
+ QScopedPointer<Data> d;
std::vector<BasicBlockIndex> idom; // BasicBlock index -> immediate dominator BasicBlock index
- std::vector<BasicBlockIndex> samedom; // BasicBlock index -> same dominator BasicBlock index
std::vector<BasicBlockSet> DF; // BasicBlock index -> dominator frontier
struct DFSTodo {
@@ -401,17 +310,17 @@ class DominatorTree {
void DFS(BasicBlockIndex node) {
std::vector<DFSTodo> worklist;
- worklist.reserve(vertex.capacity() / 2);
+ worklist.reserve(d->vertex.capacity() / 2);
DFSTodo todo(node, InvalidBasicBlockIndex);
while (true) {
BasicBlockIndex n = todo.node;
- if (dfnum[n] == 0) {
- dfnum[n] = N;
- vertex[N] = n;
- parent[n] = todo.parent;
- ++N;
+ if (d->dfnum[n] == 0) {
+ d->dfnum[n] = d->N;
+ d->vertex[d->N] = n;
+ d->parent[n] = todo.parent;
+ ++d->N;
const QVector<BasicBlock *> &out = function->basicBlock(n)->out;
for (int i = out.size() - 1; i > 0; --i)
worklist.push_back(DFSTodo(out[i]->index(), n));
@@ -438,20 +347,20 @@ class DominatorTree {
BasicBlockIndex ancestorWithLowestSemi(BasicBlockIndex v, std::vector<BasicBlockIndex> &worklist) {
worklist.clear();
- for (BasicBlockIndex it = v; it != InvalidBasicBlockIndex; it = ancestor[it])
+ for (BasicBlockIndex it = v; it != InvalidBasicBlockIndex; it = d->ancestor[it])
worklist.push_back(it);
if (worklist.size() < 2)
- return best[v];
+ return d->best[v];
BasicBlockIndex b = InvalidBasicBlockIndex;
BasicBlockIndex last = worklist.back();
Q_ASSERT(worklist.size() <= INT_MAX);
for (int it = static_cast<int>(worklist.size()) - 2; it >= 0; --it) {
BasicBlockIndex bbIt = worklist[it];
- ancestor[bbIt] = last;
- BasicBlockIndex &best_it = best[bbIt];
- if (b != InvalidBasicBlockIndex && dfnum[semi[b]] < dfnum[semi[best_it]])
+ d->ancestor[bbIt] = last;
+ BasicBlockIndex &best_it = d->best[bbIt];
+ if (b != InvalidBasicBlockIndex && d->dfnum[d->semi[b]] < d->dfnum[d->semi[best_it]])
best_it = b;
else
b = best_it;
@@ -460,57 +369,57 @@ class DominatorTree {
}
void link(BasicBlockIndex p, BasicBlockIndex n) {
- ancestor[n] = p;
- best[n] = n;
+ d->ancestor[n] = p;
+ d->best[n] = n;
}
void calculateIDoms() {
Q_ASSERT(function->basicBlock(0)->in.isEmpty());
const int bbCount = function->basicBlockCount();
- vertex = std::vector<int>(bbCount, InvalidBasicBlockIndex);
- parent = std::vector<int>(bbCount, InvalidBasicBlockIndex);
- dfnum = std::vector<int>(bbCount, 0);
- semi = std::vector<BasicBlockIndex>(bbCount, InvalidBasicBlockIndex);
- ancestor = std::vector<BasicBlockIndex>(bbCount, InvalidBasicBlockIndex);
+ d->vertex = std::vector<int>(bbCount, InvalidBasicBlockIndex);
+ d->parent = std::vector<int>(bbCount, InvalidBasicBlockIndex);
+ d->dfnum = std::vector<int>(bbCount, 0);
+ d->semi = std::vector<BasicBlockIndex>(bbCount, InvalidBasicBlockIndex);
+ d->ancestor = std::vector<BasicBlockIndex>(bbCount, InvalidBasicBlockIndex);
idom = std::vector<BasicBlockIndex>(bbCount, InvalidBasicBlockIndex);
- samedom = std::vector<BasicBlockIndex>(bbCount, InvalidBasicBlockIndex);
- best = std::vector<BasicBlockIndex>(bbCount, InvalidBasicBlockIndex);
+ d->samedom = std::vector<BasicBlockIndex>(bbCount, InvalidBasicBlockIndex);
+ d->best = std::vector<BasicBlockIndex>(bbCount, InvalidBasicBlockIndex);
QHash<BasicBlockIndex, std::vector<BasicBlockIndex> > bucket;
bucket.reserve(bbCount);
DFS(function->basicBlock(0)->index());
- Q_ASSERT(N == function->liveBasicBlocksCount());
+ Q_ASSERT(d->N == function->liveBasicBlocksCount());
std::vector<BasicBlockIndex> worklist;
- worklist.reserve(vertex.capacity() / 2);
+ worklist.reserve(d->vertex.capacity() / 2);
- for (int i = N - 1; i > 0; --i) {
- BasicBlockIndex n = vertex[i];
- BasicBlockIndex p = parent[n];
+ for (int i = d->N - 1; i > 0; --i) {
+ BasicBlockIndex n = d->vertex[i];
+ BasicBlockIndex p = d->parent[n];
BasicBlockIndex s = p;
foreach (BasicBlock *v, function->basicBlock(n)->in) {
BasicBlockIndex ss = InvalidBasicBlockIndex;
- if (dfnum[v->index()] <= dfnum[n])
+ if (d->dfnum[v->index()] <= d->dfnum[n])
ss = v->index();
else
- ss = semi[ancestorWithLowestSemi(v->index(), worklist)];
- if (dfnum[ss] < dfnum[s])
+ ss = d->semi[ancestorWithLowestSemi(v->index(), worklist)];
+ if (d->dfnum[ss] < d->dfnum[s])
s = ss;
}
- semi[n] = s;
+ d->semi[n] = s;
bucket[s].push_back(n);
link(p, n);
if (bucket.contains(p)) {
foreach (BasicBlockIndex v, bucket[p]) {
BasicBlockIndex y = ancestorWithLowestSemi(v, worklist);
- BasicBlockIndex semi_v = semi[v];
- if (semi[y] == semi_v)
+ BasicBlockIndex semi_v = d->semi[v];
+ if (d->semi[y] == semi_v)
idom[v] = semi_v;
else
- samedom[v] = y;
+ d->samedom[v] = y;
}
bucket.remove(p);
}
@@ -521,31 +430,19 @@ class DominatorTree {
qDebug("\tL%d: ancestor = %d, semi = %d, samedom = %d", i, ancestor[i], semi[i], samedom[i]);
#endif // SHOW_SSA
- for (int i = 1; i < N; ++i) {
- BasicBlockIndex n = vertex[i];
+ for (int i = 1; i < d->N; ++i) {
+ BasicBlockIndex n = d->vertex[i];
Q_ASSERT(n != InvalidBasicBlockIndex);
Q_ASSERT(!bucket.contains(n));
- Q_ASSERT(ancestor[n] != InvalidBasicBlockIndex
- && ((semi[n] != InvalidBasicBlockIndex
- && dfnum[ancestor[n]] <= dfnum[semi[n]]) || semi[n] == n));
- BasicBlockIndex sdn = samedom[n];
+ Q_ASSERT(d->ancestor[n] != InvalidBasicBlockIndex
+ && ((d->semi[n] != InvalidBasicBlockIndex
+ && d->dfnum[d->ancestor[n]] <= d->dfnum[d->semi[n]]) || d->semi[n] == n));
+ BasicBlockIndex sdn = d->samedom[n];
if (sdn != InvalidBasicBlockIndex)
idom[n] = idom[sdn];
}
-#if defined(SHOW_SSA)
- qout << "Immediate dominators:" << endl;
- foreach (BasicBlock *to, nodes) {
- qout << '\t';
- BasicBlockIndex from = idom.at(to->index);
- if (from != InvalidBasicBlockIndex)
- qout << from;
- else
- qout << "(none)";
- qout << " -> " << to->index << endl;
- }
- qout << "N = " << N << endl;
-#endif // SHOW_SSA
+ dumpImmediateDominators();
}
struct NodeProgress {
@@ -553,7 +450,18 @@ class DominatorTree {
std::vector<BasicBlockIndex> todo;
};
+public:
+ DominatorTree(IR::Function *function)
+ : function(function)
+ , d(new Data)
+ {
+ calculateIDoms();
+ d.reset();
+ }
+
void computeDF() {
+ DF.resize(function->basicBlockCount());
+
// compute children of each node in the dominator tree
std::vector<std::vector<BasicBlockIndex> > children; // BasicBlock index -> children
children.resize(function->basicBlockCount());
@@ -569,10 +477,10 @@ class DominatorTree {
}
// Fill the worklist and initialize the node status for each basic-block
- QHash<BasicBlockIndex, NodeProgress> nodeStatus;
- nodeStatus.reserve(function->basicBlockCount());
+ std::vector<NodeProgress> nodeStatus;
+ nodeStatus.resize(function->basicBlockCount());
std::vector<BasicBlockIndex> worklist;
- worklist.reserve(function->basicBlockCount() * 2);
+ worklist.reserve(function->basicBlockCount());
foreach (BasicBlock *bb, function->basicBlocks()) {
if (bb->isRemoved())
continue;
@@ -624,19 +532,23 @@ class DominatorTree {
}
}
-#if defined(SHOW_SSA)
- qout << "Dominator Frontiers:" << endl;
- foreach (BasicBlock *n, nodes) {
- qout << "\tDF[" << n->index << "]: {";
- QList<BasicBlock *> SList = DF[n->index].values();
- for (int i = 0; i < SList.size(); ++i) {
- if (i > 0)
- qout << ", ";
- qout << SList[i]->index;
+ if (DebugDominatorFrontiers) {
+ qout << "Dominator Frontiers:" << endl;
+ foreach (BasicBlock *n, function->basicBlocks()) {
+ if (n->isRemoved())
+ continue;
+
+ qout << "\tDF[" << n->index() << "]: {";
+ const BasicBlockSet &SList = DF[n->index()];
+ for (BasicBlockSet::const_iterator i = SList.begin(), ei = SList.end(); i != ei; ++i) {
+ if (i != SList.begin())
+ qout << ", ";
+ qout << (*i)->index();
+ }
+ qout << "}" << endl;
}
- qout << "}" << endl;
}
-#endif // SHOW_SSA
+
#if !defined(QT_NO_DEBUG) && defined(CAN_TAKE_LOSTS_OF_TIME)
foreach (BasicBlock *n, nodes) {
const BasicBlockSet &fBlocks = DF[n->index];
@@ -659,37 +571,40 @@ class DominatorTree {
#endif // !QT_NO_DEBUG
}
-public:
- DominatorTree(IR::Function *function)
- : function(function)
- , N(0)
- {
- DF.resize(function->basicBlockCount());
- calculateIDoms();
- computeDF();
- }
-
const BasicBlockSet &dominatorFrontier(BasicBlock *n) const {
return DF[n->index()];
}
BasicBlock *immediateDominator(BasicBlock *bb) const {
- return function->basicBlock(idom[bb->index()]);
+ const BasicBlockIndex idx = idom[bb->index()];
+ if (idx == -1)
+ return 0;
+ return function->basicBlock(idx);
}
void dumpImmediateDominators() const
{
- qDebug() << "Immediate dominators for" << idom.size() << "nodes:";
- for (size_t i = 0, ei = idom.size(); i != ei; ++i)
- if (idom[i] == InvalidBasicBlockIndex)
- qDebug("\tnone -> L%d", int(i));
- else
- qDebug("\tL%d -> L%d", idom[i], int(i));
+ if (DebugImmediateDominators) {
+ qout << "Immediate dominators:" << endl;
+ foreach (BasicBlock *to, function->basicBlocks()) {
+ if (to->isRemoved())
+ continue;
+
+ qout << '\t';
+ BasicBlockIndex from = idom.at(to->index());
+ if (from != InvalidBasicBlockIndex)
+ qout << from;
+ else
+ qout << "(none)";
+ qout << " -> " << to->index() << endl;
+ }
+ }
}
void updateImmediateDominator(BasicBlock *bb, BasicBlock *newDominator)
{
Q_ASSERT(bb->index() >= 0);
+ Q_ASSERT(!newDominator || newDominator->index() >= 0);
if (static_cast<std::vector<BasicBlockIndex>::size_type>(bb->index()) >= idom.size()) {
// This is a new block, probably introduced by edge splitting. So, we'll have to grow
@@ -697,13 +612,60 @@ public:
idom.resize(function->basicBlockCount(), InvalidBasicBlockIndex);
}
- idom[bb->index()] = newDominator->index();
+ idom[bb->index()] = newDominator ? newDominator->index() : 0;
}
bool dominates(BasicBlock *dominator, BasicBlock *dominated) const {
return dominates(dominator->index(), dominated->index());
}
+ // Calculate a depth-first iteration order on the nodes of the dominator tree.
+ //
+ // The order of the nodes in the vector is not the same as one where a recursive depth-first
+ // iteration is done on a tree. Rather, the nodes are (reverse) sorted on tree depth.
+ // So for the:
+ // 1 dominates 2
+ // 2 dominates 3
+ // 3 dominates 4
+ // 2 dominates 5
+ // the order will be:
+ // 4, 3, 5, 2, 1
+ // or:
+ // 4, 5, 3, 2, 1
+ // So the order of nodes on the same depth is undefined, but it will be after the nodes
+ // they dominate, and before the nodes that dominate them.
+ //
+ // The reason for this order is that a proper DFS pre-/post-order would require inverting
+ // the idom vector by either building a real tree datastructure or by searching the idoms
+ // for siblings and children. Both have a higher time complexity than sorting by depth.
+ QVector<BasicBlock *> calculateDFNodeIterOrder() const
+ {
+ std::vector<int> depths = calculateNodeDepths();
+ struct Cmp {
+ std::vector<int> *nodeDepths;
+ Cmp(std::vector<int> *nodeDepths)
+ : nodeDepths(nodeDepths)
+ { Q_ASSERT(nodeDepths); }
+ bool operator()(BasicBlock *one, BasicBlock *two) const
+ {
+ if (one->isRemoved())
+ return false;
+ if (two->isRemoved())
+ return true;
+ return nodeDepths->at(one->index()) > nodeDepths->at(two->index());
+ }
+ };
+ QVector<BasicBlock *> order = function->basicBlocks();
+ std::sort(order.begin(), order.end(), Cmp(&depths));
+ for (int i = 0; i < order.size(); ) {
+ if (order[i]->isRemoved())
+ order.remove(i);
+ else
+ ++i;
+ }
+ return order;
+ }
+
private:
bool dominates(BasicBlockIndex dominator, BasicBlockIndex dominated) const {
// dominator can be Invalid when the dominated block has no dominator (i.e. the start node)
@@ -719,28 +681,95 @@ private:
return false;
}
+
+ // Algorithm:
+ // - for each node:
+ // - get the depth of a node. If it's unknown (-1):
+ // - get the depth of the immediate dominator.
+ // - if that's unknown too, calculate it by calling calculateNodeDepth
+ // - set the current node's depth to that of immediate dominator + 1
+ std::vector<int> calculateNodeDepths() const
+ {
+ std::vector<int> nodeDepths(function->basicBlockCount(), -1);
+ nodeDepths[0] = 0;
+ foreach (BasicBlock *bb, function->basicBlocks()) {
+ if (bb->isRemoved())
+ continue;
+
+ int &bbDepth = nodeDepths[bb->index()];
+ if (bbDepth == -1) {
+ const int immDom = idom[bb->index()];
+ int immDomDepth = nodeDepths[immDom];
+ if (immDomDepth == -1)
+ immDomDepth = calculateNodeDepth(immDom, nodeDepths);
+ bbDepth = immDomDepth + 1;
+ }
+ }
+ return nodeDepths;
+ }
+
+ // Algorithm:
+ // - search for the first dominator of a node that has a known depth. As all nodes are
+ // reachable from the start node, and that node's depth is 0, this is finite.
+ // - while doing that search, put all unknown nodes in the worklist
+ // - pop all nodes from the worklist, and set their depth to the previous' (== dominating)
+ // node's depth + 1
+ // This way every node's depth is calculated once, and the complexity is O(n).
+ int calculateNodeDepth(int nodeIdx, std::vector<int> &nodeDepths) const
+ {
+ std::vector<int> worklist;
+ worklist.reserve(8);
+ int depth = -1;
+
+ do {
+ worklist.push_back(nodeIdx);
+ nodeIdx = idom[nodeIdx];
+ depth = nodeDepths[nodeIdx];
+ } while (depth == -1);
+
+ for (std::vector<int>::const_reverse_iterator it = worklist.rbegin(), eit = worklist.rend(); it != eit; ++it)
+ nodeDepths[*it] = ++depth;
+
+ return depth;
+ }
};
class VariableCollector: public StmtVisitor, ExprVisitor {
- typedef QHash<Temp, QSet<BasicBlock *> > DefSites;
- DefSites _defsites;
- QVector<QSet<Temp> > A_orig;
- QSet<Temp> nonLocals;
- QSet<Temp> killed;
+ std::vector<Temp> _allTemps;
+ std::vector<BasicBlockSet> _defsites;
+ std::vector<std::vector<int> > A_orig;
+ std::vector<bool> nonLocals;
+ std::vector<bool> killed;
BasicBlock *currentBB;
- IR::Function *function;
bool isCollectable(Temp *t) const
{
+ Q_UNUSED(t);
Q_ASSERT(t->kind != Temp::PhysicalRegister && t->kind != Temp::StackSlot);
- return unescapableTemp(t, function);
+ return true;
+ }
+
+ void addDefInCurrentBlock(Temp *t)
+ {
+ std::vector<int> &temps = A_orig[currentBB->index()];
+ if (std::find(temps.begin(), temps.end(), t->index) == temps.end())
+ temps.push_back(t->index);
+ }
+
+ void addTemp(Temp *t)
+ {
+ if (_allTemps[t->index].kind == Temp::Invalid)
+ _allTemps[t->index] = *t;
}
public:
VariableCollector(IR::Function *function)
- : function(function)
{
- _defsites.reserve(function->tempCount);
+ _allTemps.resize(function->tempCount);
+ _defsites.resize(function->tempCount);
+ for (int i = 0; i < function->tempCount; ++i)
+ _defsites[i].init(function);
+ nonLocals.resize(function->tempCount);
A_orig.resize(function->basicBlockCount());
for (int i = 0, ei = A_orig.size(); i != ei; ++i)
A_orig[i].reserve(8);
@@ -754,11 +783,9 @@ public:
continue;
currentBB = bb;
- killed.clear();
- killed.reserve(bb->statements().size() / 2);
- foreach (Stmt *s, bb->statements()) {
+ killed.assign(function->tempCount, false);
+ foreach (Stmt *s, bb->statements())
s->accept(this);
- }
}
#if defined(SHOW_SSA)
@@ -773,28 +800,36 @@ public:
#endif // SHOW_SSA
}
- QList<Temp> vars() const {
- return _defsites.keys();
- }
+ const std::vector<Temp> &allTemps() const
+ { return _allTemps; }
- QSet<BasicBlock *> defsite(const Temp &n) const {
- return _defsites[n];
+ void collectDefSites(const Temp &n, std::vector<BasicBlock *> &bbs) const {
+ Q_ASSERT(!n.isInvalid());
+ Q_ASSERT(n.index < _defsites.size());
+ _defsites[n.index].collectValues(bbs);
}
- QSet<Temp> inBlock(BasicBlock *n) const {
+ const std::vector<int> &inBlock(BasicBlock *n) const
+ {
return A_orig.at(n->index());
}
- bool isNonLocal(const Temp &var) const { return nonLocals.contains(var); }
+ bool isNonLocal(const Temp &var) const
+ {
+ Q_ASSERT(!var.isInvalid());
+ Q_ASSERT(var.index < nonLocals.size());
+ return nonLocals[var.index];
+ }
protected:
- virtual void visitPhi(Phi *) {};
- virtual void visitConvert(Convert *e) { e->expr->accept(this); };
+ virtual void visitPhi(Phi *) {}
+ virtual void visitConvert(Convert *e) { e->expr->accept(this); }
virtual void visitConst(Const *) {}
virtual void visitString(IR::String *) {}
virtual void visitRegExp(IR::RegExp *) {}
virtual void visitName(Name *) {}
+ virtual void visitArgLocal(ArgLocal *) {}
virtual void visitClosure(Closure *) {}
virtual void visitUnop(Unop *e) { e->expr->accept(this); }
virtual void visitBinop(Binop *e) { e->left->accept(this); e->right->accept(this); }
@@ -821,6 +856,8 @@ protected:
s->source->accept(this);
if (Temp *t = s->target->asTemp()) {
+ addTemp(t);
+
if (isCollectable(t)) {
#if defined(SHOW_SSA)
qout << '\t';
@@ -828,18 +865,11 @@ protected:
qout << " -> L" << currentBB->index << endl;
#endif // SHOW_SSA
- DefSites::iterator defsitesIt = _defsites.find(*t);
- if (defsitesIt == _defsites.end()) {
- QSet<BasicBlock *> bbs;
- bbs.reserve(4);
- defsitesIt = _defsites.insert(*t, bbs);
- }
- defsitesIt->insert(currentBB);
-
- A_orig[currentBB->index()].insert(*t);
+ _defsites[t->index].insert(currentBB);
+ addDefInCurrentBlock(t);
// For semi-pruned SSA:
- killed.insert(*t);
+ killed[t->index] = true;
}
} else {
s->target->accept(this);
@@ -848,9 +878,243 @@ protected:
virtual void visitTemp(Temp *t)
{
+ addTemp(t);
+
if (isCollectable(t))
- if (!killed.contains(*t))
- nonLocals.insert(*t);
+ if (!killed[t->index])
+ nonLocals[t->index] = true;
+ }
+};
+
+struct UntypedTemp {
+ Temp temp;
+ UntypedTemp() {}
+ UntypedTemp(const Temp &t): temp(t) {}
+};
+inline bool operator==(const UntypedTemp &t1, const UntypedTemp &t2) Q_DECL_NOTHROW
+{ return t1.temp.index == t2.temp.index && t1.temp.kind == t2.temp.kind; }
+inline bool operator!=(const UntypedTemp &t1, const UntypedTemp &t2) Q_DECL_NOTHROW
+{ return !(t1 == t2); }
+
+class DefUses
+{
+public:
+ struct DefUse {
+ DefUse()
+ : defStmt(0)
+ , blockOfStatement(0)
+ { uses.reserve(8); }
+ Temp temp;
+ Stmt *defStmt;
+ BasicBlock *blockOfStatement;
+ QVector<Stmt *> uses;
+
+ bool isValid() const
+ { return temp.kind != Temp::Invalid; }
+
+ void clear()
+ { defStmt = 0; blockOfStatement = 0; uses.clear(); }
+ };
+
+private:
+ std::vector<DefUse> _defUses;
+ class Temps: public QVector<Temp> {
+ public:
+ Temps() { reserve(4); }
+ };
+ std::vector<Temps> _usesPerStatement;
+
+ void ensure(Temp *newTemp)
+ {
+ if (_defUses.size() <= newTemp->index) {
+ _defUses.reserve(newTemp->index + _defUses.size() / 3 + 1);
+ _defUses.resize(newTemp->index + 1);
+ }
+ }
+
+ void ensure(Stmt *s)
+ {
+ Q_ASSERT(s->id() >= 0);
+ if (static_cast<unsigned>(s->id()) >= _usesPerStatement.size()) {
+ _usesPerStatement.reserve(s->id() + _usesPerStatement.size() / 3 + 1);
+ _usesPerStatement.resize(s->id() + 1);
+ }
+ }
+
+ void addUseForStatement(Stmt *s, const Temp &var)
+ {
+ ensure(s);
+ _usesPerStatement[s->id()].push_back(var);
+ }
+
+public:
+ DefUses(IR::Function *function)
+ {
+ _usesPerStatement.resize(function->statementCount());
+ _defUses.resize(function->tempCount);
+ }
+
+ void cleanup()
+ {
+ for (size_t i = 0, ei = _defUses.size(); i != ei; ++i) {
+ DefUse &defUse = _defUses[i];
+ if (defUse.isValid() && !defUse.defStmt)
+ defUse.clear();
+ }
+ }
+
+ unsigned statementCount() const
+ { return _usesPerStatement.size(); }
+
+ unsigned tempCount() const
+ { return _defUses.size(); }
+
+ const Temp &temp(int idx) const
+ { return _defUses[idx].temp; }
+
+ void addDef(Temp *newTemp, Stmt *defStmt, BasicBlock *defBlock)
+ {
+ ensure(newTemp);
+ DefUse &defUse = _defUses[newTemp->index];
+ Q_ASSERT(!defUse.isValid());
+ defUse.temp = *newTemp;
+ defUse.defStmt = defStmt;
+ defUse.blockOfStatement = defBlock;
+ }
+
+ QList<UntypedTemp> defsUntyped() const
+ {
+ QList<UntypedTemp> res;
+ foreach (const DefUse &du, _defUses)
+ if (du.isValid())
+ res.append(UntypedTemp(du.temp));
+ return res;
+ }
+
+ std::vector<const Temp *> defs() const {
+ std::vector<const Temp *> res;
+ res.reserve(_defUses.size());
+ for (unsigned i = 0, ei = _defUses.size(); i != ei; ++i) {
+ const DefUse &du = _defUses.at(i);
+ if (du.isValid())
+ res.push_back(&du.temp);
+ }
+ return res;
+ }
+
+ void removeDef(const Temp &variable) {
+ Q_ASSERT(static_cast<unsigned>(variable.index) < _defUses.size());
+ _defUses[variable.index].clear();
+ }
+
+ void addUses(const Temp &variable, const QVector<Stmt *> &newUses)
+ {
+ Q_ASSERT(static_cast<unsigned>(variable.index) < _defUses.size());
+ QVector<Stmt *> &uses = _defUses[variable.index].uses;
+ foreach (Stmt *stmt, newUses)
+ if (std::find(uses.begin(), uses.end(), stmt) == uses.end())
+ uses.push_back(stmt);
+ }
+
+ void addUse(const Temp &variable, Stmt *newUse)
+ {
+ if (_defUses.size() <= variable.index) {
+ _defUses.resize(variable.index + 1);
+ DefUse &du = _defUses[variable.index];
+ du.temp = variable;
+ du.uses.push_back(newUse);
+ addUseForStatement(newUse, variable);
+ return;
+ }
+
+ QVector<Stmt *> &uses = _defUses[variable.index].uses;
+ if (std::find(uses.begin(), uses.end(), newUse) == uses.end())
+ uses.push_back(newUse);
+ addUseForStatement(newUse, variable);
+ }
+
+ int useCount(const Temp &variable) const
+ {
+ Q_ASSERT(static_cast<unsigned>(variable.index) < _defUses.size());
+ return _defUses[variable.index].uses.size();
+ }
+
+ Stmt *defStmt(const Temp &variable) const
+ {
+ Q_ASSERT(static_cast<unsigned>(variable.index) < _defUses.size());
+ return _defUses[variable.index].defStmt;
+ }
+
+ BasicBlock *defStmtBlock(const Temp &variable) const
+ {
+ Q_ASSERT(static_cast<unsigned>(variable.index) < _defUses.size());
+ return _defUses[variable.index].blockOfStatement;
+ }
+
+ void removeUse(Stmt *usingStmt, const Temp &var)
+ {
+ Q_ASSERT(static_cast<unsigned>(var.index) < _defUses.size());
+ QVector<Stmt *> &uses = _defUses[var.index].uses;
+ uses.erase(std::remove(uses.begin(), uses.end(), usingStmt), uses.end());
+ }
+
+ void registerNewStatement(Stmt *s)
+ {
+ ensure(s);
+ }
+
+ const QVector<Temp> &usedVars(Stmt *s) const
+ {
+ Q_ASSERT(s->id() >= 0);
+ Q_ASSERT(static_cast<unsigned>(s->id()) < _usesPerStatement.size());
+ return _usesPerStatement[s->id()];
+ }
+
+ const QVector<Stmt *> &uses(const Temp &var) const
+ {
+ return _defUses[var.index].uses;
+ }
+
+ QVector<Stmt*> removeDefUses(Stmt *s)
+ {
+ QVector<Stmt*> defStmts;
+ foreach (const Temp &usedVar, usedVars(s)) {
+ if (Stmt *ds = defStmt(usedVar))
+ defStmts += ds;
+ removeUse(s, usedVar);
+ }
+ if (Move *m = s->asMove()) {
+ if (Temp *t = m->target->asTemp())
+ removeDef(*t);
+ } else if (Phi *p = s->asPhi()) {
+ removeDef(*p->targetTemp);
+ }
+
+ return defStmts;
+ }
+
+ void dump() const
+ {
+ qout << "Defines and uses:" << endl;
+ foreach (const DefUse &du, _defUses) {
+ if (!du.isValid())
+ continue;
+ qout << '%' << du.temp.index;
+ qout << " -> defined in block " << du.blockOfStatement->index()
+ << ", statement: " << du.defStmt->id()
+ << endl;
+ qout << " uses:";
+ foreach (Stmt *s, du.uses)
+ qout << ' ' << s->id();
+ qout << endl;
+ }
+ qout << "Uses per statement:" << endl;
+ for (unsigned i = 0, ei = _usesPerStatement.size(); i != ei; ++i) {
+ qout << " " << i << ":";
+ foreach (const Temp &t, _usesPerStatement[i])
+ qout << ' ' << t.index;
+ qout << endl;
+ }
}
};
@@ -861,16 +1125,16 @@ void insertPhiNode(const Temp &a, BasicBlock *y, IR::Function *f) {
qout << " in block " << y->index << endl;
#endif
- Phi *phiNode = f->New<Phi>();
+ Phi *phiNode = f->NewStmt<Phi>();
phiNode->d = new Stmt::Data;
phiNode->targetTemp = f->New<Temp>();
- phiNode->targetTemp->init(a.kind, a.index, 0);
+ phiNode->targetTemp->init(a.kind, a.index);
y->prependStatement(phiNode);
phiNode->d->incoming.resize(y->in.size());
for (int i = 0, ei = y->in.size(); i < ei; ++i) {
Temp *t = f->New<Temp>();
- t->init(a.kind, a.index, 0);
+ t->init(a.kind, a.index);
phiNode->d->incoming[i] = t;
}
}
@@ -945,23 +1209,22 @@ void insertPhiNode(const Temp &a, BasicBlock *y, IR::Function *f) {
// mapping[t] = c
class VariableRenamer: public StmtVisitor, public ExprVisitor
{
+ Q_DISABLE_COPY(VariableRenamer)
+
IR::Function *function;
+ DefUses &defUses;
unsigned tempCount;
- typedef QHash<unsigned, int> Mapping; // maps from existing/old temp number to the new and unique temp number.
+ typedef std::vector<int> Mapping; // maps from existing/old temp number to the new and unique temp number.
enum { Absent = -1 };
- Mapping localMapping;
Mapping vregMapping;
ProcessedBlocks processed;
- bool isRenamable(Temp *t) const
- {
- Q_ASSERT(t->kind != Temp::PhysicalRegister && t->kind != Temp::StackSlot);
- return unescapableTemp(t, function);
- }
+ BasicBlock *currentBB;
+ Stmt *currentStmt;
struct TodoAction {
- enum { RestoreLocal, RestoreVReg, Rename } action;
+ enum { RestoreVReg, Rename } action;
union {
struct {
unsigned temp;
@@ -982,9 +1245,9 @@ class VariableRenamer: public StmtVisitor, public ExprVisitor
TodoAction(const Temp &t, int prev)
{
- Q_ASSERT(t.kind == Temp::Local || t.kind == Temp::VirtualRegister);
+ Q_ASSERT(t.kind == Temp::VirtualRegister);
- action = t.kind == Temp::Local ? RestoreLocal : RestoreVReg;
+ action = RestoreVReg;
restoreData.temp = t.index;
restoreData.previous = prev;
}
@@ -1001,13 +1264,13 @@ class VariableRenamer: public StmtVisitor, public ExprVisitor
QVector<TodoAction> todo;
public:
- VariableRenamer(IR::Function *f)
+ VariableRenamer(IR::Function *f, DefUses &defUses)
: function(f)
+ , defUses(defUses)
, tempCount(0)
, processed(f)
{
- localMapping.reserve(f->tempCount);
- vregMapping.reserve(f->tempCount);
+ vregMapping.assign(f->tempCount, Absent);
todo.reserve(f->basicBlockCount());
}
@@ -1023,9 +1286,6 @@ public:
case TodoAction::Rename:
rename(todoAction.renameData.basicBlock);
break;
- case TodoAction::RestoreLocal:
- restore(localMapping, todoAction.restoreData.temp, todoAction.restoreData.previous);
- break;
case TodoAction::RestoreVReg:
restore(vregMapping, todoAction.restoreData.temp, todoAction.restoreData.previous);
break;
@@ -1038,12 +1298,9 @@ public:
}
private:
- static inline void restore(Mapping &mapping, unsigned temp, int previous)
+ static inline void restore(Mapping &mapping, int temp, int previous)
{
- if (previous == Absent)
- mapping.remove(temp);
- else
- mapping[temp] = previous;
+ mapping[temp] = previous;
}
void rename(BasicBlock *bb)
@@ -1067,8 +1324,12 @@ private:
void renameStatementsAndPhis(BasicBlock *bb)
{
- foreach (Stmt *s, bb->statements())
+ currentBB = bb;
+
+ foreach (Stmt *s, bb->statements()) {
+ currentStmt = s;
s->accept(this);
+ }
foreach (BasicBlock *Y, bb->out) {
const int j = Y->in.indexOf(bb);
@@ -1080,6 +1341,7 @@ private:
// qDebug()<<"I: replacing phi use"<<a<<"with"<<newTmp<<"in L"<<Y->index;
t->index = newTmp;
t->kind = Temp::VirtualRegister;
+ defUses.addUse(*t, phi);
} else {
break;
}
@@ -1091,11 +1353,8 @@ private:
{
int nr = Absent;
switch (t.kind) {
- case Temp::Local:
- nr = localMapping.value(t.index, Absent);
- break;
case Temp::VirtualRegister:
- nr = vregMapping.value(t.index, Absent);
+ nr = vregMapping[t.index];
break;
default:
Q_UNREACHABLE();
@@ -1122,13 +1381,9 @@ private:
int oldIndex = Absent;
switch (t.kind) {
- case Temp::Local:
- oldIndex = localMapping.value(t.index, Absent);
- localMapping.insert(t.index, newIndex);
- break;
case Temp::VirtualRegister:
- oldIndex = vregMapping.value(t.index, Absent);
- vregMapping.insert(t.index, newIndex);
+ oldIndex = vregMapping[t.index];
+ vregMapping[t.index] = newIndex;
break;
default:
Q_UNREACHABLE();
@@ -1141,11 +1396,10 @@ private:
protected:
virtual void visitTemp(Temp *e) { // only called for uses, not defs
- if (isRenamable(e)) {
-// qDebug()<<"I: replacing use of"<<e->index<<"with"<<stack[e->index].top();
- e->index = currentNumber(*e);
- e->kind = Temp::VirtualRegister;
- }
+// qDebug()<<"I: replacing use of"<<e->index<<"with"<<stack[e->index].top();
+ e->index = currentNumber(*e);
+ e->kind = Temp::VirtualRegister;
+ defUses.addUse(*e, currentStmt);
}
virtual void visitMove(Move *s) {
@@ -1159,13 +1413,12 @@ protected:
s->target->accept(this);
}
- void renameTemp(Temp *t) {
- if (isRenamable(t)) {
- const int newIdx = nextFreeTemp(*t);
-// qDebug()<<"I: replacing def of"<<a<<"with"<<newIdx;
- t->kind = Temp::VirtualRegister;
- t->index = newIdx;
- }
+ void renameTemp(Temp *t) { // only called for defs, not uses
+ const int newIdx = nextFreeTemp(*t);
+// qDebug()<<"I: replacing def of"<<a<<"with"<<newIdx;
+ t->kind = Temp::VirtualRegister;
+ t->index = newIdx;
+ defUses.addDef(t, currentStmt, currentBB);
}
virtual void visitConvert(Convert *e) { e->expr->accept(this); }
@@ -1181,6 +1434,7 @@ protected:
virtual void visitString(IR::String *) {}
virtual void visitRegExp(IR::RegExp *) {}
virtual void visitName(Name *) {}
+ virtual void visitArgLocal(ArgLocal *) {}
virtual void visitClosure(Closure *) {}
virtual void visitUnop(Unop *e) { e->expr->accept(this); }
virtual void visitBinop(Binop *e) { e->left->accept(this); e->right->accept(this); }
@@ -1206,7 +1460,9 @@ protected:
}
};
-void convertToSSA(IR::Function *function, const DominatorTree &df)
+// This function converts the IR to semi-pruned SSA form. For details about SSA and the algorightm,
+// see [Appel]. For the changes needed for semi-pruned SSA form, and for its advantages, see [Briggs].
+void convertToSSA(IR::Function *function, const DominatorTree &df, DefUses &defUses)
{
#if defined(SHOW_SSA)
qout << "Converting function ";
@@ -1221,376 +1477,214 @@ void convertToSSA(IR::Function *function, const DominatorTree &df)
VariableCollector variables(function);
// Prepare for phi node insertion:
- QVector<QSet<Temp> > A_phi;
+ std::vector<std::vector<bool> > A_phi;
A_phi.resize(function->basicBlockCount());
- for (int i = 0, ei = A_phi.size(); i != ei; ++i) {
- QSet<Temp> temps;
- temps.reserve(4);
- A_phi[i] = temps;
- }
+ for (int i = 0, ei = A_phi.size(); i != ei; ++i)
+ A_phi[i].assign(function->tempCount, false);
+
+ std::vector<BasicBlock *> W;
+ W.reserve(8);
// Place phi functions:
- foreach (Temp a, variables.vars()) {
+ foreach (const Temp &a, variables.allTemps()) {
+ if (a.isInvalid())
+ continue;
if (!variables.isNonLocal(a))
continue; // for semi-pruned SSA
- QList<BasicBlock *> W = QList<BasicBlock *>::fromSet(variables.defsite(a));
- while (!W.isEmpty()) {
- BasicBlock *n = W.first();
- W.removeFirst();
+ W.clear();
+ variables.collectDefSites(a, W);
+ while (!W.empty()) {
+ BasicBlock *n = W.back();
+ W.pop_back();
const BasicBlockSet &dominatorFrontierForN = df.dominatorFrontier(n);
for (BasicBlockSet::const_iterator it = dominatorFrontierForN.begin(), eit = dominatorFrontierForN.end();
it != eit; ++it) {
BasicBlock *y = *it;
- if (!A_phi.at(y->index()).contains(a)) {
+ if (!A_phi.at(y->index()).at(a.index)) {
insertPhiNode(a, y, function);
- A_phi[y->index()].insert(a);
- if (!variables.inBlock(y).contains(a))
- W.append(y);
+ A_phi[y->index()].at(a.index) = true;
+ const std::vector<int> &varsInBlockY = variables.inBlock(y);
+ if (std::find(varsInBlockY.begin(), varsInBlockY.end(), a.index) == varsInBlockY.end())
+ W.push_back(y);
}
}
}
}
// Rename variables:
- VariableRenamer(function).run();
+ VariableRenamer(function, defUses).run();
}
-struct UntypedTemp {
- Temp temp;
- UntypedTemp() {}
- UntypedTemp(const Temp &t): temp(t) {}
-};
-inline uint qHash(const UntypedTemp &t, uint seed = 0) Q_DECL_NOTHROW
-{ return t.temp.index ^ (t.temp.kind | (t.temp.scope << 3)) ^ seed; }
-inline bool operator==(const UntypedTemp &t1, const UntypedTemp &t2) Q_DECL_NOTHROW
-{ return t1.temp.index == t2.temp.index && t1.temp.scope == t2.temp.scope && t1.temp.kind == t2.temp.kind; }
-inline bool operator!=(const UntypedTemp &t1, const UntypedTemp &t2) Q_DECL_NOTHROW
-{ return !(t1 == t2); }
-
-class DefUsesCalculator: public StmtVisitor, public ExprVisitor {
-public:
- struct DefUse {
- DefUse()
- : defStmt(0)
- , blockOfStatement(0)
- {}
- Stmt *defStmt;
- BasicBlock *blockOfStatement;
- QList<Stmt *> uses;
- };
-
-private:
- IR::Function *function;
- typedef QHash<UntypedTemp, DefUse> DefUses;
- DefUses _defUses;
- QHash<Stmt *, QList<Temp> > _usesPerStatement;
-
- BasicBlock *_block;
- Stmt *_stmt;
-
- bool isCollectible(Temp *t) const {
- Q_ASSERT(t->kind != Temp::PhysicalRegister && t->kind != Temp::StackSlot);
- return unescapableTemp(t, function);
- }
-
- void addUse(Temp *t) {
- Q_ASSERT(t);
- if (!isCollectible(t))
- return;
-
- _defUses[*t].uses.append(_stmt);
- _usesPerStatement[_stmt].append(*t);
- }
-
- void addDef(Temp *t) {
- if (!isCollectible(t))
- return;
-
- Q_ASSERT(!_defUses.contains(*t) || _defUses.value(*t).defStmt == 0 || _defUses.value(*t).defStmt == _stmt);
-
- DefUse &defUse = _defUses[*t];
- defUse.defStmt = _stmt;
- defUse.blockOfStatement = _block;
- }
-
-public:
- DefUsesCalculator(IR::Function *function)
- : function(function)
- {
- foreach (BasicBlock *bb, function->basicBlocks()) {
- if (bb->isRemoved())
- continue;
-
- _block = bb;
- foreach (Stmt *stmt, bb->statements()) {
- _stmt = stmt;
- stmt->accept(this);
- }
- }
-
- QMutableHashIterator<UntypedTemp, DefUse> it(_defUses);
- while (it.hasNext()) {
- it.next();
- if (!it.value().defStmt)
- it.remove();
- }
- }
-
- void addTemp(Temp *newTemp, Stmt *defStmt, BasicBlock *defBlock)
- {
- DefUse &defUse = _defUses[*newTemp];
- defUse.defStmt = defStmt;
- defUse.blockOfStatement = defBlock;
- }
-
- QList<UntypedTemp> defsUntyped() const { return _defUses.keys(); }
-
- QList<Temp> defs() const {
- QList<Temp> res;
- res.reserve(_defUses.size());
- foreach (const UntypedTemp &t, _defUses.keys())
- res.append(t.temp);
- return res;
- }
-
- void removeDef(const Temp &var) {
- _defUses.remove(var);
- }
-
- void addUses(const Temp &variable, const QList<Stmt *> &newUses)
- { _defUses[variable].uses.append(newUses); }
-
- void addUse(const Temp &variable, Stmt * newUse)
- { _defUses[variable].uses.append(newUse); }
-
- int useCount(const UntypedTemp &variable) const
- { return _defUses[variable].uses.size(); }
-
- Stmt *defStmt(const UntypedTemp &variable) const
- { return _defUses[variable].defStmt; }
-
- BasicBlock *defStmtBlock(const Temp &variable) const
- { return _defUses[variable].blockOfStatement; }
-
- void removeUse(Stmt *usingStmt, const Temp &var)
- { _defUses[var].uses.removeAll(usingStmt); }
-
- QList<Temp> usedVars(Stmt *s) const
- { return _usesPerStatement[s]; }
-
- const QList<Stmt *> &uses(const UntypedTemp &var) const
- {
- static const QList<Stmt *> noUses;
-
- DefUses::const_iterator it = _defUses.find(var);
- if (it == _defUses.end())
- return noUses;
- else
- return it->uses;
- }
-
- QVector<Stmt*> removeDefUses(Stmt *s)
- {
- QVector<Stmt*> defStmts;
- foreach (const Temp &usedVar, usedVars(s)) {
- if (Stmt *ds = defStmt(usedVar))
- defStmts += ds;
- removeUse(s, usedVar);
- }
- if (Move *m = s->asMove()) {
- if (Temp *t = m->target->asTemp())
- removeDef(*t);
- } else if (Phi *p = s->asPhi()) {
- removeDef(*p->targetTemp);
- }
-
- return defStmts;
- }
-
- void dump() const
- {
- foreach (const UntypedTemp &var, _defUses.keys()) {
- const DefUse &du = _defUses[var];
- var.temp.dump(qout);
- qout<<" -> defined in block "<<du.blockOfStatement->index()<<", statement: ";
- du.defStmt->dump(qout);
- qout<<endl<<" uses:"<<endl;
- foreach (Stmt *s, du.uses) {
- qout<<" ";s->dump(qout);qout<<endl;
- }
- }
- }
-
-protected:
- virtual void visitExp(Exp *s) { s->expr->accept(this); }
- virtual void visitJump(Jump *) {}
- virtual void visitCJump(CJump *s) { s->cond->accept(this); }
- virtual void visitRet(Ret *s) { s->expr->accept(this); }
-
- virtual void visitPhi(Phi *s) {
- addDef(s->targetTemp);
- foreach (Expr *e, s->d->incoming)
- addUse(e->asTemp());
- }
-
- virtual void visitMove(Move *s) {
- if (Temp *t = s->target->asTemp())
- addDef(t);
- else
- s->target->accept(this);
-
- s->source->accept(this);
- }
-
- virtual void visitTemp(Temp *e) { addUse(e); }
+/// Calculate if a phi node result is used only by other phi nodes, and if those uses are
+/// in turn also used by other phi nodes.
+bool hasPhiOnlyUses(Phi *phi, const DefUses &defUses, QBitArray &collectedPhis)
+{
+ collectedPhis.setBit(phi->id());
- virtual void visitConst(Const *) {}
- virtual void visitString(IR::String *) {}
- virtual void visitRegExp(IR::RegExp *) {}
- virtual void visitName(Name *) {}
- virtual void visitClosure(Closure *) {}
- virtual void visitConvert(Convert *e) { e->expr->accept(this); }
- virtual void visitUnop(Unop *e) { e->expr->accept(this); }
- virtual void visitBinop(Binop *e) { e->left->accept(this); e->right->accept(this); }
- virtual void visitSubscript(Subscript *e) { e->base->accept(this); e->index->accept(this); }
- virtual void visitMember(Member *e) { e->base->accept(this); }
- virtual void visitCall(Call *e) {
- e->base->accept(this);
- for (ExprList *it = e->args; it; it = it->next)
- it->expr->accept(this);
- }
+ foreach (Stmt *use, defUses.uses(*phi->targetTemp)) {
+ Phi *dependentPhi = use->asPhi();
+ if (!dependentPhi)
+ return false; // there is a use by a non-phi node
- virtual void visitNew(New *e) {
- e->base->accept(this);
- for (ExprList *it = e->args; it; it = it->next)
- it->expr->accept(this);
- }
-};
+ if (collectedPhis.at(dependentPhi->id()))
+ continue; // we already found this node
-bool hasPhiOnlyUses(Phi *phi, const DefUsesCalculator &defUses, QSet<Phi *> &collectedPhis)
-{
- collectedPhis.insert(phi);
- foreach (Stmt *use, defUses.uses(*phi->targetTemp)) {
- if (Phi *dependentPhi = use->asPhi()) {
- if (!collectedPhis.contains(dependentPhi)) {
- if (!hasPhiOnlyUses(dependentPhi, defUses, collectedPhis))
- return false;
- }
- } else {
+ if (!hasPhiOnlyUses(dependentPhi, defUses, collectedPhis))
return false;
- }
}
+
return true;
}
-void cleanupPhis(DefUsesCalculator &defUses)
+void cleanupPhis(DefUses &defUses)
{
- QLinkedList<Phi *> phis;
- foreach (const Temp &def, defUses.defs())
- if (Phi *phi = defUses.defStmt(def)->asPhi())
- phis.append(phi);
-
- QSet<Phi *> toRemove;
- while (!phis.isEmpty()) {
- Phi *phi = phis.first();
- phis.removeFirst();
- if (toRemove.contains(phi))
+ QBitArray toRemove(defUses.statementCount());
+ QBitArray collectedPhis(defUses.statementCount());
+ std::vector<Phi *> allPhis;
+ allPhis.reserve(32);
+
+ foreach (const Temp *def, defUses.defs()) {
+ Stmt *defStmt = defUses.defStmt(*def);
+ if (!defStmt)
+ continue;
+
+ Phi *phi = defStmt->asPhi();
+ if (!phi)
+ continue;
+ allPhis.push_back(phi);
+ if (toRemove.at(phi->id()))
continue;
- QSet<Phi *> collectedPhis;
+
+ collectedPhis.fill(false);
if (hasPhiOnlyUses(phi, defUses, collectedPhis))
- toRemove.unite(collectedPhis);
+ toRemove |= collectedPhis;
}
- foreach (Phi *phi, toRemove) {
- Temp targetVar = *phi->targetTemp;
+ foreach (Phi *phi, allPhis) {
+ if (!toRemove.at(phi->id()))
+ continue;
+ const Temp &targetVar = *phi->targetTemp;
defUses.defStmtBlock(targetVar)->removeStatement(phi);
foreach (const Temp &usedVar, defUses.usedVars(phi))
defUses.removeUse(phi, usedVar);
defUses.removeDef(targetVar);
}
+
+ defUses.cleanup();
}
class StatementWorklist
{
- QVector<Stmt *> worklist;
- QBitArray inWorklist;
- QSet<Stmt *> removed;
- QHash<Stmt*,Stmt*> replaced;
+ IR::Function *theFunction;
+ std::vector<Stmt *> stmts;
+ std::vector<bool> worklist;
+ unsigned worklistSize;
+ std::vector<int> replaced;
+ std::vector<bool> removed;
Q_DISABLE_COPY(StatementWorklist)
public:
StatementWorklist(IR::Function *function)
+ : theFunction(function)
+ , stmts(function->statementCount(), 0)
+ , worklist(function->statementCount(), false)
+ , worklistSize(0)
+ , replaced(function->statementCount(), Stmt::InvalidId)
+ , removed(function->statementCount())
{
- QVector<Stmt *> w;
- int stmtCount = 0;
+ grow();
- // Put in all statements, and number them on the fly. The numbering is used to index the
- // bit array.
foreach (BasicBlock *bb, function->basicBlocks()) {
if (bb->isRemoved())
continue;
foreach (Stmt *s, bb->statements()) {
- s->id = stmtCount++;
- w.append(s);
+ if (!s)
+ continue;
+
+ stmts[s->id()] = s;
+ worklist[s->id()] = true;
+ ++worklistSize;
}
}
+ }
- // For QVector efficiency reasons, we process statements from the back. However, it is more
- // effective to process the statements in ascending order. So we need to invert the
- // order.
- worklist.reserve(w.size());
- for (int i = w.size() - 1; i >= 0; --i)
- worklist.append(w.at(i));
+ void reset()
+ {
+ foreach (Stmt *s, stmts) {
+ if (!s)
+ continue;
- inWorklist = QBitArray(stmtCount, true);
+ worklist[s->id()] = true;
+ ++worklistSize;
+ }
+
+ replaced.assign(replaced.size(), Stmt::InvalidId);
+ removed.assign(removed.size(), false);
}
- // This will clear the entry for the statement in the basic block. After processing all
- // statements, the cleanup method needs to be run to remove all null-pointers.
- void clear(Stmt *stmt)
+ void remove(Stmt *stmt)
{
- Q_ASSERT(!inWorklist.at(stmt->id));
- removed.insert(stmt);
+ replaced[stmt->id()] = Stmt::InvalidId;
+ removed[stmt->id()] = true;
+ std::vector<bool>::reference inWorklist = worklist[stmt->id()];
+ if (inWorklist) {
+ inWorklist = false;
+ Q_ASSERT(worklistSize > 0);
+ --worklistSize;
+ }
}
void replace(Stmt *oldStmt, Stmt *newStmt)
{
Q_ASSERT(oldStmt);
+ Q_ASSERT(replaced[oldStmt->id()] == Stmt::InvalidId);
+ Q_ASSERT(removed[oldStmt->id()] == false);
+
Q_ASSERT(newStmt);
- Q_ASSERT(!removed.contains(oldStmt));
+ registerNewStatement(newStmt);
+ Q_ASSERT(replaced[newStmt->id()] == Stmt::InvalidId);
+ Q_ASSERT(removed[newStmt->id()] == false);
- if (newStmt->id == -1)
- newStmt->id = oldStmt->id;
- QHash<Stmt *, Stmt *>::const_iterator it = replaced.find(oldStmt);
- if (it != replaced.end())
- oldStmt = it.key();
- replaced[oldStmt] = newStmt;
+ replaced[oldStmt->id()] = newStmt->id();
+ worklist[oldStmt->id()] = false;
}
- void cleanup(IR::Function *function)
+ void applyToFunction()
{
- foreach (BasicBlock *bb, function->basicBlocks()) {
+ foreach (BasicBlock *bb, theFunction->basicBlocks()) {
if (bb->isRemoved())
continue;
for (int i = 0; i < bb->statementCount();) {
- Stmt *stmt = bb->statements()[i];
- QHash<Stmt *, Stmt *>::const_iterator it = replaced.find(stmt);
- if (it != replaced.end() && !removed.contains(it.value())) {
- bb->replaceStatement(i, it.value());
- } else if (removed.contains(stmt)) {
+ Stmt *stmt = bb->statements().at(i);
+
+ int id = stmt->id();
+ Q_ASSERT(id != Stmt::InvalidId);
+ Q_ASSERT(static_cast<unsigned>(stmt->id()) < stmts.size());
+
+ for (int replacementId = replaced[id]; replacementId != Stmt::InvalidId; replacementId = replaced[replacementId])
+ id = replacementId;
+ Q_ASSERT(id != Stmt::InvalidId);
+ Q_ASSERT(static_cast<unsigned>(stmt->id()) < stmts.size());
+
+ if (removed[id]) {
bb->removeStatement(i);
- continue;
- }
+ } else {
+ if (id != stmt->id())
+ bb->replaceStatement(i, stmts[id]);
- ++i;
+ ++i;
+ }
}
}
+
+ replaced.assign(replaced.size(), Stmt::InvalidId);
+ removed.assign(removed.size(), false);
}
StatementWorklist &operator+=(const QVector<Stmt *> &stmts)
@@ -1601,18 +1695,17 @@ public:
return *this;
}
-
StatementWorklist &operator+=(Stmt *s)
{
if (!s)
return *this;
- Q_ASSERT(s->id >= 0);
- Q_ASSERT(s->id < inWorklist.size());
+ Q_ASSERT(s->id() >= 0);
+ Q_ASSERT(static_cast<unsigned>(s->id()) < worklist.size());
- if (!inWorklist.at(s->id)) {
- worklist.append(s);
- inWorklist.setBit(s->id);
+ if (!worklist[s->id()]) {
+ worklist[s->id()] = true;
+ ++worklistSize;
}
return *this;
@@ -1620,12 +1713,14 @@ public:
StatementWorklist &operator-=(Stmt *s)
{
- Q_ASSERT(s->id >= 0);
- Q_ASSERT(s->id < inWorklist.size());
-
- if (inWorklist.at(s->id)) {
- worklist.remove(worklist.indexOf(s));
- inWorklist.clearBit(s->id);
+ Q_ASSERT(s->id() >= 0);
+ Q_ASSERT(static_cast<unsigned>(s->id()) < worklist.size());
+
+ std::vector<bool>::reference inWorklist = worklist[s->id()];
+ if (inWorklist) {
+ inWorklist = false;
+ Q_ASSERT(worklistSize > 0);
+ --worklistSize;
}
return *this;
@@ -1633,34 +1728,78 @@ public:
bool isEmpty() const
{
- return worklist.isEmpty();
+ return worklistSize == 0;
}
- Stmt *takeOne()
+ Stmt *takeNext(Stmt *last)
{
if (isEmpty())
return 0;
- Stmt *s = worklist.last();
- Q_ASSERT(s->id < inWorklist.size());
- worklist.removeLast();
- inWorklist.clearBit(s->id);
+ const int startAt = last ? last->id() + 1 : 0;
+ Q_ASSERT(startAt >= 0);
+ Q_ASSERT(static_cast<unsigned>(startAt) <= worklist.size());
+
+ Q_ASSERT(worklist.size() == stmts.size());
+
+ // Do not compare the result of find with the end iterator, because some libc++ versions
+ // have a bug where the result of the ++operator is past-the-end of the vector, but unequal
+ // to end().
+ size_t pos = std::find(worklist.begin() + startAt, worklist.end(), true) - worklist.begin();
+ if (pos >= worklist.size())
+ pos = std::find(worklist.begin(), worklist.begin() + startAt, true) - worklist.begin();
+
+ worklist[pos] = false;
+ Q_ASSERT(worklistSize > 0);
+ --worklistSize;
+ Stmt *s = stmts.at(pos);
+ Q_ASSERT(s);
return s;
}
+
+ IR::Function *function() const
+ {
+ return theFunction;
+ }
+
+ void registerNewStatement(Stmt *s)
+ {
+ Q_ASSERT(s->id() >= 0);
+ if (static_cast<unsigned>(s->id()) >= stmts.size()) {
+ if (static_cast<unsigned>(s->id()) >= stmts.capacity())
+ grow();
+
+ int newSize = s->id() + 1;
+ stmts.resize(newSize, 0);
+ worklist.resize(newSize, false);
+ replaced.resize(newSize, Stmt::InvalidId);
+ removed.resize(newSize, false);
+ }
+
+ stmts[s->id()] = s;
+ }
+
+private:
+ void grow()
+ {
+ size_t newCapacity = ((stmts.capacity() + 1) * 3) / 2;
+ stmts.reserve(newCapacity);
+ worklist.reserve(newCapacity);
+ replaced.reserve(newCapacity);
+ removed.reserve(newCapacity);
+ }
};
class EliminateDeadCode: public ExprVisitor {
- DefUsesCalculator &_defUses;
+ DefUses &_defUses;
StatementWorklist &_worklist;
- IR::Function *function;
bool _sideEffect;
QVector<Temp *> _collectedTemps;
public:
- EliminateDeadCode(DefUsesCalculator &defUses, StatementWorklist &worklist, IR::Function *function)
+ EliminateDeadCode(DefUses &defUses, StatementWorklist &worklist)
: _defUses(defUses)
, _worklist(worklist)
- , function(function)
{
_collectedTemps.reserve(8);
}
@@ -1691,11 +1830,6 @@ private:
_collectedTemps.clear();
}
- bool isCollectable(Temp *t) const
- {
- return unescapableTemp(t, function);
- }
-
protected:
virtual void visitConst(Const *) {}
virtual void visitString(IR::String *) {}
@@ -1713,10 +1847,11 @@ protected:
virtual void visitTemp(Temp *e)
{
- if (isCollectable(e))
- _collectedTemps.append(e);
+ _collectedTemps.append(e);
}
+ virtual void visitArgLocal(ArgLocal *) {}
+
virtual void visitClosure(Closure *)
{
markAsSideEffect();
@@ -1814,12 +1949,12 @@ struct DiscoveredType {
class PropagateTempTypes: public StmtVisitor, ExprVisitor
{
- const DefUsesCalculator &defUses;
+ const DefUses &defUses;
UntypedTemp theTemp;
DiscoveredType newType;
public:
- PropagateTempTypes(const DefUsesCalculator &defUses)
+ PropagateTempTypes(const DefUses &defUses)
: defUses(defUses)
{}
@@ -1827,9 +1962,9 @@ public:
{
newType = type;
theTemp = temp;
- if (Stmt *defStmt = defUses.defStmt(temp))
+ if (Stmt *defStmt = defUses.defStmt(temp.temp))
defStmt->accept(this);
- foreach (Stmt *use, defUses.uses(temp))
+ foreach (Stmt *use, defUses.uses(temp.temp))
use->accept(this);
}
@@ -1844,6 +1979,7 @@ protected:
e->memberResolver = newType.memberResolver;
}
}
+ virtual void visitArgLocal(ArgLocal *) {}
virtual void visitClosure(Closure *) {}
virtual void visitConvert(Convert *e) { e->expr->accept(this); }
virtual void visitUnop(Unop *e) { e->expr->accept(this); }
@@ -1884,71 +2020,81 @@ protected:
}
};
-class TypeInference: public StmtVisitor, public ExprVisitor {
+class TypeInference: public StmtVisitor, public ExprVisitor
+{
+ enum { DebugTypeInference = 0 };
+
QQmlEnginePrivate *qmlEngine;
- IR::Function *function;
- const DefUsesCalculator &_defUses;
- typedef QHash<Temp, DiscoveredType> TempTypes;
+ const DefUses &_defUses;
+ typedef std::vector<DiscoveredType> TempTypes;
TempTypes _tempTypes;
- QList<Stmt *> _worklist;
+ StatementWorklist *_worklist;
struct TypingResult {
DiscoveredType type;
bool fullyTyped;
- TypingResult(const DiscoveredType &type = DiscoveredType()) : type(type), fullyTyped(type.type != UnknownType) {}
- explicit TypingResult(MemberExpressionResolver memberResolver): type(memberResolver), fullyTyped(true) {}
+ TypingResult(const DiscoveredType &type = DiscoveredType())
+ : type(type)
+ , fullyTyped(type.type != UnknownType)
+ {}
+ explicit TypingResult(MemberExpressionResolver memberResolver)
+ : type(memberResolver)
+ , fullyTyped(true)
+ {}
};
TypingResult _ty;
public:
- TypeInference(QQmlEnginePrivate *qmlEngine, const DefUsesCalculator &defUses)
+ TypeInference(QQmlEnginePrivate *qmlEngine, const DefUses &defUses)
: qmlEngine(qmlEngine)
, _defUses(defUses)
+ , _tempTypes(_defUses.tempCount())
+ , _worklist(0)
, _ty(UnknownType)
{}
- void run(IR::Function *f) {
- function = f;
+ void run(StatementWorklist &w) {
+ _worklist = &w;
- // TODO: the worklist handling looks a bit inefficient... check if there is something better
- _worklist.clear();
- for (int i = 0, ei = function->basicBlockCount(); i != ei; ++i) {
- BasicBlock *bb = function->basicBlock(i);
- if (bb->isRemoved())
+ Stmt *s = 0;
+ while ((s = _worklist->takeNext(s))) {
+ if (s->asJump())
continue;
- if (i == 0 || !bb->in.isEmpty())
- _worklist += bb->statements().toList();
- }
-
- while (!_worklist.isEmpty()) {
- QList<Stmt *> worklist = QSet<Stmt *>::fromList(_worklist).toList();
- _worklist.clear();
- while (!worklist.isEmpty()) {
- Stmt *s = worklist.first();
- worklist.removeFirst();
- if (s->asJump())
- continue;
-#if defined(SHOW_SSA)
- qout<<"Typing stmt ";s->dump(qout);qout<<endl;
-#endif
+ if (DebugTypeInference) {
+ qout<<"Typing stmt ";
+ IRPrinter(&qout).print(s);
+ qout<<endl;
+ }
- if (!run(s)) {
- _worklist += s;
-#if defined(SHOW_SSA)
+ if (!run(s)) {
+ *_worklist += s;
+ if (DebugTypeInference) {
qout<<"Pushing back stmt: ";
- s->dump(qout);qout<<endl;
- } else {
+ IRPrinter(&qout).print(s);
+ qout<<endl;
+ }
+ } else {
+ if (DebugTypeInference) {
qout<<"Finished: ";
- s->dump(qout);qout<<endl;
-#endif
+ IRPrinter(&qout).print(s);
+ qout<<endl;
}
}
}
PropagateTempTypes propagator(_defUses);
- for (QHash<Temp, DiscoveredType>::const_iterator i = _tempTypes.begin(), ei = _tempTypes.end(); i != ei; ++i)
- propagator.run(i.key(), i.value());
+ for (unsigned i = 0, ei = _tempTypes.size(); i != ei; ++i) {
+ const Temp &temp = _defUses.temp(i);
+ if (temp.kind == Temp::Invalid)
+ continue;
+ const DiscoveredType &tempType = _tempTypes[i];
+ if (tempType.type == UnknownType)
+ continue;
+ propagator.run(temp, tempType);
+ }
+
+ _worklist = 0;
}
private:
@@ -1971,35 +2117,26 @@ private:
return ty;
}
- bool isAlwaysVar(Temp *t) {
- if (unescapableTemp(t, function))
- return false;
- t->type = VarType;
- return true;
- }
-
void setType(Expr *e, DiscoveredType ty) {
if (Temp *t = e->asTemp()) {
-#if defined(SHOW_SSA)
- qout<<"Setting type for "<< (t->scope?"scoped temp ":"temp ") <<t->index<< " to "<<typeName(Type(ty)) << " (" << ty << ")" << endl;
-#endif
- if (isAlwaysVar(t))
- ty = DiscoveredType(VarType);
- TempTypes::iterator it = _tempTypes.find(*t);
- if (it == _tempTypes.end())
- it = _tempTypes.insert(*t, DiscoveredType());
- if (it.value() != ty) {
- it.value() = ty;
-
-#if defined(SHOW_SSA)
- foreach (Stmt *s, _defUses.uses(*t)) {
- qout << "Pushing back dependent stmt: ";
- s->dump(qout);
- qout << endl;
+ if (DebugTypeInference)
+ qout << "Setting type for temp " << t->index
+ << " to " << typeName(Type(ty.type)) << " (" << ty.type << ")"
+ << endl;
+
+ DiscoveredType &it = _tempTypes[t->index];
+ if (it != ty) {
+ it = ty;
+
+ if (DebugTypeInference) {
+ foreach (Stmt *s, _defUses.uses(*t)) {
+ qout << "Pushing back dependent stmt: ";
+ IRPrinter(&qout).print(s);
+ qout<<endl;
+ }
}
-#endif
- _worklist += _defUses.uses(*t);
+ *_worklist += _defUses.uses(*t);
}
} else {
e->type = (Type) ty.type;
@@ -2022,14 +2159,17 @@ protected:
virtual void visitRegExp(IR::RegExp *) { _ty = TypingResult(VarType); }
virtual void visitName(Name *) { _ty = TypingResult(VarType); }
virtual void visitTemp(Temp *e) {
- if (isAlwaysVar(e))
- _ty = TypingResult(VarType);
- else if (e->memberResolver.isValid())
+ if (e->memberResolver.isValid())
_ty = TypingResult(e->memberResolver);
else
- _ty = TypingResult(_tempTypes.value(*e));
+ _ty = TypingResult(_tempTypes[e->index]);
+ setType(e, _ty.type);
+ }
+ virtual void visitArgLocal(ArgLocal *e) {
+ _ty = TypingResult(VarType);
setType(e, _ty.type);
}
+
virtual void visitClosure(Closure *) { _ty = TypingResult(VarType); }
virtual void visitConvert(Convert *e) {
_ty = TypingResult(e->type);
@@ -2201,15 +2341,17 @@ protected:
class ReverseInference
{
- const DefUsesCalculator &_defUses;
+ const DefUses &_defUses;
public:
- ReverseInference(const DefUsesCalculator &defUses)
+ ReverseInference(const DefUses &defUses)
: _defUses(defUses)
{}
void run(IR::Function *f)
{
+ Q_UNUSED(f);
+
QVector<UntypedTemp> knownOk;
QList<UntypedTemp> candidates = _defUses.defsUntyped();
while (!candidates.isEmpty()) {
@@ -2222,7 +2364,7 @@ public:
if (!isUsedAsInt32(temp, knownOk))
continue;
- Stmt *s = _defUses.defStmt(temp);
+ Stmt *s = _defUses.defStmt(temp.temp);
Move *m = s->asMove();
if (!m)
continue;
@@ -2252,13 +2394,13 @@ public:
default:
continue;
}
- if (Temp *lt = unescapableTemp(b->left, f))
+ if (Temp *lt = b->left->asTemp())
candidates.append(*lt);
- if (Temp *rt = unescapableTemp(b->right, f))
+ if (Temp *rt = b->right->asTemp())
candidates.append(*rt);
} else if (Unop *u = m->source->asUnop()) {
if (u->op == OpCompl || u->op == OpUPlus) {
- if (Temp *t = unescapableTemp(u->expr, f))
+ if (Temp *t = u->expr->asTemp())
candidates.append(*t);
}
} else {
@@ -2271,7 +2413,7 @@ public:
PropagateTempTypes propagator(_defUses);
foreach (const UntypedTemp &t, knownOk) {
propagator.run(t, SInt32Type);
- if (Stmt *defStmt = _defUses.defStmt(t)) {
+ if (Stmt *defStmt = _defUses.defStmt(t.temp)) {
if (Move *m = defStmt->asMove()) {
if (Convert *c = m->source->asConvert()) {
c->type = SInt32Type;
@@ -2289,7 +2431,7 @@ public:
private:
bool isUsedAsInt32(const UntypedTemp &t, const QVector<UntypedTemp> &knownOk) const
{
- const QList<Stmt *> &uses = _defUses.uses(t);
+ const QVector<Stmt *> &uses = _defUses.uses(t.temp);
if (uses.isEmpty())
return false;
@@ -2364,7 +2506,7 @@ void convertConst(Const *c, Type targetType)
}
class TypePropagation: public StmtVisitor, public ExprVisitor {
- DefUsesCalculator &_defUses;
+ DefUses &_defUses;
Type _ty;
IR::Function *_f;
@@ -2415,9 +2557,9 @@ class TypePropagation: public StmtVisitor, public ExprVisitor {
}
public:
- TypePropagation(DefUsesCalculator &defUses) : _defUses(defUses), _ty(UnknownType) {}
+ TypePropagation(DefUses &defUses) : _defUses(defUses), _ty(UnknownType) {}
- void run(IR::Function *f) {
+ void run(IR::Function *f, StatementWorklist &worklist) {
_f = f;
foreach (BasicBlock *bb, f->basicBlocks()) {
if (bb->isRemoved())
@@ -2438,13 +2580,35 @@ public:
*conversion.expr = bb->CONVERT(*conversion.expr, conversion.targetType);
} else if (Const *c = (*conversion.expr)->asConst()) {
convertConst(c, conversion.targetType);
+ } else if (ArgLocal *al = (*conversion.expr)->asArgLocal()) {
+ Temp *target = bb->TEMP(bb->newTemp());
+ target->type = conversion.targetType;
+ Expr *convert = bb->CONVERT(al, conversion.targetType);
+ Move *convCall = f->NewStmt<Move>();
+ worklist.registerNewStatement(convCall);
+ convCall->init(target, convert);
+ _defUses.addDef(target, convCall, bb);
+
+ Temp *source = bb->TEMP(target->index);
+ source->type = conversion.targetType;
+ _defUses.addUse(*source, conversion.stmt);
+
+ if (conversion.stmt->asPhi()) {
+ // Only temps can be used as arguments to phi nodes, so this is a sanity check...:
+ Q_UNREACHABLE();
+ } else {
+ bb->insertStatementBefore(conversion.stmt, convCall);
+ }
+
+ *conversion.expr = source;
} else if (Temp *t = (*conversion.expr)->asTemp()) {
Temp *target = bb->TEMP(bb->newTemp());
target->type = conversion.targetType;
Expr *convert = bb->CONVERT(t, conversion.targetType);
- Move *convCall = f->New<Move>();
+ Move *convCall = f->NewStmt<Move>();
+ worklist.registerNewStatement(convCall);
convCall->init(target, convert);
- _defUses.addTemp(target, convCall, bb);
+ _defUses.addDef(target, convCall, bb);
_defUses.addUse(*t, convCall);
Temp *source = bb->TEMP(target->index);
@@ -2469,9 +2633,10 @@ public:
// int32{%2} = int32{convert(double{%3})};
Temp *tmp = bb->TEMP(bb->newTemp());
tmp->type = u->type;
- Move *extraMove = f->New<Move>();
+ Move *extraMove = f->NewStmt<Move>();
+ worklist.registerNewStatement(extraMove);
extraMove->init(tmp, u);
- _defUses.addTemp(tmp, extraMove, bb);
+ _defUses.addDef(tmp, extraMove, bb);
if (Temp *unopOperand = u->expr->asTemp()) {
_defUses.addUse(*unopOperand, extraMove);
@@ -2480,7 +2645,7 @@ public:
bb->insertStatementBefore(conversion.stmt, extraMove);
- *conversion.expr = bb->CONVERT(tmp, conversion.targetType);
+ *conversion.expr = bb->CONVERT(CloneExpr::cloneTemp(tmp, f), conversion.targetType);
_defUses.addUse(*tmp, move);
} else {
Q_UNREACHABLE();
@@ -2504,6 +2669,7 @@ protected:
virtual void visitRegExp(IR::RegExp *) {}
virtual void visitName(Name *) {}
virtual void visitTemp(Temp *) {}
+ virtual void visitArgLocal(ArgLocal *) {}
virtual void visitClosure(Closure *) {}
virtual void visitConvert(Convert *e) { run(e->expr, e->type); }
virtual void visitUnop(Unop *e) { run(e->expr, e->type); }
@@ -2608,7 +2774,7 @@ protected:
}
};
-void splitCriticalEdges(IR::Function *f, DominatorTree &df)
+void splitCriticalEdges(IR::Function *f, DominatorTree &df, StatementWorklist &worklist, DefUses &defUses)
{
foreach (BasicBlock *bb, f->basicBlocks()) {
if (bb->isRemoved())
@@ -2622,11 +2788,11 @@ void splitCriticalEdges(IR::Function *f, DominatorTree &df)
continue;
// We found a critical edge.
- BasicBlock *containingGroup = inBB->isGroupStart() ? inBB : inBB->containingGroup();
-
// create the basic block:
- BasicBlock *newBB = f->newBasicBlock(containingGroup, bb->catchBlock);
- Jump *s = f->New<Jump>();
+ BasicBlock *newBB = f->newBasicBlock(bb->catchBlock);
+ Jump *s = f->NewStmt<Jump>();
+ worklist.registerNewStatement(s);
+ defUses.registerNewStatement(s);
s->init(bb);
newBB->appendStatement(s);
@@ -2663,6 +2829,231 @@ void splitCriticalEdges(IR::Function *f, DominatorTree &df)
}
}
+// Detect all (sub-)loops in a function.
+//
+// Doing loop detection on the CFG is better than relying on the statement information in
+// order to mark loops. Although JavaScript only has natural loops, it can still be the case
+// that something is not a loop even though a loop-like-statement is in the source. For
+// example:
+// while (true) {
+// if (i > 0)
+// break;
+// else
+// break;
+// }
+//
+// Algorithm:
+// - do a DFS on the dominator tree, where for each node:
+// - collect all back-edges
+// - if there are back-edges, the node is a loop-header for a new loop, so:
+// - walk the CFG is reverse-direction, and for every node:
+// - if the node already belongs to a loop, we've found a nested loop:
+// - get the loop-header for the (outermost) nested loop
+// - add that loop-header to the current loop
+// - continue by walking all incoming edges that do not yet belong to the current loop
+// - if the node does not belong to a loop yet, add it to the current loop, and
+// go on with all incoming edges
+//
+// Loop-header detection by checking for back-edges is very straight forward: a back-edge is
+// an incoming edge where the other node is dominated by the current node. Meaning: all
+// execution paths that reach that other node have to go through the current node, that other
+// node ends with a (conditional) jump back to the loop header.
+//
+// The exact order of the DFS on the dominator tree is not important. The only property has to
+// be that a node is only visited when all the nodes it dominates have been visited before.
+// The reason for the DFS is that for nested loops, the inner loop's loop-header is dominated
+// by the outer loop's header. So, by visiting depth-first, sub-loops are identified before
+// their containing loops, which makes nested-loop identification free. An added benefit is
+// that the nodes for those sub-loops are only processed once.
+//
+// Note: independent loops that share the same header are merged together. For example, in
+// the code snippet below, there are 2 back-edges into the loop-header, but only one single
+// loop will be detected.
+// while (a) {
+// if (b)
+// continue;
+// else
+// continue;
+// }
+class LoopDetection
+{
+ enum { DebugLoopDetection = 0 };
+
+ Q_DISABLE_COPY(LoopDetection)
+
+public:
+ struct LoopInfo
+ {
+ BasicBlock *loopHeader;
+ QVector<BasicBlock *> loopBody;
+ QVector<LoopInfo *> nestedLoops;
+ LoopInfo *parentLoop;
+
+ LoopInfo(BasicBlock *loopHeader = 0)
+ : loopHeader(loopHeader)
+ , parentLoop(0)
+ {}
+
+ bool isValid() const
+ { return loopHeader != 0; }
+
+ void addNestedLoop(LoopInfo *nested)
+ {
+ Q_ASSERT(nested);
+ Q_ASSERT(!nestedLoops.contains(nested));
+ Q_ASSERT(nested->parentLoop == 0);
+ nested->parentLoop = this;
+ nestedLoops.append(nested);
+ }
+ };
+
+public:
+ LoopDetection(const DominatorTree &dt)
+ : dt(dt)
+ {}
+
+ ~LoopDetection()
+ {
+ qDeleteAll(loopInfos);
+ }
+
+ void run(IR::Function *function)
+ {
+ std::vector<BasicBlock *> backedges;
+ backedges.reserve(4);
+
+ foreach (BasicBlock *bb, dt.calculateDFNodeIterOrder()) {
+ Q_ASSERT(!bb->isRemoved());
+
+ backedges.clear();
+
+ foreach (BasicBlock *in, bb->in)
+ if (dt.dominates(bb, in))
+ backedges.push_back(in);
+
+ if (!backedges.empty()) {
+ subLoop(bb, backedges);
+ }
+ }
+
+ createLoopInfos(function);
+ dumpLoopInfo();
+ }
+
+ void dumpLoopInfo() const
+ {
+ if (!DebugLoopDetection)
+ return;
+
+ foreach (LoopInfo *info, loopInfos) {
+ qDebug() << "Loop header:" << info->loopHeader->index()
+ << "for loop" << quint64(info);
+ foreach (BasicBlock *bb, info->loopBody)
+ qDebug() << " " << bb->index();
+ foreach (LoopInfo *nested, info->nestedLoops)
+ qDebug() << " sub loop:" << quint64(nested);
+ qDebug() << " parent loop:" << quint64(info->parentLoop);
+ }
+ }
+
+ QVector<LoopInfo *> allLoops() const
+ { return loopInfos; }
+
+ // returns all loop headers for loops that have no nested loops.
+ QVector<LoopInfo *> innermostLoops() const
+ {
+ QVector<LoopInfo *> inner(loopInfos);
+
+ for (int i = 0; i < inner.size(); ) {
+ if (inner.at(i)->nestedLoops.isEmpty())
+ ++i;
+ else
+ inner.remove(i);
+ }
+
+ return inner;
+ }
+
+private:
+ void subLoop(BasicBlock *loopHead, const std::vector<BasicBlock *> &backedges)
+ {
+ loopHead->markAsGroupStart();
+
+ std::vector<BasicBlock *> worklist;
+ worklist.reserve(backedges.size() + 8);
+ worklist.insert(worklist.end(), backedges.begin(), backedges.end());
+ while (!worklist.empty()) {
+ BasicBlock *predIt = worklist.back();
+ worklist.pop_back();
+
+ BasicBlock *subloop = predIt->containingGroup();
+ if (subloop) {
+ // This is a discovered block. Find its outermost discovered loop.
+ while (BasicBlock *parentLoop = subloop->containingGroup())
+ subloop = parentLoop;
+
+ // If it is already discovered to be a subloop of this loop, continue.
+ if (subloop == loopHead)
+ continue;
+
+ // Yay, it's a subloop of this loop.
+ subloop->setContainingGroup(loopHead);
+ predIt = subloop;
+
+ // Add all predecessors of the subloop header to the worklist, as long as
+ // those predecessors are not in the current subloop. It might be the case
+ // that they are in other loops, which we will then add as a subloop to the
+ // current loop.
+ foreach (BasicBlock *predIn, predIt->in)
+ if (predIn->containingGroup() != subloop)
+ worklist.push_back(predIn);
+ } else {
+ if (predIt == loopHead)
+ continue;
+
+ // This is an undiscovered block. Map it to the current loop.
+ predIt->setContainingGroup(loopHead);
+
+ // Add all incoming edges to the worklist.
+ foreach (BasicBlock *bb, predIt->in)
+ worklist.push_back(bb);
+ }
+ }
+ }
+
+private:
+ const DominatorTree &dt;
+ QVector<LoopInfo *> loopInfos;
+
+ void createLoopInfos(IR::Function *function)
+ {
+ foreach (BasicBlock *bb, function->basicBlocks()) {
+ if (bb->isRemoved())
+ continue;
+ if (BasicBlock *loopHeader = bb->containingGroup())
+ findLoop(loopHeader)->loopBody.append(bb);
+ }
+
+ foreach (LoopInfo *info, loopInfos) {
+ if (BasicBlock *containingLoopHeader = info->loopHeader->containingGroup())
+ findLoop(containingLoopHeader)->addNestedLoop(info);
+ }
+ }
+
+ LoopInfo *findLoop(BasicBlock *loopHeader)
+ {
+ foreach (LoopInfo *info, loopInfos) {
+ if (info->loopHeader == loopHeader)
+ return info;
+ }
+
+ LoopInfo *info = new LoopInfo;
+ info->loopHeader = loopHeader;
+ loopInfos.append(info);
+ return info;
+ }
+};
+
// High-level algorithm:
// 0. start with the first node (the start node) of a function
// 1. emit the node
@@ -2931,20 +3322,20 @@ static Expr *clone(Expr *e, IR::Function *function) {
class ExprReplacer: public StmtVisitor, public ExprVisitor
{
- DefUsesCalculator &_defUses;
+ DefUses &_defUses;
IR::Function* _function;
Temp *_toReplace;
Expr *_replacement;
public:
- ExprReplacer(DefUsesCalculator &defUses, IR::Function *function)
+ ExprReplacer(DefUses &defUses, IR::Function *function)
: _defUses(defUses)
, _function(function)
, _toReplace(0)
, _replacement(0)
{}
- void operator()(Temp *toReplace, Expr *replacement, StatementWorklist &W, QList<Stmt *> *newUses = 0)
+ void operator()(Temp *toReplace, Expr *replacement, StatementWorklist &W, QVector<Stmt *> *newUses = 0)
{
Q_ASSERT(replacement->asTemp() || replacement->asConst() || replacement->asName());
@@ -2953,7 +3344,7 @@ public:
qSwap(_toReplace, toReplace);
qSwap(_replacement, replacement);
- const QList<Stmt *> &uses = _defUses.uses(*_toReplace);
+ const QVector<Stmt *> &uses = _defUses.uses(*_toReplace);
if (newUses)
newUses->reserve(uses.size());
@@ -2964,7 +3355,7 @@ public:
// qout<<" -> ";use->dump(qout);qout<<"\n";
W += use;
if (newUses)
- newUses->append(use);
+ newUses->push_back(use);
}
qSwap(_replacement, replacement);
@@ -2977,6 +3368,7 @@ protected:
virtual void visitRegExp(IR::RegExp *) {}
virtual void visitName(Name *) {}
virtual void visitTemp(Temp *) {}
+ virtual void visitArgLocal(ArgLocal *) {}
virtual void visitClosure(Closure *) {}
virtual void visitConvert(Convert *e) { check(e->expr); }
virtual void visitUnop(Unop *e) { check(e->expr); }
@@ -3047,7 +3439,7 @@ namespace {
/// and removes unreachable staements from the worklist, so that optimiseSSA won't consider them
/// anymore.
/// Important: this assumes that there are no critical edges in the control-flow graph!
-void purgeBB(BasicBlock *bb, IR::Function *func, DefUsesCalculator &defUses, StatementWorklist &W,
+void purgeBB(BasicBlock *bb, IR::Function *func, DefUses &defUses, StatementWorklist &W,
DominatorTree &df)
{
// TODO: after the change above: if we keep on detaching the block from predecessors or
@@ -3085,8 +3477,10 @@ void purgeBB(BasicBlock *bb, IR::Function *func, DefUsesCalculator &defUses, Sta
if (!outStmt)
continue;
if (Phi *phi = outStmt->asPhi()) {
- if (Temp *t = phi->d->incoming[idx]->asTemp())
+ if (Temp *t = phi->d->incoming[idx]->asTemp()) {
defUses.removeUse(phi, *t);
+ W += defUses.defStmt(*t);
+ }
phi->d->incoming.remove(idx);
W += phi;
} else
@@ -3180,24 +3574,79 @@ bool tryOptimizingComparison(Expr *&expr)
return false;
}
+
+void cfg2dot(IR::Function *f, const QVector<LoopDetection::LoopInfo *> &loops = QVector<LoopDetection::LoopInfo *>())
+{
+ static bool showCode = !qgetenv("QV4_SHOW_IR").isNull();
+ if (!showCode)
+ return;
+
+ struct Util {
+ static void genLoop(LoopDetection::LoopInfo *loop)
+ {
+ qout << " subgraph \"cluster" << quint64(loop) << "\" {\n";
+ qout << " L" << loop->loopHeader->index() << ";\n";
+ foreach (BasicBlock *bb, loop->loopBody)
+ qout << " L" << bb->index() << ";\n";
+ foreach (LoopDetection::LoopInfo *nested, loop->nestedLoops)
+ genLoop(nested);
+ qout << " }\n";
+ }
+ };
+
+ QString name;
+ if (f->name) name = *f->name;
+ else name = QString::fromLatin1("%1").arg((unsigned long long)f);
+ qout << "digraph \"" << name << "\" { ordering=out;\n";
+
+ foreach (LoopDetection::LoopInfo *l, loops) {
+ if (l->parentLoop == 0)
+ Util::genLoop(l);
+ }
+
+ foreach (BasicBlock *bb, f->basicBlocks()) {
+ if (bb->isRemoved())
+ continue;
+
+ int idx = bb->index();
+ qout << " L" << idx << " [label=\"L" << idx << "\"";
+ if (idx == 0 || bb->terminator()->asRet())
+ qout << ", shape=doublecircle";
+ else
+ qout << ", shape=circle";
+ qout << "];\n";
+ foreach (BasicBlock *out, bb->out)
+ qout << " L" << idx << " -> L" << out->index() << "\n";
+ }
+
+ qout << "}\n" << flush;
+}
+
} // anonymous namespace
-void optimizeSSA(IR::Function *function, DefUsesCalculator &defUses, DominatorTree &df)
+void optimizeSSA(StatementWorklist &W, DefUses &defUses, DominatorTree &df)
{
- StatementWorklist W(function);
+ IR::Function *function = W.function();
ExprReplacer replaceUses(defUses, function);
+ Stmt *s = 0;
while (!W.isEmpty()) {
- Stmt *s = W.takeOne();
- if (!s)
- continue;
+ s = W.takeNext(s);
+ Q_ASSERT(s);
if (Phi *phi = s->asPhi()) {
+ // dead code elimination:
+ if (defUses.useCount(*phi->targetTemp) == 0) {
+ W += defUses.removeDefUses(phi);
+ W.remove(s);
+ continue;
+ }
+
// constant propagation:
if (Const *c = isConstPhi(phi)) {
replaceUses(phi->targetTemp, c, W);
defUses.removeDef(*phi->targetTemp);
- W.clear(s);
+ W.remove(s);
continue;
}
@@ -3206,26 +3655,15 @@ void optimizeSSA(IR::Function *function, DefUsesCalculator &defUses, DominatorTr
Temp *t = phi->targetTemp;
Expr *e = phi->d->incoming.first();
- QList<Stmt *> newT2Uses;
+ QVector<Stmt *> newT2Uses;
replaceUses(t, e, W, &newT2Uses);
if (Temp *t2 = e->asTemp()) {
defUses.removeUse(s, *t2);
defUses.addUses(*t2, newT2Uses);
+ W += defUses.defStmt(*t2);
}
defUses.removeDef(*t);
- W.clear(s);
- continue;
- }
-
- // dead code elimination:
- if (defUses.useCount(*phi->targetTemp) == 0) {
- foreach (Expr *in, phi->d->incoming) {
- if (Temp *t = in->asTemp())
- W += defUses.defStmt(*t);
- }
-
- defUses.removeDef(*phi->targetTemp);
- W.clear(s);
+ W.remove(s);
continue;
}
} else if (Move *m = s->asMove()) {
@@ -3244,12 +3682,12 @@ void optimizeSSA(IR::Function *function, DefUsesCalculator &defUses, DominatorTr
}
}
- if (Temp *targetTemp = unescapableTemp(m->target, function)) {
+ if (Temp *targetTemp = m->target->asTemp()) {
// dead code elimination:
if (defUses.useCount(*targetTemp) == 0) {
- EliminateDeadCode(defUses, W, function).run(m->source, s);
+ EliminateDeadCode(defUses, W).run(m->source, s);
if (!m->source)
- W.clear(s);
+ W.remove(s);
continue;
}
@@ -3257,7 +3695,7 @@ void optimizeSSA(IR::Function *function, DefUsesCalculator &defUses, DominatorTr
if (Const *sourceConst = m->source->asConst()) {
replaceUses(targetTemp, sourceConst, W);
defUses.removeDef(*targetTemp);
- W.clear(s);
+ W.remove(s);
continue;
}
if (Member *member = m->source->asMember()) {
@@ -3267,7 +3705,7 @@ void optimizeSSA(IR::Function *function, DefUsesCalculator &defUses, DominatorTr
c->init(SInt32Type, enumValue);
replaceUses(targetTemp, c, W);
defUses.removeDef(*targetTemp);
- W.clear(s);
+ W.remove(s);
defUses.removeUse(s, *member->base->asTemp());
continue;
} else if (member->attachedPropertiesIdOrEnumValue != 0 && member->property && member->base->asTemp()) {
@@ -3282,13 +3720,13 @@ void optimizeSSA(IR::Function *function, DefUsesCalculator &defUses, DominatorTr
}
// copy propagation:
- if (Temp *sourceTemp = unescapableTemp(m->source, function)) {
- QList<Stmt *> newT2Uses;
+ if (Temp *sourceTemp = m->source->asTemp()) {
+ QVector<Stmt *> newT2Uses;
replaceUses(targetTemp, sourceTemp, W, &newT2Uses);
defUses.removeUse(s, *sourceTemp);
defUses.addUses(*sourceTemp, newT2Uses);
defUses.removeDef(*targetTemp);
- W.clear(s);
+ W.remove(s);
continue;
}
@@ -3451,7 +3889,8 @@ void optimizeSSA(IR::Function *function, DefUsesCalculator &defUses, DominatorTr
if (Const *constantCondition = cjump->cond->asConst()) {
// Note: this assumes that there are no critical edges! Meaning, we can safely purge
// any basic blocks that are found to be unreachable.
- Jump *jump = function->New<Jump>();
+ Jump *jump = function->NewStmt<Jump>();
+ W.registerNewStatement(jump);
if (convertToValue(constantCondition).toBoolean()) {
jump->target = cjump->iftrue;
purgeBB(cjump->iffalse, function, defUses, W, df);
@@ -3473,21 +3912,27 @@ void optimizeSSA(IR::Function *function, DefUsesCalculator &defUses, DominatorTr
}
}
- W.cleanup(function);
+ W.applyToFunction();
}
+//### TODO: use DefUses from the optimizer, because it already has all this information
class InputOutputCollector: protected StmtVisitor, protected ExprVisitor {
- IR::Function *function;
+ void setOutput(Temp *out)
+ {
+ Q_ASSERT(!output);
+ output = out;
+ }
public:
- QList<Temp> inputs;
- QList<Temp> outputs;
+ std::vector<Temp *> inputs;
+ Temp *output;
- InputOutputCollector(IR::Function *f): function(f) {}
+ InputOutputCollector()
+ { inputs.reserve(4); }
void collect(Stmt *s) {
- inputs.clear();
- outputs.clear();
+ inputs.resize(0);
+ output = 0;
s->accept(this);
}
@@ -3497,9 +3942,9 @@ protected:
virtual void visitRegExp(IR::RegExp *) {}
virtual void visitName(Name *) {}
virtual void visitTemp(Temp *e) {
- if (unescapableTemp(e, function))
- inputs.append(*e);
+ inputs.push_back(e);
}
+ virtual void visitArgLocal(ArgLocal *) {}
virtual void visitClosure(Closure *) {}
virtual void visitConvert(Convert *e) { e->expr->accept(this); }
virtual void visitUnop(Unop *e) { e->expr->accept(this); }
@@ -3520,10 +3965,7 @@ protected:
virtual void visitMove(Move *s) {
s->source->accept(this);
if (Temp *t = s->target->asTemp()) {
- if (unescapableTemp(t, function))
- outputs.append(*t);
- else
- s->target->accept(this);
+ setOutput(t);
} else {
s->target->accept(this);
}
@@ -3542,74 +3984,88 @@ protected:
* Linear Scan Register Allocation on SSA Form
* Christian Wimmer & Michael Franz, CGO'10, April 24-28, 2010
*
- * There is one slight difference w.r.t. the phi-nodes: in the artice, the phi nodes are attached
- * to the basic-blocks. Therefore, in the algorithm in the article, the ranges for input parameters
- * for phi nodes run from their definition upto the branch instruction into the block with the phi
- * node. In our representation, phi nodes are mostly treaded as normal instructions, so we have to
- * enlarge the range to cover the phi node itself.
+ * See LifeTimeIntervals::renumber for details on the numbering.
*/
class LifeRanges {
typedef QSet<Temp> LiveRegs;
- QVector<LiveRegs> _liveIn;
- QHash<Temp, LifeTimeInterval> _intervals;
- typedef QVector<LifeTimeInterval> LifeTimeIntervals;
- LifeTimeIntervals _sortedIntervals;
+ std::vector<LiveRegs> _liveIn;
+ std::vector<LifeTimeInterval *> _intervals;
+ LifeTimeIntervals::Ptr _sortedIntervals;
+
+ LifeTimeInterval &interval(const Temp *temp)
+ {
+ LifeTimeInterval *&lti = _intervals[temp->index];
+ if (Q_UNLIKELY(!lti)) {
+ lti = new LifeTimeInterval;
+ lti->setTemp(*temp);
+ }
+ return *lti;
+ }
+
+ int defPosition(IR::Stmt *s) const
+ {
+ return usePosition(s) + 1;
+ }
+
+ int usePosition(IR::Stmt *s) const
+ {
+ return _sortedIntervals->positionForStatement(s);
+ }
+
+ int start(IR::BasicBlock *bb) const
+ {
+ return _sortedIntervals->startPosition(bb);
+ }
+
+ int end(IR::BasicBlock *bb) const
+ {
+ return _sortedIntervals->endPosition(bb);
+ }
public:
LifeRanges(IR::Function *function, const QHash<BasicBlock *, BasicBlock *> &startEndLoops)
+ : _intervals(function->tempCount)
{
+ _sortedIntervals = LifeTimeIntervals::create(function);
_liveIn.resize(function->basicBlockCount());
- int id = 0;
- foreach (BasicBlock *bb, function->basicBlocks()) {
- foreach (Stmt *s, bb->statements()) {
- if (s->asPhi())
- s->id = id + 1;
- else
- s->id = ++id;
- }
- }
-
for (int i = function->basicBlockCount() - 1; i >= 0; --i) {
BasicBlock *bb = function->basicBlock(i);
- buildIntervals(bb, startEndLoops.value(bb, 0), function);
+ buildIntervals(bb, startEndLoops.value(bb, 0));
}
- _sortedIntervals.reserve(_intervals.size());
- for (QHash<Temp, LifeTimeInterval>::const_iterator i = _intervals.begin(), ei = _intervals.end(); i != ei; ++i) {
- LifeTimeIntervals::iterator lti = _sortedIntervals.insert(_sortedIntervals.end(), i.value());
- lti->setTemp(i.key());
- }
- std::sort(_sortedIntervals.begin(), _sortedIntervals.end(), LifeTimeInterval::lessThan);
_intervals.clear();
}
- QVector<LifeTimeInterval> intervals() const { return _sortedIntervals; }
+ LifeTimeIntervals::Ptr intervals() const { return _sortedIntervals; }
void dump() const
{
qout << "Life ranges:" << endl;
qout << "Intervals:" << endl;
- foreach (const LifeTimeInterval &range, _sortedIntervals) {
- range.dump(qout);
+ foreach (const LifeTimeInterval *range, _sortedIntervals->intervals()) {
+ range->dump(qout);
qout << endl;
}
+ IRPrinter printer(&qout);
for (int i = 0, ei = _liveIn.size(); i != ei; ++i) {
qout << "L" << i <<" live-in: ";
QList<Temp> live = QList<Temp>::fromSet(_liveIn.at(i));
+ if (live.isEmpty())
+ qout << "(none)";
std::sort(live.begin(), live.end());
for (int i = 0; i < live.size(); ++i) {
if (i > 0) qout << ", ";
- live[i].dump(qout);
+ printer.print(&live[i]);
}
qout << endl;
}
}
private:
- void buildIntervals(BasicBlock *bb, BasicBlock *loopEnd, IR::Function *function)
+ void buildIntervals(BasicBlock *bb, BasicBlock *loopEnd)
{
LiveRegs live;
foreach (BasicBlock *successor, bb->out) {
@@ -3630,35 +4086,41 @@ private:
QVector<Stmt *> statements = bb->statements();
foreach (const Temp &opd, live)
- _intervals[opd].addRange(statements.first()->id, statements.last()->id);
+ interval(&opd).addRange(start(bb), end(bb));
- InputOutputCollector collector(function);
+ InputOutputCollector collector;
for (int i = statements.size() - 1; i >= 0; --i) {
- Stmt *s = statements[i];
+ Stmt *s = statements.at(i);
if (Phi *phi = s->asPhi()) {
LiveRegs::iterator it = live.find(*phi->targetTemp);
if (it == live.end()) {
// a phi node target that is only defined, but never used
- _intervals[*phi->targetTemp].setFrom(s);
+ interval(phi->targetTemp).setFrom(start(bb));
} else {
live.erase(it);
}
+ _sortedIntervals->add(&interval(phi->targetTemp));
continue;
}
collector.collect(s);
- foreach (const Temp &opd, collector.outputs) {
- _intervals[opd].setFrom(s);
- live.remove(opd);
+ //### TODO: use DefUses from the optimizer, because it already has all this information
+ if (Temp *opd = collector.output) {
+ LifeTimeInterval &lti = interval(opd);
+ lti.setFrom(defPosition(s));
+ live.remove(lti.temp());
+ _sortedIntervals->add(&lti);
}
- foreach (const Temp &opd, collector.inputs) {
- _intervals[opd].addRange(statements.first()->id, s->id);
- live.insert(opd);
+ //### TODO: use DefUses from the optimizer, because it already has all this information
+ for (unsigned i = 0, ei = collector.inputs.size(); i != ei; ++i) {
+ Temp *opd = collector.inputs[i];
+ interval(opd).addRange(start(bb), usePosition(s));
+ live.insert(*opd);
}
}
if (loopEnd) { // Meaning: bb is a loop header, because loopEnd is set to non-null.
foreach (const Temp &opd, live)
- _intervals[opd].addRange(statements.first()->id, loopEnd->terminator()->id);
+ interval(&opd).addRange(start(bb), usePosition(loopEnd->terminator()));
}
_liveIn[bb->index()] = live;
@@ -3675,17 +4137,280 @@ void removeUnreachleBlocks(IR::Function *function)
function->setScheduledBlocks(newSchedule);
function->renumberBasicBlocks();
}
+
+class ConvertArgLocals: protected StmtVisitor, protected ExprVisitor
+{
+public:
+ ConvertArgLocals(IR::Function *function)
+ : function(function)
+ , convertArgs(!function->usesArgumentsObject)
+ {
+ tempForFormal.resize(function->formals.size(), -1);
+ tempForLocal.resize(function->locals.size(), -1);
+ }
+
+ void toTemps()
+ {
+ if (function->variablesCanEscape())
+ return;
+
+ QVector<Stmt *> extraMoves;
+ if (convertArgs) {
+ const int formalCount = function->formals.size();
+ extraMoves.reserve(formalCount + function->basicBlock(0)->statementCount());
+ extraMoves.resize(formalCount);
+
+ for (int i = 0; i != formalCount; ++i) {
+ const int newTemp = function->tempCount++;
+ tempForFormal[i] = newTemp;
+
+ ArgLocal *source = function->New<ArgLocal>();
+ source->init(ArgLocal::Formal, i, 0);
+
+ Temp *target = function->New<Temp>();
+ target->init(Temp::VirtualRegister, newTemp);
+
+ Move *m = function->NewStmt<Move>();
+ m->init(target, source);
+ extraMoves[i] = m;
+ }
+ }
+
+ foreach (BasicBlock *bb, function->basicBlocks())
+ if (!bb->isRemoved())
+ foreach (Stmt *s, bb->statements())
+ s->accept(this);
+
+ if (convertArgs && function->formals.size() > 0)
+ function->basicBlock(0)->prependStatements(extraMoves);
+
+ function->locals.clear();
+ }
+
+protected:
+ virtual void visitConst(Const *) {}
+ virtual void visitString(IR::String *) {}
+ virtual void visitRegExp(IR::RegExp *) {}
+ virtual void visitName(Name *) {}
+ virtual void visitTemp(Temp *) {}
+ virtual void visitArgLocal(ArgLocal *) {}
+ virtual void visitClosure(Closure *) {}
+ virtual void visitConvert(Convert *e) { check(e->expr); }
+ virtual void visitUnop(Unop *e) { check(e->expr); }
+ virtual void visitBinop(Binop *e) { check(e->left); check(e->right); }
+ virtual void visitCall(Call *e) {
+ check(e->base);
+ for (ExprList *it = e->args; it; it = it->next)
+ check(it->expr);
+ }
+ virtual void visitNew(New *e) {
+ check(e->base);
+ for (ExprList *it = e->args; it; it = it->next)
+ check(it->expr);
+ }
+ virtual void visitSubscript(Subscript *e) { check(e->base); check(e->index); }
+ virtual void visitMember(Member *e) { check(e->base); }
+ virtual void visitExp(Exp *s) { check(s->expr); }
+ virtual void visitMove(Move *s) { check(s->target); check(s->source); }
+ virtual void visitJump(Jump *) {}
+ virtual void visitCJump(CJump *s) { check(s->cond); }
+ virtual void visitRet(Ret *s) { check(s->expr); }
+ virtual void visitPhi(Phi *) {
+ Q_UNREACHABLE();
+ }
+
+private:
+ void check(Expr *&e) {
+ if (ArgLocal *al = e->asArgLocal()) {
+ if (al->kind == ArgLocal::Local) {
+ Temp *t = function->New<Temp>();
+ t->init(Temp::VirtualRegister, fetchTempForLocal(al->index));
+ e = t;
+ } else if (convertArgs && al->kind == ArgLocal::Formal) {
+ Temp *t = function->New<Temp>();
+ t->init(Temp::VirtualRegister, fetchTempForFormal(al->index));
+ e = t;
+ }
+ } else {
+ e->accept(this);
+ }
+ }
+
+ int fetchTempForLocal(int local)
+ {
+ int &ref = tempForLocal[local];
+ if (ref == -1)
+ ref = function->tempCount++;
+ return ref;
+ }
+
+ int fetchTempForFormal(int formal)
+ {
+ return tempForFormal[formal];
+ }
+
+ IR::Function *function;
+ bool convertArgs;
+ std::vector<int> tempForFormal;
+ std::vector<int> tempForLocal;
+};
+
+static void verifyCFG(IR::Function *function)
+{
+ if (!DoVerification)
+ return;
+
+ foreach (BasicBlock *bb, function->basicBlocks()) {
+ if (bb->isRemoved()) {
+ Q_ASSERT(bb->in.isEmpty());
+ Q_ASSERT(bb->out.isEmpty());
+ continue;
+ }
+
+ Q_ASSERT(function->basicBlock(bb->index()) == bb);
+
+ // Check the terminators:
+ if (Jump *jump = bb->terminator()->asJump()) {
+ Q_UNUSED(jump);
+ Q_ASSERT(jump->target);
+ Q_ASSERT(!jump->target->isRemoved());
+ Q_ASSERT(bb->out.size() == 1);
+ Q_ASSERT(bb->out.first() == jump->target);
+ } else if (CJump *cjump = bb->terminator()->asCJump()) {
+ Q_UNUSED(cjump);
+ Q_ASSERT(bb->out.size() == 2);
+ Q_ASSERT(cjump->iftrue);
+ Q_ASSERT(!cjump->iftrue->isRemoved());
+ Q_ASSERT(cjump->iftrue == bb->out[0]);
+ Q_ASSERT(cjump->iffalse);
+ Q_ASSERT(!cjump->iffalse->isRemoved());
+ Q_ASSERT(cjump->iffalse == bb->out[1]);
+ } else if (bb->terminator()->asRet()) {
+ Q_ASSERT(bb->out.size() == 0);
+ } else {
+ Q_UNREACHABLE();
+ }
+
+ // Check the outgoing edges:
+ foreach (BasicBlock *out, bb->out) {
+ Q_UNUSED(out);
+ Q_ASSERT(!out->isRemoved());
+ Q_ASSERT(out->in.contains(bb));
+ }
+
+ // Check the incoming edges:
+ foreach (BasicBlock *in, bb->in) {
+ Q_UNUSED(in);
+ Q_ASSERT(!in->isRemoved());
+ Q_ASSERT(in->out.contains(bb));
+ }
+ }
+}
+
+static void verifyImmediateDominators(const DominatorTree &dt, IR::Function *function)
+{
+ if (!DoVerification)
+ return;
+
+ cfg2dot(function);
+ dt.dumpImmediateDominators();
+ DominatorTree referenceTree(function);
+
+ foreach (BasicBlock *bb, function->basicBlocks()) {
+ if (bb->isRemoved())
+ continue;
+
+ BasicBlock *idom = dt.immediateDominator(bb);
+ BasicBlock *referenceIdom = referenceTree.immediateDominator(bb);
+ Q_UNUSED(idom);
+ Q_UNUSED(referenceIdom);
+ Q_ASSERT(idom == referenceIdom);
+ }
+}
+
+static void verifyNoPointerSharing(IR::Function *function)
+{
+ if (!DoVerification)
+ return;
+
+ class : public StmtVisitor, public ExprVisitor {
+ public:
+ void operator()(IR::Function *f)
+ {
+ foreach (BasicBlock *bb, f->basicBlocks()) {
+ if (bb->isRemoved())
+ continue;
+
+ foreach (Stmt *s, bb->statements())
+ s->accept(this);
+ }
+ }
+
+ protected:
+ virtual void visitExp(Exp *s) { check(s); s->expr->accept(this); }
+ virtual void visitMove(Move *s) { check(s); s->target->accept(this); s->source->accept(this); }
+ virtual void visitJump(Jump *s) { check(s); }
+ virtual void visitCJump(CJump *s) { check(s); s->cond->accept(this); }
+ virtual void visitRet(Ret *s) { check(s); s->expr->accept(this); }
+ virtual void visitPhi(Phi *s)
+ {
+ check(s);
+ s->targetTemp->accept(this);
+ foreach (Expr *e, s->d->incoming)
+ e->accept(this);
+ }
+
+ virtual void visitConst(Const *e) { check(e); }
+ virtual void visitString(IR::String *e) { check(e); }
+ virtual void visitRegExp(IR::RegExp *e) { check(e); }
+ virtual void visitName(Name *e) { check(e); }
+ virtual void visitTemp(Temp *e) { check(e); }
+ virtual void visitArgLocal(ArgLocal *e) { check(e); }
+ virtual void visitClosure(Closure *e) { check(e); }
+ virtual void visitConvert(Convert *e) { check(e); e->expr->accept(this); }
+ virtual void visitUnop(Unop *e) { check(e); e->expr->accept(this); }
+ virtual void visitBinop(Binop *e) { check(e); e->left->accept(this); e->right->accept(this); }
+ virtual void visitCall(Call *e) { check(e); e->base->accept(this); check(e->args); }
+ virtual void visitNew(New *e) { check(e); e->base->accept(this); check(e->args); }
+ virtual void visitSubscript(Subscript *e) { check(e); e->base->accept(this); e->index->accept(this); }
+ virtual void visitMember(Member *e) { check(e); e->base->accept(this); }
+
+ void check(ExprList *l)
+ {
+ for (ExprList *it = l; it; it = it->next)
+ check(it->expr);
+ }
+
+ private:
+ void check(Stmt *s)
+ {
+ Q_ASSERT(!stmts.contains(s));
+ stmts.insert(s);
+ }
+
+ void check(Expr *e)
+ {
+ Q_ASSERT(!exprs.contains(e));
+ exprs.insert(e);
+ }
+
+ QSet<Stmt *> stmts;
+ QSet<Expr *> exprs;
+ } V;
+ V(function);
+}
+
} // anonymous namespace
-void LifeTimeInterval::setFrom(Stmt *from) {
- Q_ASSERT(from && from->id > 0);
+void LifeTimeInterval::setFrom(int from) {
+ Q_ASSERT(from > 0);
if (_ranges.isEmpty()) { // this is the case where there is no use, only a define
- _ranges.push_front(Range(from->id, from->id));
- if (_end == Invalid)
- _end = from->id;
+ _ranges.push_front(Range(from, from));
+ if (_end == InvalidPosition)
+ _end = from;
} else {
- _ranges.first().start = from->id;
+ _ranges.first().start = from;
}
}
@@ -3705,7 +4430,7 @@ void LifeTimeInterval::addRange(int from, int to) {
p->start = qMin(p->start, from);
p->end = qMax(p->end, to);
while (_ranges.count() > 1) {
- Range *p1 = &_ranges[1];
+ Range *p1 = p + 1;
if (p->end + 1 < p1->start || p1->end + 1 < p->start)
break;
p1->start = qMin(p->start, p1->start);
@@ -3727,7 +4452,7 @@ void LifeTimeInterval::addRange(int from, int to) {
LifeTimeInterval LifeTimeInterval::split(int atPosition, int newStart)
{
- Q_ASSERT(atPosition < newStart || newStart == Invalid);
+ Q_ASSERT(atPosition < newStart || newStart == InvalidPosition);
if (_ranges.isEmpty() || atPosition < _ranges.first().start)
return LifeTimeInterval();
@@ -3756,7 +4481,7 @@ LifeTimeInterval LifeTimeInterval::split(int atPosition, int newStart)
if (newInterval._ranges.first().end == atPosition)
newInterval._ranges.removeFirst();
- if (newStart == Invalid) {
+ if (newStart == InvalidPosition) {
// the temp stays inactive for the rest of its lifetime
newInterval = LifeTimeInterval();
} else {
@@ -3793,7 +4518,7 @@ LifeTimeInterval LifeTimeInterval::split(int atPosition, int newStart)
}
void LifeTimeInterval::dump(QTextStream &out) const {
- _temp.dump(out);
+ IRPrinter(&out).print(const_cast<Temp *>(&_temp));
out << ": ends at " << _end << " with ranges ";
if (_ranges.isEmpty())
out << "(none)";
@@ -3801,23 +4526,87 @@ void LifeTimeInterval::dump(QTextStream &out) const {
if (i > 0) out << ", ";
out << _ranges[i].start << " - " << _ranges[i].end;
}
- if (_reg != Invalid)
+ if (_reg != InvalidRegister)
out << " (register " << _reg << ")";
}
-bool LifeTimeInterval::lessThan(const LifeTimeInterval &r1, const LifeTimeInterval &r2) {
- if (r1._ranges.first().start == r2._ranges.first().start) {
- if (r1.isSplitFromInterval() == r2.isSplitFromInterval())
- return r1._ranges.last().end < r2._ranges.last().end;
+bool LifeTimeInterval::lessThan(const LifeTimeInterval *r1, const LifeTimeInterval *r2) {
+ if (r1->_ranges.first().start == r2->_ranges.first().start) {
+ if (r1->isSplitFromInterval() == r2->isSplitFromInterval())
+ return r1->_ranges.last().end < r2->_ranges.last().end;
else
- return r1.isSplitFromInterval();
+ return r1->isSplitFromInterval();
} else
- return r1._ranges.first().start < r2._ranges.first().start;
+ return r1->_ranges.first().start < r2->_ranges.first().start;
+}
+
+bool LifeTimeInterval::lessThanForTemp(const LifeTimeInterval *r1, const LifeTimeInterval *r2)
+{
+ return r1->temp() < r2->temp();
+}
+
+LifeTimeIntervals::LifeTimeIntervals(IR::Function *function)
+ : _basicBlockPosition(function->basicBlockCount())
+ , _positionForStatement(function->statementCount(), IR::Stmt::InvalidId)
+ , _lastPosition(0)
+{
+ _intervals.reserve(function->tempCount + 32); // we reserve a bit more space for intervals, because the register allocator will add intervals with fixed ranges for each register.
+ renumber(function);
}
-bool LifeTimeInterval::lessThanForTemp(const LifeTimeInterval &r1, const LifeTimeInterval &r2)
+// Renumbering works as follows:
+// - phi statements are not numbered
+// - statement numbers start at 0 (zero) and increment get an even number (lastPosition + 2)
+// - basic blocks start at firstStatementNumber - 1, or rephrased: lastPosition + 1
+// - basic blocks end at the number of the last statement
+// And during life-time calculation the next rule is used:
+// - any temporary starts its life-time at definingStatementPosition + 1
+//
+// This numbering simulates half-open intervals. For example:
+// 0: %1 = 1
+// 2: %2 = 2
+// 4: %3 = %1 + %2
+// 6: print(%3)
+// Here the half-open life-time intervals would be:
+// %1: (0-4]
+// %2: (2-4]
+// %3: (4-6]
+// Instead, we use the even statement positions for uses of temporaries, and the odd positions for
+// their definitions:
+// %1: [1-4]
+// %2: [3-4]
+// %3: [5-6]
+// This has the nice advantage that placing %3 (for example) is really easy: the start will
+// never overlap with the end of the uses of the operands used in the defining statement.
+//
+// The reason to start a basic-block at firstStatementPosition - 1 is to have correct start
+// positions for target temporaries of phi-nodes. Those temporaries will now start before the
+// first statement. This also means that any moves that get generated when transforming out of SSA
+// form, will not interfere with (read: overlap) any defining statements in the preceding
+// basic-block.
+void LifeTimeIntervals::renumber(IR::Function *function)
{
- return r1.temp() < r2.temp();
+ foreach (BasicBlock *bb, function->basicBlocks()) {
+ if (bb->isRemoved())
+ continue;
+
+ _basicBlockPosition[bb->index()].start = _lastPosition + 1;
+
+ foreach (Stmt *s, bb->statements()) {
+ if (s->asPhi())
+ continue;
+
+ _lastPosition += 2;
+ _positionForStatement[s->id()] = _lastPosition;
+ }
+
+ _basicBlockPosition[bb->index()].end = _lastPosition;
+ }
+}
+
+LifeTimeIntervals::~LifeTimeIntervals()
+{
+ qDeleteAll(_intervals);
}
Optimizer::Optimizer(IR::Function *function)
@@ -3845,22 +4634,31 @@ void Optimizer::run(QQmlEnginePrivate *qmlEngine)
if (!function->hasTry && !function->hasWith && !function->module->debugMode && doSSA) {
// qout << "SSA for " << (function->name ? qPrintable(*function->name) : "<anonymous>") << endl;
+ ConvertArgLocals(function).toTemps();
+ showMeTheCode(function);
+
// Calculate the dominator tree:
DominatorTree df(function);
+ df.computeDF();
+
+ verifyCFG(function);
+ verifyImmediateDominators(df, function);
+
+ DefUses defUses(function);
// qout << "Converting to SSA..." << endl;
- convertToSSA(function, df);
+ convertToSSA(function, df, defUses);
// showMeTheCode(function);
-
-// qout << "Starting def/uses calculation..." << endl;
- DefUsesCalculator defUses(function);
+// defUses.dump();
// qout << "Cleaning up phi nodes..." << endl;
cleanupPhis(defUses);
// showMeTheCode(function);
+ StatementWorklist worklist(function);
+
// qout << "Running type inference..." << endl;
- TypeInference(qmlEngine, defUses).run(function);
+ TypeInference(qmlEngine, defUses).run(worklist);
// showMeTheCode(function);
// qout << "Doing reverse inference..." << endl;
@@ -3868,18 +4666,20 @@ void Optimizer::run(QQmlEnginePrivate *qmlEngine)
// showMeTheCode(function);
// qout << "Doing type propagation..." << endl;
- TypePropagation(defUses).run(function);
+ TypePropagation(defUses).run(function, worklist);
// showMeTheCode(function);
+ verifyNoPointerSharing(function);
// Transform the CFG into edge-split SSA.
// qout << "Starting edge splitting..." << endl;
- splitCriticalEdges(function, df);
+ splitCriticalEdges(function, df, worklist, defUses);
// showMeTheCode(function);
static bool doOpt = qgetenv("QV4_NO_OPT").isEmpty();
if (doOpt) {
// qout << "Running SSA optimization..." << endl;
- optimizeSSA(function, defUses, df);
+ worklist.reset();
+ optimizeSSA(worklist, defUses, df);
// showMeTheCode(function);
}
@@ -3894,6 +4694,9 @@ void Optimizer::run(QQmlEnginePrivate *qmlEngine)
cleanupBasicBlocks(function);
// showMeTheCode(function);
+ LoopDetection(df).run(function);
+ showMeTheCode(function);
+
// qout << "Doing block scheduling..." << endl;
// df.dumpImmediateDominators();
startEndLoops = BlockScheduler(function, df).go();
@@ -3960,7 +4763,7 @@ void Optimizer::convertOutOfSSA() {
}
}
-QVector<LifeTimeInterval> Optimizer::lifeTimeIntervals() const
+LifeTimeIntervals::Ptr Optimizer::lifeTimeIntervals() const
{
Q_ASSERT(isInSSA());
@@ -4021,8 +4824,6 @@ static inline bool overlappingStorage(const Temp &t1, const Temp &t2)
// This is the same as the operator==, but for one detail: memory locations are not sensitive
// to types, and neither are general-purpose registers.
- if (t1.scope != t2.scope)
- return false;
if (t1.index != t2.index)
return false; // different position, where-ever that may (physically) be.
if (t1.kind != t2.kind)
@@ -4103,7 +4904,7 @@ QList<IR::Move *> MoveMapping::insertMoves(BasicBlock *bb, IR::Function *functio
int insertionPoint = atEnd ? bb->statements().size() - 1 : 0;
foreach (const Move &m, _moves) {
- IR::Move *move = function->New<IR::Move>();
+ IR::Move *move = function->NewStmt<IR::Move>();
move->init(clone(m.to, function), clone(m.from, function));
move->swap = m.needsSwap;
bb->insertStatementBefore(insertionPoint++, move);
diff --git a/src/qml/compiler/qv4ssa_p.h b/src/qml/compiler/qv4ssa_p.h
index 372fe5cdeb..8a2241641e 100644
--- a/src/qml/compiler/qv4ssa_p.h
+++ b/src/qml/compiler/qv4ssa_p.h
@@ -43,6 +43,7 @@
#define QV4SSA_P_H
#include "qv4jsir_p.h"
+#include <QtCore/QSharedPointer>
QT_BEGIN_NAMESPACE
class QTextStream;
@@ -57,7 +58,7 @@ public:
int start;
int end;
- Range(int start = Invalid, int end = Invalid)
+ Range(int start = InvalidPosition, int end = InvalidPosition)
: start(start)
, end(end)
{}
@@ -75,22 +76,23 @@ private:
unsigned _isSplitFromInterval : 1;
public:
- enum { Invalid = -1 };
+ enum { InvalidPosition = -1 };
+ enum { InvalidRegister = -1 };
explicit LifeTimeInterval(int rangeCapacity = 2)
- : _end(Invalid)
- , _reg(Invalid)
+ : _end(InvalidPosition)
+ , _reg(InvalidRegister)
, _isFixedInterval(0)
, _isSplitFromInterval(0)
{ _ranges.reserve(rangeCapacity); }
- bool isValid() const { return _end != Invalid; }
+ bool isValid() const { return _end != InvalidRegister; }
void setTemp(const Temp &temp) { this->_temp = temp; }
Temp temp() const { return _temp; }
bool isFP() const { return _temp.type == IR::DoubleType; }
- void setFrom(Stmt *from);
+ void setFrom(int from);
void addRange(int from, int to);
const Ranges &ranges() const { return _ranges; }
@@ -98,15 +100,13 @@ public:
int end() const { return _end; }
bool covers(int position) const
{
- foreach (const Range &r, _ranges) {
- if (r.covers(position))
+ for (int i = 0, ei = _ranges.size(); i != ei; ++i) {
+ if (_ranges.at(i).covers(position))
return true;
}
return false;
}
- int firstPossibleUsePosition(bool isPhiTarget) const { return start() + (isSplitFromInterval() || isPhiTarget ? 0 : 1); }
-
int reg() const { return _reg; }
void setReg(int reg) { Q_ASSERT(!_isFixedInterval); _reg = reg; }
@@ -118,13 +118,13 @@ public:
void setSplitFromInterval(bool isSplitFromInterval) { _isSplitFromInterval = isSplitFromInterval; }
void dump(QTextStream &out) const;
- static bool lessThan(const LifeTimeInterval &r1, const LifeTimeInterval &r2);
- static bool lessThanForTemp(const LifeTimeInterval &r1, const LifeTimeInterval &r2);
+ static bool lessThan(const LifeTimeInterval *r1, const LifeTimeInterval *r2);
+ static bool lessThanForTemp(const LifeTimeInterval *r1, const LifeTimeInterval *r2);
void validate() const {
#if !defined(QT_NO_DEBUG)
// Validate the new range
- if (_end != Invalid) {
+ if (_end != InvalidPosition) {
Q_ASSERT(!_ranges.isEmpty());
foreach (const Range &range, _ranges) {
Q_ASSERT(range.start >= 0);
@@ -136,6 +136,78 @@ public:
}
};
+class LifeTimeIntervals
+{
+ Q_DISABLE_COPY(LifeTimeIntervals)
+
+ LifeTimeIntervals(IR::Function *function);
+ void renumber(IR::Function *function);
+
+public:
+ typedef QSharedPointer<LifeTimeIntervals> Ptr;
+ static Ptr create(IR::Function *function)
+ { return Ptr(new LifeTimeIntervals(function)); }
+
+ ~LifeTimeIntervals();
+
+ // takes ownership of the pointer
+ void add(LifeTimeInterval *interval)
+ { _intervals.append(interval); }
+
+ // After calling Optimizer::lifeTimeIntervals() the result will have all intervals in descending order of start position.
+ QVector<LifeTimeInterval *> intervals() const
+ { return _intervals; }
+
+ int size() const
+ { return _intervals.size(); }
+
+ int positionForStatement(Stmt *stmt) const
+ {
+ Q_ASSERT(stmt->id() >= 0);
+ if (static_cast<unsigned>(stmt->id()) < _positionForStatement.size())
+ return _positionForStatement[stmt->id()];
+
+ return Stmt::InvalidId;
+ }
+
+ int startPosition(BasicBlock *bb) const
+ {
+ Q_ASSERT(bb->index() >= 0);
+ Q_ASSERT(static_cast<unsigned>(bb->index()) < _basicBlockPosition.size());
+
+ return _basicBlockPosition.at(bb->index()).start;
+ }
+
+ int endPosition(BasicBlock *bb) const
+ {
+ Q_ASSERT(bb->index() >= 0);
+ Q_ASSERT(static_cast<unsigned>(bb->index()) < _basicBlockPosition.size());
+
+ return _basicBlockPosition.at(bb->index()).end;
+ }
+
+ int lastPosition() const
+ {
+ return _lastPosition;
+ }
+
+private:
+ struct BasicBlockPositions {
+ int start;
+ int end;
+
+ BasicBlockPositions()
+ : start(IR::Stmt::InvalidId)
+ , end(IR::Stmt::InvalidId)
+ {}
+ };
+
+ std::vector<BasicBlockPositions> _basicBlockPosition;
+ std::vector<int> _positionForStatement;
+ QVector<LifeTimeInterval *> _intervals;
+ int _lastPosition;
+};
+
class Q_QML_PRIVATE_EXPORT Optimizer
{
Q_DISABLE_COPY(Optimizer)
@@ -151,7 +223,7 @@ public:
QHash<BasicBlock *, BasicBlock *> loopStartEndBlocks() const { return startEndLoops; }
- QVector<LifeTimeInterval> lifeTimeIntervals() const;
+ LifeTimeIntervals::Ptr lifeTimeIntervals() const;
QSet<IR::Jump *> calculateOptionalJumps();
diff --git a/src/qml/debugger/qqmlprofilerdefinitions_p.h b/src/qml/debugger/qqmlprofilerdefinitions_p.h
index 9452260ce4..689a06a0d1 100644
--- a/src/qml/debugger/qqmlprofilerdefinitions_p.h
+++ b/src/qml/debugger/qqmlprofilerdefinitions_p.h
@@ -67,6 +67,7 @@ struct QQmlProfilerDefinitions {
Complete, // end of transmission
PixmapCacheEvent,
SceneGraphFrame,
+ MemoryAllocation,
MaximumMessage
};
@@ -122,7 +123,7 @@ struct QQmlProfilerDefinitions {
SceneGraphPolishAndSync,
SceneGraphWindowsRenderShow,
SceneGraphWindowsAnimations,
- SceneGraphWindowsPolishFrame,
+ SceneGraphPolishFrame,
MaximumSceneGraphFrameType
};
diff --git a/src/qml/debugger/qv4profileradapter.cpp b/src/qml/debugger/qv4profileradapter.cpp
index e7b82566d6..cdceb0e533 100644
--- a/src/qml/debugger/qv4profileradapter.cpp
+++ b/src/qml/debugger/qv4profileradapter.cpp
@@ -58,26 +58,47 @@ QV4ProfilerAdapter::QV4ProfilerAdapter(QQmlProfilerService *service, QV4::Execut
connect(this, SIGNAL(dataRequested()), engine->profiler, SLOT(reportData()));
connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)),
engine->profiler, SLOT(setTimer(QElapsedTimer)));
- connect(engine->profiler, SIGNAL(dataReady(QList<QV4::Profiling::FunctionCallProperties>)),
- this, SLOT(receiveData(QList<QV4::Profiling::FunctionCallProperties>)));
+ connect(engine->profiler, SIGNAL(dataReady(QList<QV4::Profiling::FunctionCallProperties>,
+ QList<QV4::Profiling::MemoryAllocationProperties>)),
+ this, SLOT(receiveData(QList<QV4::Profiling::FunctionCallProperties>,
+ QList<QV4::Profiling::MemoryAllocationProperties>)));
}
+qint64 QV4ProfilerAdapter::appendMemoryEvents(qint64 until, QList<QByteArray> &messages)
+{
+ QByteArray message;
+ while (!memory_data.empty() && memory_data.front().timestamp <= until) {
+ QQmlDebugStream d(&message, QIODevice::WriteOnly);
+ QV4::Profiling::MemoryAllocationProperties &props = memory_data.front();
+ d << props.timestamp << MemoryAllocation << props.type << props.size;
+ memory_data.pop_front();
+ messages.append(message);
+ }
+ return memory_data.empty() ? -1 : memory_data.front().timestamp;
+}
qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages)
{
QByteArray message;
while (true) {
while (!stack.empty() && (data.empty() || stack.top() <= data.front().start)) {
- if (stack.top() > until)
- return stack.top();
+ if (stack.top() > until) {
+ qint64 memory_next = appendMemoryEvents(until, messages);
+ return memory_next == -1 ? stack.top() : qMin(stack.top(), memory_next);
+ }
+ appendMemoryEvents(stack.top(), messages);
QQmlDebugStream d(&message, QIODevice::WriteOnly);
d << stack.pop() << RangeEnd << Javascript;
messages.append(message);
}
while (!data.empty() && (stack.empty() || data.front().start < stack.top())) {
- if (data.front().start > until)
- return data.front().start;
const QV4::Profiling::FunctionCallProperties &props = data.front();
+ if (props.start > until) {
+ qint64 memory_next = appendMemoryEvents(until, messages);
+ return memory_next == -1 ? props.start : qMin(props.start, memory_next);
+ }
+ appendMemoryEvents(props.start, messages);
+
QQmlDebugStream d_start(&message, QIODevice::WriteOnly);
d_start << props.start << RangeStart << Javascript;
messages.push_back(message);
@@ -95,13 +116,15 @@ qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &message
data.pop_front();
}
if (stack.empty() && data.empty())
- return -1;
+ return appendMemoryEvents(until, messages);
}
}
-void QV4ProfilerAdapter::receiveData(const QList<QV4::Profiling::FunctionCallProperties> &new_data)
+void QV4ProfilerAdapter::receiveData(const QList<QV4::Profiling::FunctionCallProperties> &new_data,
+ const QList<QV4::Profiling::MemoryAllocationProperties> &new_memory_data)
{
data = new_data;
+ memory_data = new_memory_data;
stack.clear();
service->dataReady(this);
}
diff --git a/src/qml/debugger/qv4profileradapter_p.h b/src/qml/debugger/qv4profileradapter_p.h
index 922aedd828..29bdd606ef 100644
--- a/src/qml/debugger/qv4profileradapter_p.h
+++ b/src/qml/debugger/qv4profileradapter_p.h
@@ -71,11 +71,14 @@ public:
virtual qint64 sendMessages(qint64 until, QList<QByteArray> &messages);
public slots:
- void receiveData(const QList<QV4::Profiling::FunctionCallProperties> &);
+ void receiveData(const QList<QV4::Profiling::FunctionCallProperties> &,
+ const QList<QV4::Profiling::MemoryAllocationProperties> &);
private:
QList<QV4::Profiling::FunctionCallProperties> data;
+ QList<QV4::Profiling::MemoryAllocationProperties> memory_data;
QStack<qint64> stack;
+ qint64 appendMemoryEvents(qint64 until, QList<QByteArray> &messages);
};
QT_END_NAMESPACE
diff --git a/src/qml/doc/qtqml.qdocconf b/src/qml/doc/qtqml.qdocconf
index d691dbfd8a..418a330d2c 100644
--- a/src/qml/doc/qtqml.qdocconf
+++ b/src/qml/doc/qtqml.qdocconf
@@ -28,7 +28,7 @@ qhp.QtQml.subprojects.examples.indexTitle = Qt Quick Examples and Tutorials
qhp.QtQml.subprojects.examples.selectors = fake:example
qhp.QtQml.subprojects.qmltypes.title = QML Types
qhp.QtQml.subprojects.qmltypes.indexTitle = Qt QML QML Types
-qhp.QtQml.subprojects.qmltypes.selectors = fake:qmlclass
+qhp.QtQml.subprojects.qmltypes.selectors = qmlclass
qhp.QtQml.subprojects.qmltypes.sortPages = true
diff --git a/src/qml/doc/src/qmlfunctions.qdoc b/src/qml/doc/src/qmlfunctions.qdoc
index d3d3174193..e95784dc5c 100644
--- a/src/qml/doc/src/qmlfunctions.qdoc
+++ b/src/qml/doc/src/qmlfunctions.qdoc
@@ -157,6 +157,44 @@
*/
/*!
+ \fn int qmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString& message)
+ \relates QQmlEgine
+
+ This template function registers the C++ type and its extension
+ in the QML system with the name \a qmlName in the library imported
+ from \a uri having version number composed from \a versionMajor and
+ \a versionMinor.
+
+ While the type has a name and a type, it cannot be created, and the
+ given error \a message will result if creation is attempted.
+
+ This is useful where the type is only intended for providing attached
+ properties, enum values or an abstract base class with its extension.
+
+ Returns the QML type id.
+
+ #include <QtQml> to use this function.
+
+ \sa qmlRegisterUncreatableType()
+*/
+
+/*!
+ \fn int qmlRegisterCustomExtendedType(const char *uri, int versionMajor, int versionMinor, const char *qmlName, QQmlCustomParser *parser)
+ \relates QQmlEgine
+
+ This template function registers the C++ type and its extension
+ in the QML system with the name \a qmlName in the library imported
+ from \a uri having version number composed from \a versionMajor and
+ \a versionMinor. Properties from the C++ type or its extension that
+ cannot be resolved directly by the QML system will be resolved using
+ the \a parser provided.
+
+ Returns the QML type id.
+
+ #include <QtQml> to use this function.
+*/
+
+/*!
\fn int qmlRegisterTypeNotAvailable(const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString& message)
\relates QQmlEngine
diff --git a/src/qml/jit/jit.pri b/src/qml/jit/jit.pri
index 151ff32df9..7ea4e951d5 100644
--- a/src/qml/jit/jit.pri
+++ b/src/qml/jit/jit.pri
@@ -6,9 +6,11 @@ INCLUDEPATH += $$OUT_PWD
HEADERS += \
$$PWD/qv4assembler_p.h \
$$PWD/qv4regalloc_p.h \
+ $$PWD/qv4targetplatform_p.h \
$$PWD/qv4isel_masm_p.h \
$$PWD/qv4binop_p.h \
$$PWD/qv4unop_p.h \
+ $$PWD/qv4registerinfo_p.h
SOURCES += \
$$PWD/qv4assembler.cpp \
diff --git a/src/qml/jit/qv4assembler.cpp b/src/qml/jit/qv4assembler.cpp
index cd44b537df..cb2279b336 100644
--- a/src/qml/jit/qv4assembler.cpp
+++ b/src/qml/jit/qv4assembler.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtQml module of the Qt Toolkit.
@@ -91,58 +91,6 @@ QV4::ExecutableAllocator::ChunkOfPages *CompilationUnit::chunkForFunction(int fu
return handle->chunk();
}
-
-
-/* Platform/Calling convention/Architecture specific section */
-
-#if CPU(X86_64)
-# if OS(LINUX) || OS(MAC_OS_X)
-static const Assembler::RegisterID calleeSavedRegisters[] = {
- JSC::X86Registers::ebx,
- JSC::X86Registers::r12, // LocalsRegister
- JSC::X86Registers::r13,
- JSC::X86Registers::r14, // ContextRegister
- JSC::X86Registers::r15
-};
-# elif OS(WINDOWS)
-static const Assembler::RegisterID calleeSavedRegisters[] = {
- JSC::X86Registers::ebx,
- JSC::X86Registers::esi,
- JSC::X86Registers::edi,
- JSC::X86Registers::r12, // LocalsRegister
- JSC::X86Registers::r13,
- JSC::X86Registers::r14, // ContextRegister
- JSC::X86Registers::r15
-};
-# endif
-#endif
-
-#if CPU(X86)
-static const Assembler::RegisterID calleeSavedRegisters[] = {
- JSC::X86Registers::ebx, // temporary register
- JSC::X86Registers::esi, // ContextRegister
- JSC::X86Registers::edi // LocalsRegister
-};
-#endif
-
-#if CPU(ARM)
-static const Assembler::RegisterID calleeSavedRegisters[] = {
- JSC::ARMRegisters::r11,
- JSC::ARMRegisters::r10,
- JSC::ARMRegisters::r9,
- JSC::ARMRegisters::r8,
- JSC::ARMRegisters::r7,
- JSC::ARMRegisters::r6,
- JSC::ARMRegisters::r5,
- JSC::ARMRegisters::r4
-};
-#endif
-
-const int Assembler::calleeSavedRegisterCount = sizeof(calleeSavedRegisters) / sizeof(calleeSavedRegisters[0]);
-
-/* End of platform/calling convention/architecture specific section */
-
-
const Assembler::VoidType Assembler::Void;
Assembler::Assembler(InstructionSelection *isel, IR::Function* function, QV4::ExecutableAllocator *executableAllocator,
@@ -223,33 +171,47 @@ void Assembler::generateCJumpOnCompare(RelationalCondition cond, RegisterID left
}
}
-Assembler::Pointer Assembler::loadTempAddress(RegisterID baseReg, IR::Temp *t)
+Assembler::Pointer Assembler::loadAddress(RegisterID tmp, IR::Expr *e)
+{
+ IR::Temp *t = e->asTemp();
+ if (t)
+ return loadTempAddress(t);
+ else
+ return loadArgLocalAddress(tmp, e->asArgLocal());
+}
+
+Assembler::Pointer Assembler::loadTempAddress(IR::Temp *t)
+{
+ if (t->kind == IR::Temp::StackSlot)
+ return stackSlotPointer(t);
+ else
+ Q_UNREACHABLE();
+}
+
+Assembler::Pointer Assembler::loadArgLocalAddress(RegisterID baseReg, IR::ArgLocal *al)
{
int32_t offset = 0;
- int scope = t->scope;
+ int scope = al->scope;
RegisterID context = ContextRegister;
if (scope) {
- loadPtr(Address(ContextRegister, qOffsetOf(ExecutionContext, outer)), baseReg);
+ loadPtr(Address(ContextRegister, qOffsetOf(ExecutionContext::Data, outer)), baseReg);
--scope;
context = baseReg;
while (scope) {
- loadPtr(Address(context, qOffsetOf(ExecutionContext, outer)), context);
+ loadPtr(Address(context, qOffsetOf(ExecutionContext::Data, outer)), context);
--scope;
}
}
- switch (t->kind) {
- case IR::Temp::Formal:
- case IR::Temp::ScopedFormal: {
- loadPtr(Address(context, qOffsetOf(ExecutionContext, callData)), baseReg);
- offset = sizeof(CallData) + (t->index - 1) * sizeof(Value);
+ switch (al->kind) {
+ case IR::ArgLocal::Formal:
+ case IR::ArgLocal::ScopedFormal: {
+ loadPtr(Address(context, qOffsetOf(ExecutionContext::Data, callData)), baseReg);
+ offset = sizeof(CallData) + (al->index - 1) * sizeof(Value);
} break;
- case IR::Temp::Local:
- case IR::Temp::ScopedLocal: {
- loadPtr(Address(context, qOffsetOf(CallContext, locals)), baseReg);
- offset = t->index * sizeof(Value);
- } break;
- case IR::Temp::StackSlot: {
- return stackSlotPointer(t);
+ case IR::ArgLocal::Local:
+ case IR::ArgLocal::ScopedLocal: {
+ loadPtr(Address(context, qOffsetOf(CallContext::Data, locals)), baseReg);
+ offset = al->index * sizeof(Value);
} break;
default:
Q_UNREACHABLE();
@@ -259,7 +221,7 @@ Assembler::Pointer Assembler::loadTempAddress(RegisterID baseReg, IR::Temp *t)
Assembler::Pointer Assembler::loadStringAddress(RegisterID reg, const QString &string)
{
- loadPtr(Address(Assembler::ContextRegister, qOffsetOf(QV4::ExecutionContext, compilationUnit)), Assembler::ScratchRegister);
+ loadPtr(Address(Assembler::ContextRegister, qOffsetOf(QV4::ExecutionContext::Data, compilationUnit)), Assembler::ScratchRegister);
loadPtr(Address(Assembler::ScratchRegister, qOffsetOf(QV4::CompiledData::CompilationUnit, runtimeStrings)), reg);
const int id = _isel->registerString(string);
return Pointer(reg, id * sizeof(QV4::StringValue));
@@ -267,21 +229,21 @@ Assembler::Pointer Assembler::loadStringAddress(RegisterID reg, const QString &s
void Assembler::loadStringRef(RegisterID reg, const QString &string)
{
- loadPtr(Address(Assembler::ContextRegister, qOffsetOf(QV4::ExecutionContext, compilationUnit)), reg);
+ loadPtr(Address(Assembler::ContextRegister, qOffsetOf(QV4::ExecutionContext::Data, compilationUnit)), reg);
loadPtr(Address(reg, qOffsetOf(QV4::CompiledData::CompilationUnit, runtimeStrings)), reg);
const int id = _isel->registerString(string);
- addPtr(TrustedImmPtr(id * sizeof(QV4::StringValue)), reg);
+ loadPtr(Address(reg, id * sizeof(QV4::StringValue)), reg);
}
-void Assembler::storeValue(QV4::Primitive value, IR::Temp* destination)
+void Assembler::storeValue(QV4::Primitive value, IR::Expr *destination)
{
- Address addr = loadTempAddress(ScratchRegister, destination);
+ Address addr = loadAddress(ScratchRegister, destination);
storeValue(value, addr);
}
void Assembler::enterStandardStackFrame()
{
- platformEnterStandardStackFrame();
+ platformEnterStandardStackFrame(this);
// ### FIXME: Handle through calleeSavedRegisters mechanism
// or eliminate StackFrameRegister altogether.
@@ -292,16 +254,18 @@ void Assembler::enterStandardStackFrame()
subPtr(TrustedImm32(frameSize), StackPointerRegister);
- for (int i = 0; i < calleeSavedRegisterCount; ++i)
- storePtr(calleeSavedRegisters[i], Address(StackFrameRegister, -(i + 1) * sizeof(void*)));
+ const RegisterInformation &calleeSavedRegisters = getCalleeSavedRegisters();
+ for (int i = 0; i < calleeSavedRegisterCount(); ++i)
+ storePtr(calleeSavedRegisters[i].reg<RegisterID>(), Address(StackFrameRegister, -(i + 1) * sizeof(void*)));
}
void Assembler::leaveStandardStackFrame()
{
// restore the callee saved registers
- for (int i = calleeSavedRegisterCount - 1; i >= 0; --i)
- loadPtr(Address(StackFrameRegister, -(i + 1) * sizeof(void*)), calleeSavedRegisters[i]);
+ const RegisterInformation &calleeSavedRegisters = getCalleeSavedRegisters();
+ for (int i = calleeSavedRegisterCount() - 1; i >= 0; --i)
+ loadPtr(Address(StackFrameRegister, -(i + 1) * sizeof(void*)), calleeSavedRegisters[i].reg<RegisterID>());
int frameSize = _stackLayout.calculateStackFrameSize();
// Work around bug in ARMv7Assembler.h where add32(imm, sp, sp) doesn't
@@ -314,7 +278,7 @@ void Assembler::leaveStandardStackFrame()
#endif
pop(StackFrameRegister);
- platformLeaveStandardStackFrame();
+ platformLeaveStandardStackFrame(this);
}
@@ -347,13 +311,12 @@ Assembler::Jump Assembler::genTryDoubleConversion(IR::Expr *src, Assembler::FPRe
break;
}
- IR::Temp *sourceTemp = src->asTemp();
- Q_ASSERT(sourceTemp);
+ Q_ASSERT(src->asTemp() || src->asArgLocal());
// It's not a number type, so it cannot be in a register.
- Q_ASSERT(sourceTemp->kind != IR::Temp::PhysicalRegister || sourceTemp->type == IR::BoolType);
+ Q_ASSERT(src->asArgLocal() || src->asTemp()->kind != IR::Temp::PhysicalRegister || src->type == IR::BoolType);
- Assembler::Pointer tagAddr = loadTempAddress(Assembler::ScratchRegister, sourceTemp);
+ Assembler::Pointer tagAddr = loadAddress(Assembler::ScratchRegister, src);
tagAddr.offset += 4;
load32(tagAddr, Assembler::ScratchRegister);
diff --git a/src/qml/jit/qv4assembler_p.h b/src/qml/jit/qv4assembler_p.h
index 6fde517e1f..5e1f162f39 100644
--- a/src/qml/jit/qv4assembler_p.h
+++ b/src/qml/jit/qv4assembler_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtQml module of the Qt Toolkit.
@@ -47,6 +47,7 @@
#include "private/qv4isel_util_p.h"
#include "private/qv4value_p.h"
#include "private/qv4lookup_p.h"
+#include "qv4targetplatform_p.h"
#include <QtCore/QHash>
#include <QtCore/QStack>
@@ -123,158 +124,12 @@ struct ExceptionCheck<void (*)(QV4::NoThrowContext *, A, B, C)> {
enum { NeedsCheck = 0 };
};
-class Assembler : public JSC::MacroAssembler
+class Assembler : public JSC::MacroAssembler, public TargetPlatform
{
public:
Assembler(InstructionSelection *isel, IR::Function* function, QV4::ExecutableAllocator *executableAllocator,
int maxArgCountForBuiltins);
-#if CPU(X86)
-
-#undef VALUE_FITS_IN_REGISTER
-#undef ARGUMENTS_IN_REGISTERS
-
-#define HAVE_ALU_OPS_WITH_MEM_OPERAND 1
-
- static const RegisterID StackFrameRegister = JSC::X86Registers::ebp;
- static const RegisterID StackPointerRegister = JSC::X86Registers::esp;
- static const RegisterID LocalsRegister = JSC::X86Registers::edi;
- static const RegisterID ContextRegister = JSC::X86Registers::esi;
- static const RegisterID ReturnValueRegister = JSC::X86Registers::eax;
- static const RegisterID ScratchRegister = JSC::X86Registers::ecx;
- static const FPRegisterID FPGpr0 = JSC::X86Registers::xmm0;
- static const FPRegisterID FPGpr1 = JSC::X86Registers::xmm1;
-
- static const int RegisterSize = 4;
-
- static const int RegisterArgumentCount = 0;
- static RegisterID registerForArgument(int)
- {
- Q_ASSERT(false);
- // Not reached.
- return JSC::X86Registers::eax;
- }
-
- // Return address is pushed onto stack by the CPU.
- static const int StackSpaceAllocatedUponFunctionEntry = RegisterSize;
- static const int StackShadowSpace = 0;
- inline void platformEnterStandardStackFrame() {}
- inline void platformLeaveStandardStackFrame() {}
-#elif CPU(X86_64)
-
-#define VALUE_FITS_IN_REGISTER
-#define ARGUMENTS_IN_REGISTERS
-#define HAVE_ALU_OPS_WITH_MEM_OPERAND 1
-
- static const RegisterID StackFrameRegister = JSC::X86Registers::ebp;
- static const RegisterID StackPointerRegister = JSC::X86Registers::esp;
- static const RegisterID LocalsRegister = JSC::X86Registers::r12;
- static const RegisterID ContextRegister = JSC::X86Registers::r14;
- static const RegisterID ReturnValueRegister = JSC::X86Registers::eax;
- static const RegisterID ScratchRegister = JSC::X86Registers::r10;
- static const FPRegisterID FPGpr0 = JSC::X86Registers::xmm0;
- static const FPRegisterID FPGpr1 = JSC::X86Registers::xmm1;
-
- static const int RegisterSize = 8;
-
-#if OS(WINDOWS)
- static const int RegisterArgumentCount = 4;
- static RegisterID registerForArgument(int index)
- {
- static RegisterID regs[RegisterArgumentCount] = {
- JSC::X86Registers::ecx,
- JSC::X86Registers::edx,
- JSC::X86Registers::r8,
- JSC::X86Registers::r9
- };
- Q_ASSERT(index >= 0 && index < RegisterArgumentCount);
- return regs[index];
- };
- static const int StackShadowSpace = 32;
-#else // Unix
- static const int RegisterArgumentCount = 6;
- static RegisterID registerForArgument(int index)
- {
- static RegisterID regs[RegisterArgumentCount] = {
- JSC::X86Registers::edi,
- JSC::X86Registers::esi,
- JSC::X86Registers::edx,
- JSC::X86Registers::ecx,
- JSC::X86Registers::r8,
- JSC::X86Registers::r9
- };
- Q_ASSERT(index >= 0 && index < RegisterArgumentCount);
- return regs[index];
- };
- static const int StackShadowSpace = 0;
-#endif
-
- // Return address is pushed onto stack by the CPU.
- static const int StackSpaceAllocatedUponFunctionEntry = RegisterSize;
- inline void platformEnterStandardStackFrame() {}
- inline void platformLeaveStandardStackFrame() {}
-#elif CPU(ARM)
-
-#undef VALUE_FITS_IN_REGISTER
-#define ARGUMENTS_IN_REGISTERS
-#undef HAVE_ALU_OPS_WITH_MEM_OPERAND
-
- static const RegisterID StackPointerRegister = JSC::ARMRegisters::sp; // r13
- static const RegisterID StackFrameRegister = JSC::ARMRegisters::fp; // r11
- static const RegisterID LocalsRegister = JSC::ARMRegisters::r7;
- static const RegisterID ScratchRegister = JSC::ARMRegisters::r6;
- static const RegisterID ContextRegister = JSC::ARMRegisters::r5;
- static const RegisterID ReturnValueRegister = JSC::ARMRegisters::r0;
- static const FPRegisterID FPGpr0 = JSC::ARMRegisters::d0;
- static const FPRegisterID FPGpr1 = JSC::ARMRegisters::d1;
-
- static const int RegisterSize = 4;
-
- static const RegisterID RegisterArgument1 = JSC::ARMRegisters::r0;
- static const RegisterID RegisterArgument2 = JSC::ARMRegisters::r1;
- static const RegisterID RegisterArgument3 = JSC::ARMRegisters::r2;
- static const RegisterID RegisterArgument4 = JSC::ARMRegisters::r3;
-
- static const int RegisterArgumentCount = 4;
- static RegisterID registerForArgument(int index)
- {
- Q_ASSERT(index >= 0 && index < RegisterArgumentCount);
- return static_cast<RegisterID>(JSC::ARMRegisters::r0 + index);
- };
-
- // Registers saved in platformEnterStandardStackFrame below.
- static const int StackSpaceAllocatedUponFunctionEntry = 5 * RegisterSize;
- static const int StackShadowSpace = 0;
- inline void platformEnterStandardStackFrame()
- {
- // Move the register arguments onto the stack as if they were
- // pushed by the caller, just like on ia32. This gives us consistent
- // access to the parameters if we need to.
- push(JSC::ARMRegisters::r3);
- push(JSC::ARMRegisters::r2);
- push(JSC::ARMRegisters::r1);
- push(JSC::ARMRegisters::r0);
- push(JSC::ARMRegisters::lr);
- }
- inline void platformLeaveStandardStackFrame()
- {
- pop(JSC::ARMRegisters::lr);
- addPtr(TrustedImm32(4 * RegisterSize), StackPointerRegister);
- }
-#else
-#error The JIT needs to be ported to this platform.
-#endif
- static const int calleeSavedRegisterCount;
-
-#if CPU(X86) || CPU(X86_64)
- static const int StackAlignment = 16;
-#elif CPU(ARM)
- // Per AAPCS
- static const int StackAlignment = 8;
-#else
-#error Stack alignment unknown for this platform.
-#endif
-
// Explicit type to allow distinguishing between
// pushing an address itself or the value it points
// to onto the stack when calling functions.
@@ -318,7 +173,7 @@ public:
{
public:
StackLayout(IR::Function *function, int maxArgCountForBuiltins)
- : calleeSavedRegCount(Assembler::calleeSavedRegisterCount + 1)
+ : calleeSavedRegCount(Assembler::calleeSavedRegisterCount() + 1)
, maxOutgoingArgumentCount(function->maxNumberOfArguments)
, localCount(function->tempCount)
, savedRegCount(maxArgCountForBuiltins)
@@ -351,7 +206,7 @@ public:
+ RegisterSize; // saved StackFrameRegister
// space for the callee saved registers
- int frameSize = RegisterSize * calleeSavedRegisterCount;
+ int frameSize = RegisterSize * calleeSavedRegisterCount();
frameSize += savedRegCount * sizeof(QV4::Value); // these get written out as Values, not as native registers
Q_ASSERT(frameSize + stackSpaceAllocatedOtherwise < INT_MAX);
@@ -460,8 +315,10 @@ public:
QString string;
};
struct Reference {
- Reference(IR::Temp *value) : value(value) {}
- IR::Temp *value;
+ Reference(IR::Expr *value) : value(value) {
+ Q_ASSERT(value->asTemp() || value->asArgLocal());
+ }
+ IR::Expr *value;
};
struct ReentryBlock {
@@ -504,13 +361,14 @@ public:
Jump genTryDoubleConversion(IR::Expr *src, Assembler::FPRegisterID dest);
Assembler::Jump branchDouble(bool invertCondition, IR::AluOp op, IR::Expr *left, IR::Expr *right);
- Pointer loadTempAddress(RegisterID baseReg, IR::Temp *t);
+ Pointer loadAddress(RegisterID tmp, IR::Expr *t);
+ Pointer loadTempAddress(IR::Temp *t);
+ Pointer loadArgLocalAddress(RegisterID baseReg, IR::ArgLocal *al);
Pointer loadStringAddress(RegisterID reg, const QString &string);
void loadStringRef(RegisterID reg, const QString &string);
Pointer stackSlotPointer(IR::Temp *t) const
{
Q_ASSERT(t->kind == IR::Temp::StackSlot);
- Q_ASSERT(t->scope == 0);
return Pointer(_stackLayout.stackSlotPointer(t->index));
}
@@ -585,7 +443,7 @@ public:
void loadArgumentInRegister(Reference temp, RegisterID dest, int argumentNumber)
{
Q_ASSERT(temp.value);
- Pointer addr = loadTempAddress(dest, temp.value);
+ Pointer addr = loadAddress(dest, temp.value);
loadArgumentInRegister(addr, dest, argumentNumber);
}
@@ -603,12 +461,25 @@ public:
{
Q_UNUSED(argumentNumber);
- if (!temp) {
+ if (temp) {
+ Pointer addr = loadTempAddress(temp);
+ load64(addr, dest);
+ } else {
QV4::Value undefined = QV4::Primitive::undefinedValue();
move(TrustedImm64(undefined.val), dest);
- } else {
- Pointer addr = loadTempAddress(dest, temp);
+ }
+ }
+
+ void loadArgumentInRegister(IR::ArgLocal* al, RegisterID dest, int argumentNumber)
+ {
+ Q_UNUSED(argumentNumber);
+
+ if (al) {
+ Pointer addr = loadArgLocalAddress(dest, al);
load64(addr, dest);
+ } else {
+ QV4::Value undefined = QV4::Primitive::undefinedValue();
+ move(TrustedImm64(undefined.val), dest);
}
}
@@ -627,10 +498,12 @@ public:
if (!expr) {
QV4::Value undefined = QV4::Primitive::undefinedValue();
move(TrustedImm64(undefined.val), dest);
- } else if (expr->asTemp()){
- loadArgumentInRegister(expr->asTemp(), dest, argumentNumber);
- } else if (expr->asConst()) {
- loadArgumentInRegister(expr->asConst(), dest, argumentNumber);
+ } else if (IR::Temp *t = expr->asTemp()){
+ loadArgumentInRegister(t, dest, argumentNumber);
+ } else if (IR::ArgLocal *al = expr->asArgLocal()) {
+ loadArgumentInRegister(al, dest, argumentNumber);
+ } else if (IR::Const *c = expr->asConst()) {
+ loadArgumentInRegister(c, dest, argumentNumber);
} else {
Q_ASSERT(!"unimplemented expression type in loadArgument");
}
@@ -704,20 +577,26 @@ public:
}
#endif
- void storeReturnValue(IR::Temp *temp)
+ void storeReturnValue(IR::Expr *target)
{
- if (!temp)
+ if (!target)
return;
- if (temp->kind == IR::Temp::PhysicalRegister) {
- if (temp->type == IR::DoubleType)
- storeReturnValue((FPRegisterID) temp->index);
- else if (temp->type == IR::UInt32Type)
- storeUInt32ReturnValue((RegisterID) temp->index);
- else
- storeReturnValue((RegisterID) temp->index);
- } else {
- Pointer addr = loadTempAddress(ScratchRegister, temp);
+ if (IR::Temp *temp = target->asTemp()) {
+ if (temp->kind == IR::Temp::PhysicalRegister) {
+ if (temp->type == IR::DoubleType)
+ storeReturnValue((FPRegisterID) temp->index);
+ else if (temp->type == IR::UInt32Type)
+ storeUInt32ReturnValue((RegisterID) temp->index);
+ else
+ storeReturnValue((RegisterID) temp->index);
+ return;
+ } else {
+ Pointer addr = loadTempAddress(temp);
+ storeReturnValue(addr);
+ }
+ } else if (IR::ArgLocal *al = target->asArgLocal()) {
+ Pointer addr = loadArgLocalAddress(ScratchRegister, al);
storeReturnValue(addr);
}
}
@@ -775,7 +654,7 @@ public:
{
Q_ASSERT (temp.value);
- Pointer ptr = loadTempAddress(ScratchRegister, temp.value);
+ Pointer ptr = loadAddress(ScratchRegister, temp.value);
loadArgumentOnStack<StackSlot>(ptr, argumentNumber);
}
@@ -807,30 +686,32 @@ public:
poke(TrustedImmPtr(name), StackSlot);
}
- void loadDouble(IR::Temp* temp, FPRegisterID dest)
+ void loadDouble(IR::Expr *source, FPRegisterID dest)
{
- if (temp->kind == IR::Temp::PhysicalRegister) {
- moveDouble((FPRegisterID) temp->index, dest);
+ IR::Temp *sourceTemp = source->asTemp();
+ if (sourceTemp && sourceTemp->kind == IR::Temp::PhysicalRegister) {
+ moveDouble((FPRegisterID) sourceTemp->index, dest);
return;
}
- Pointer ptr = loadTempAddress(ScratchRegister, temp);
+ Pointer ptr = loadAddress(ScratchRegister, source);
loadDouble(ptr, dest);
}
- void storeDouble(FPRegisterID source, IR::Temp* temp)
+ void storeDouble(FPRegisterID source, IR::Expr* target)
{
- if (temp->kind == IR::Temp::PhysicalRegister) {
- moveDouble(source, (FPRegisterID) temp->index);
+ IR::Temp *targetTemp = target->asTemp();
+ if (targetTemp && targetTemp->kind == IR::Temp::PhysicalRegister) {
+ moveDouble(source, (FPRegisterID) targetTemp->index);
return;
}
#if QT_POINTER_SIZE == 8
moveDoubleTo64(source, ReturnValueRegister);
move(TrustedImm64(QV4::Value::NaNEncodeMask), ScratchRegister);
xor64(ScratchRegister, ReturnValueRegister);
- Pointer ptr = loadTempAddress(ScratchRegister, temp);
+ Pointer ptr = loadAddress(ScratchRegister, target);
store64(ReturnValueRegister, ptr);
#else
- Pointer ptr = loadTempAddress(ScratchRegister, temp);
+ Pointer ptr = loadAddress(ScratchRegister, target);
storeDouble(source, ptr);
#endif
}
@@ -862,11 +743,11 @@ public:
void copyValue(Result result, IR::Expr* source);
// The scratch register is used to calculate the temp address for the source.
- void memcopyValue(Pointer target, IR::Temp *sourceTemp, RegisterID scratchRegister)
+ void memcopyValue(Pointer target, IR::Expr *source, RegisterID scratchRegister)
{
- Q_ASSERT(sourceTemp->kind != IR::Temp::PhysicalRegister);
+ Q_ASSERT(!source->asTemp() || source->asTemp()->kind != IR::Temp::PhysicalRegister);
Q_ASSERT(target.base != scratchRegister);
- JSC::MacroAssembler::loadDouble(loadTempAddress(scratchRegister, sourceTemp), FPGpr0);
+ JSC::MacroAssembler::loadDouble(loadAddress(scratchRegister, source), FPGpr0);
JSC::MacroAssembler::storeDouble(FPGpr0, target);
}
@@ -888,13 +769,13 @@ public:
#endif
}
- void storeValue(QV4::Primitive value, IR::Temp* temp);
+ void storeValue(QV4::Primitive value, IR::Expr* temp);
void enterStandardStackFrame();
void leaveStandardStackFrame();
void checkException() {
- loadPtr(Address(ContextRegister, qOffsetOf(QV4::ExecutionContext, engine)), ScratchRegister);
+ loadPtr(Address(ContextRegister, qOffsetOf(QV4::ExecutionContext::Data, engine)), ScratchRegister);
load32(Address(ScratchRegister, qOffsetOf(QV4::ExecutionEngine, hasException)), ScratchRegister);
Jump exceptionThrown = branch32(NotEqual, ScratchRegister, TrustedImm32(0));
if (catchBlock)
@@ -988,10 +869,8 @@ public:
prepareRelativeCall(function, this);
loadArgumentOnStackOrRegister<0>(arg1);
-#if (OS(LINUX) && CPU(X86) && (defined(__PIC__) || defined(__PIE__))) || \
- (OS(WINDOWS) && CPU(X86))
- load32(Address(StackFrameRegister, -int(sizeof(void*))),
- JSC::X86Registers::ebx); // restore the GOT ptr
+#ifdef RESTORE_EBX_ON_CALL
+ load32(ebxAddressOnStack(), JSC::X86Registers::ebx); // restore the GOT ptr
#endif
callAbsolute(functionName, function);
@@ -1050,13 +929,11 @@ public:
return Pointer(addr);
}
- IR::Temp *t = e->asTemp();
- Q_ASSERT(t);
- if (t->kind != IR::Temp::PhysicalRegister)
- return loadTempAddress(tmpReg, t);
-
+ if (IR::Temp *t = e->asTemp())
+ if (t->kind == IR::Temp::PhysicalRegister)
+ return Pointer(_stackLayout.savedRegPointer(offset));
- return Pointer(_stackLayout.savedRegPointer(offset));
+ return loadAddress(tmpReg, e);
}
void storeBool(RegisterID reg, Pointer addr)
@@ -1071,24 +948,31 @@ public:
move(src, dest);
}
- void storeBool(RegisterID reg, IR::Temp *target)
+ void storeBool(RegisterID reg, IR::Expr *target)
{
- if (target->kind == IR::Temp::PhysicalRegister) {
- move(reg, (RegisterID) target->index);
- } else {
- Pointer addr = loadTempAddress(ScratchRegister, target);
- storeBool(reg, addr);
+ if (IR::Temp *targetTemp = target->asTemp()) {
+ if (targetTemp->kind == IR::Temp::PhysicalRegister) {
+ move(reg, (RegisterID) targetTemp->index);
+ return;
+ }
}
+
+ Pointer addr = loadAddress(ScratchRegister, target);
+ storeBool(reg, addr);
}
- void storeBool(bool value, IR::Temp *target) {
+ void storeBool(bool value, IR::Expr *target) {
TrustedImm32 trustedValue(value ? 1 : 0);
- if (target->kind == IR::Temp::PhysicalRegister) {
- move(trustedValue, (RegisterID) target->index);
- } else {
- move(trustedValue, ScratchRegister);
- storeBool(ScratchRegister, target);
+
+ if (IR::Temp *targetTemp = target->asTemp()) {
+ if (targetTemp->kind == IR::Temp::PhysicalRegister) {
+ move(trustedValue, (RegisterID) targetTemp->index);
+ return;
+ }
}
+
+ move(trustedValue, ScratchRegister);
+ storeBool(ScratchRegister, target);
}
void storeInt32(RegisterID src, RegisterID dest)
@@ -1103,12 +987,17 @@ public:
store32(TrustedImm32(QV4::Primitive::fromInt32(0).tag), addr);
}
- void storeInt32(RegisterID reg, IR::Temp *target)
+ void storeInt32(RegisterID reg, IR::Expr *target)
{
- if (target->kind == IR::Temp::PhysicalRegister) {
- move(reg, (RegisterID) target->index);
- } else {
- Pointer addr = loadTempAddress(ScratchRegister, target);
+ if (IR::Temp *targetTemp = target->asTemp()) {
+ if (targetTemp->kind == IR::Temp::PhysicalRegister) {
+ move(reg, (RegisterID) targetTemp->index);
+ } else {
+ Pointer addr = loadTempAddress(targetTemp);
+ storeInt32(reg, addr);
+ }
+ } else if (IR::ArgLocal *al = target->asArgLocal()) {
+ Pointer addr = loadArgLocalAddress(ScratchRegister, al);
storeInt32(reg, addr);
}
}
@@ -1130,12 +1019,13 @@ public:
done.link(this);
}
- void storeUInt32(RegisterID reg, IR::Temp *target)
+ void storeUInt32(RegisterID reg, IR::Expr *target)
{
- if (target->kind == IR::Temp::PhysicalRegister) {
- move(reg, (RegisterID) target->index);
+ IR::Temp *targetTemp = target->asTemp();
+ if (targetTemp && targetTemp->kind == IR::Temp::PhysicalRegister) {
+ move(reg, (RegisterID) targetTemp->index);
} else {
- Pointer addr = loadTempAddress(ScratchRegister, target);
+ Pointer addr = loadAddress(ScratchRegister, target);
storeUInt32(reg, addr);
}
}
@@ -1157,12 +1047,11 @@ public:
return target;
}
- IR::Temp *t = e->asTemp();
- Q_ASSERT(t);
- if (t->kind == IR::Temp::PhysicalRegister)
- return (FPRegisterID) t->index;
+ if (IR::Temp *t = e->asTemp())
+ if (t->kind == IR::Temp::PhysicalRegister)
+ return (FPRegisterID) t->index;
- loadDouble(t, target);
+ loadDouble(e, target);
return target;
}
@@ -1178,12 +1067,11 @@ public:
return scratchReg;
}
- IR::Temp *t = e->asTemp();
- Q_ASSERT(t);
- if (t->kind == IR::Temp::PhysicalRegister)
- return (RegisterID) t->index;
+ if (IR::Temp *t = e->asTemp())
+ if (t->kind == IR::Temp::PhysicalRegister)
+ return (RegisterID) t->index;
- return toInt32Register(loadTempAddress(scratchReg, t), scratchReg);
+ return toInt32Register(loadAddress(scratchReg, e), scratchReg);
}
RegisterID toInt32Register(Pointer addr, RegisterID scratchReg)
@@ -1199,12 +1087,11 @@ public:
return scratchReg;
}
- IR::Temp *t = e->asTemp();
- Q_ASSERT(t);
- if (t->kind == IR::Temp::PhysicalRegister)
- return (RegisterID) t->index;
+ if (IR::Temp *t = e->asTemp())
+ if (t->kind == IR::Temp::PhysicalRegister)
+ return (RegisterID) t->index;
- return toUInt32Register(loadTempAddress(scratchReg, t), scratchReg);
+ return toUInt32Register(loadAddress(scratchReg, e), scratchReg);
}
RegisterID toUInt32Register(Pointer addr, RegisterID scratchReg)
@@ -1291,17 +1178,15 @@ void Assembler::copyValue(Result result, IR::Expr* source)
storeUInt32(reg, result);
} else if (source->type == IR::DoubleType) {
storeDouble(toDoubleRegister(source), result);
- } else if (IR::Temp *temp = source->asTemp()) {
+ } else if (source->asTemp() || source->asArgLocal()) {
#ifdef VALUE_FITS_IN_REGISTER
- Q_UNUSED(temp);
-
- // Use ReturnValueRegister as "scratch" register because loadArgument
- // and storeArgument are functions that may need a scratch register themselves.
- loadArgumentInRegister(source, ReturnValueRegister, 0);
- storeReturnValue(result);
+ // Use ReturnValueRegister as "scratch" register because loadArgument
+ // and storeArgument are functions that may need a scratch register themselves.
+ loadArgumentInRegister(source, ReturnValueRegister, 0);
+ storeReturnValue(result);
#else
- loadDouble(temp, FPGpr0);
- storeDouble(FPGpr0, result);
+ loadDouble(source, FPGpr0);
+ storeDouble(FPGpr0, result);
#endif
} else if (IR::Const *c = source->asConst()) {
QV4::Primitive v = convertToValue(c);
@@ -1316,7 +1201,7 @@ void Assembler::copyValue(Result result, IR::Expr* source)
template <typename T> inline void prepareRelativeCall(const T &, Assembler *){}
template <> inline void prepareRelativeCall(const RelativeCall &relativeCall, Assembler *as)
{
- as->loadPtr(Assembler::Address(Assembler::ContextRegister, qOffsetOf(QV4::ExecutionContext, lookups)),
+ as->loadPtr(Assembler::Address(Assembler::ContextRegister, qOffsetOf(QV4::ExecutionContext::Data, lookups)),
relativeCall.addr.base);
}
diff --git a/src/qml/jit/qv4binop.cpp b/src/qml/jit/qv4binop.cpp
index 344bbf56e0..a19072f52e 100644
--- a/src/qml/jit/qv4binop.cpp
+++ b/src/qml/jit/qv4binop.cpp
@@ -112,7 +112,7 @@ const Binop::OpInfo Binop::operations[IR::LastAluOp + 1] = {
-void Binop::generate(IR::Expr *lhs, IR::Expr *rhs, IR::Temp *target)
+void Binop::generate(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target)
{
if (op != IR::OpMod
&& lhs->type == IR::DoubleType && rhs->type == IR::DoubleType
@@ -156,14 +156,15 @@ void Binop::generate(IR::Expr *lhs, IR::Expr *rhs, IR::Temp *target)
}
-void Binop::doubleBinop(IR::Expr *lhs, IR::Expr *rhs, IR::Temp *target)
+void Binop::doubleBinop(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target)
{
Q_ASSERT(lhs->asConst() == 0 || rhs->asConst() == 0);
Q_ASSERT(isPregOrConst(lhs));
Q_ASSERT(isPregOrConst(rhs));
+ IR::Temp *targetTemp = target->asTemp();
Assembler::FPRegisterID targetReg;
- if (target->kind == IR::Temp::PhysicalRegister)
- targetReg = (Assembler::FPRegisterID) target->index;
+ if (targetTemp && targetTemp->kind == IR::Temp::PhysicalRegister)
+ targetReg = (Assembler::FPRegisterID) targetTemp->index;
else
targetReg = Assembler::FPGpr0;
@@ -232,31 +233,33 @@ void Binop::doubleBinop(IR::Expr *lhs, IR::Expr *rhs, IR::Temp *target)
} return;
}
- if (target->kind != IR::Temp::PhysicalRegister)
+ if (!targetTemp || targetTemp->kind != IR::Temp::PhysicalRegister)
as->storeDouble(Assembler::FPGpr0, target);
}
-bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target)
+bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *target)
{
Q_ASSERT(leftSource->type == IR::SInt32Type);
+ IR::Temp *targetTemp = target->asTemp();
Assembler::RegisterID targetReg = Assembler::ReturnValueRegister;
- if (target->kind == IR::Temp::PhysicalRegister) {
+ if (targetTemp && targetTemp->kind == IR::Temp::PhysicalRegister) {
// We try to load leftSource into the target's register, but we can't do that if
// the target register is the same as rightSource.
IR::Temp *rhs = rightSource->asTemp();
- if (!rhs || rhs->kind != IR::Temp::PhysicalRegister || rhs->index != target->index)
- targetReg = (Assembler::RegisterID) target->index;
+ if (!rhs || rhs->kind != IR::Temp::PhysicalRegister || rhs->index != targetTemp->index)
+ targetReg = (Assembler::RegisterID) targetTemp->index;
}
switch (op) {
case IR::OpBitAnd: {
Q_ASSERT(rightSource->type == IR::SInt32Type);
if (rightSource->asTemp() && rightSource->asTemp()->kind == IR::Temp::PhysicalRegister
- && target->kind == IR::Temp::PhysicalRegister
- && target->index == rightSource->asTemp()->index) {
+ && targetTemp
+ && targetTemp->kind == IR::Temp::PhysicalRegister
+ && targetTemp->index == rightSource->asTemp()->index) {
as->and32(as->toInt32Register(leftSource, Assembler::ScratchRegister),
- (Assembler::RegisterID) target->index);
+ (Assembler::RegisterID) targetTemp->index);
return true;
}
@@ -268,10 +271,11 @@ bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *ta
case IR::OpBitOr: {
Q_ASSERT(rightSource->type == IR::SInt32Type);
if (rightSource->asTemp() && rightSource->asTemp()->kind == IR::Temp::PhysicalRegister
- && target->kind == IR::Temp::PhysicalRegister
- && target->index == rightSource->asTemp()->index) {
+ && targetTemp
+ && targetTemp->kind == IR::Temp::PhysicalRegister
+ && targetTemp->index == rightSource->asTemp()->index) {
as->or32(as->toInt32Register(leftSource, Assembler::ScratchRegister),
- (Assembler::RegisterID) target->index);
+ (Assembler::RegisterID) targetTemp->index);
return true;
}
@@ -283,10 +287,11 @@ bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *ta
case IR::OpBitXor: {
Q_ASSERT(rightSource->type == IR::SInt32Type);
if (rightSource->asTemp() && rightSource->asTemp()->kind == IR::Temp::PhysicalRegister
- && target->kind == IR::Temp::PhysicalRegister
- && target->index == rightSource->asTemp()->index) {
+ && targetTemp
+ && targetTemp->kind == IR::Temp::PhysicalRegister
+ && targetTemp->index == rightSource->asTemp()->index) {
as->xor32(as->toInt32Register(leftSource, Assembler::ScratchRegister),
- (Assembler::RegisterID) target->index);
+ (Assembler::RegisterID) targetTemp->index);
return true;
}
@@ -370,9 +375,10 @@ bool Binop::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *ta
Q_ASSERT(rightSource->type == IR::SInt32Type);
if (rightSource->asTemp() && rightSource->asTemp()->kind == IR::Temp::PhysicalRegister
- && target->kind == IR::Temp::PhysicalRegister
- && target->index == rightSource->asTemp()->index) {
- Assembler::RegisterID targetReg = (Assembler::RegisterID) target->index;
+ && targetTemp
+ && targetTemp->kind == IR::Temp::PhysicalRegister
+ && targetTemp->index == rightSource->asTemp()->index) {
+ Assembler::RegisterID targetReg = (Assembler::RegisterID) targetTemp->index;
as->move(targetReg, Assembler::ScratchRegister);
as->move(as->toInt32Register(leftSource, targetReg), targetReg);
as->sub32(Assembler::ScratchRegister, targetReg);
@@ -407,7 +413,7 @@ static inline Assembler::FPRegisterID getFreeFPReg(IR::Expr *shouldNotOverlap, u
return Assembler::FPRegisterID(hint);
}
-Assembler::Jump Binop::genInlineBinop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target)
+Assembler::Jump Binop::genInlineBinop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *target)
{
Assembler::Jump done;
diff --git a/src/qml/jit/qv4binop_p.h b/src/qml/jit/qv4binop_p.h
index a6292e6fb5..8c7fa4337a 100644
--- a/src/qml/jit/qv4binop_p.h
+++ b/src/qml/jit/qv4binop_p.h
@@ -58,10 +58,10 @@ struct Binop {
, op(operation)
{}
- void generate(IR::Expr *lhs, IR::Expr *rhs, IR::Temp *target);
- void doubleBinop(IR::Expr *lhs, IR::Expr *rhs, IR::Temp *target);
- bool int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target);
- Assembler::Jump genInlineBinop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target);
+ void generate(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target);
+ void doubleBinop(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target);
+ bool int32Binop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *target);
+ Assembler::Jump genInlineBinop(IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *target);
typedef Assembler::Jump (Binop::*MemRegOp)(Assembler::Address, Assembler::RegisterID);
typedef Assembler::Jump (Binop::*ImmRegOp)(Assembler::TrustedImm32, Assembler::RegisterID);
diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp
index 17e2730669..353a29425d 100644
--- a/src/qml/jit/qv4isel_masm.cpp
+++ b/src/qml/jit/qv4isel_masm.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtQml module of the Qt Toolkit.
@@ -203,9 +203,9 @@ InstructionSelection::InstructionSelection(QQmlEnginePrivate *qmlEngine, QV4::Ex
: EvalInstructionSelection(execAllocator, module, jsGenerator)
, _block(0)
, _as(0)
+ , compilationUnit(new CompilationUnit)
, qmlEngine(qmlEngine)
{
- compilationUnit = new CompilationUnit;
compilationUnit->codeRefs.resize(module->functions.size());
}
@@ -214,90 +214,6 @@ InstructionSelection::~InstructionSelection()
delete _as;
}
-#if (CPU(X86_64) && (OS(MAC_OS_X) || OS(LINUX))) || (CPU(X86) && OS(LINUX))
-# define REGALLOC_IS_SUPPORTED
-static QVector<int> getIntRegisters()
-{
-# if CPU(X86) && OS(LINUX) // x86 with linux
- static const QVector<int> intRegisters = QVector<int>()
- << JSC::X86Registers::edx
- << JSC::X86Registers::ebx;
-# else // x86_64 with linux or with macos
- static const QVector<int> intRegisters = QVector<int>()
- << JSC::X86Registers::ebx
- << JSC::X86Registers::edi
- << JSC::X86Registers::esi
- << JSC::X86Registers::edx
- << JSC::X86Registers::r9
- << JSC::X86Registers::r8
- << JSC::X86Registers::r13
- << JSC::X86Registers::r15;
-# endif
- return intRegisters;
-}
-
-static QVector<int> getFpRegisters()
-{
-// linux/x86_64, linux/x86, and macos/x86_64:
- static const QVector<int> fpRegisters = QVector<int>()
- << JSC::X86Registers::xmm2
- << JSC::X86Registers::xmm3
- << JSC::X86Registers::xmm4
- << JSC::X86Registers::xmm5
- << JSC::X86Registers::xmm6
- << JSC::X86Registers::xmm7;
- return fpRegisters;
-}
-
-#elif CPU(ARM) && OS(LINUX)
- // Note: this is not generic for all ARM platforms. Specifically, r9 is platform dependent
- // (e.g. iOS reserves it). See the ARM GNU Linux abi for details.
-# define REGALLOC_IS_SUPPORTED
-static QVector<int> getIntRegisters()
-{
- static const QVector<int> intRegisters = QVector<int>()
- << JSC::ARMRegisters::r1
- << JSC::ARMRegisters::r2
- << JSC::ARMRegisters::r3
- << JSC::ARMRegisters::r4
- << JSC::ARMRegisters::r8
- << JSC::ARMRegisters::r9;
- return intRegisters;
-}
-
-static QVector<int> getFpRegisters()
-{
- static const QVector<int> fpRegisters = QVector<int>()
- << JSC::ARMRegisters::d2
- << JSC::ARMRegisters::d3
- << JSC::ARMRegisters::d4
- << JSC::ARMRegisters::d5
- << JSC::ARMRegisters::d6;
- return fpRegisters;
-}
-#elif CPU(X86) && OS(WINDOWS)
-# define REGALLOC_IS_SUPPORTED
-static QVector<int> getIntRegisters()
-{
- static const QVector<int> intRegisters = QVector<int>()
- << JSC::X86Registers::edx
- << JSC::X86Registers::ebx;
- return intRegisters;
-}
-
-static QVector<int> getFpRegisters()
-{
- static const QVector<int> fpRegisters = QVector<int>()
- << JSC::X86Registers::xmm2
- << JSC::X86Registers::xmm3
- << JSC::X86Registers::xmm4
- << JSC::X86Registers::xmm5
- << JSC::X86Registers::xmm6
- << JSC::X86Registers::xmm7;
- return fpRegisters;
-}
-#endif
-
void InstructionSelection::run(int functionIndex)
{
IR::Function *function = irModule->functions[functionIndex];
@@ -307,19 +223,16 @@ void InstructionSelection::run(int functionIndex)
IR::Optimizer opt(_function);
opt.run(qmlEngine);
-#ifdef REGALLOC_IS_SUPPORTED
static const bool withRegisterAllocator = qgetenv("QV4_NO_REGALLOC").isEmpty();
- if (opt.isInSSA() && withRegisterAllocator) {
- RegisterAllocator(getIntRegisters(), getFpRegisters()).run(_function, opt);
- } else
-#endif // REGALLOC_IS_SUPPORTED
- {
+ if (Assembler::RegAllocIsSupported && opt.isInSSA() && withRegisterAllocator) {
+ RegisterAllocator(Assembler::getRegisterInfo()).run(_function, opt);
+ } else {
if (opt.isInSSA())
// No register allocator available for this platform, or env. var was set, so:
opt.convertOutOfSSA();
ConvertTemps().toStackSlots(_function);
+ IR::Optimizer::showMeTheCode(_function);
}
- IR::Optimizer::showMeTheCode(_function);
QSet<IR::Jump *> removableJumps = opt.calculateOptionalJumps();
qSwap(_removableJumps, removableJumps);
@@ -335,7 +248,7 @@ void InstructionSelection::run(int functionIndex)
#endif
const int locals = _as->stackLayout().calculateJSStackFrameSize();
- _as->loadPtr(Address(Assembler::ContextRegister, qOffsetOf(ExecutionContext, engine)), Assembler::ScratchRegister);
+ _as->loadPtr(Address(Assembler::ContextRegister, qOffsetOf(ExecutionContext::Data, engine)), Assembler::ScratchRegister);
_as->loadPtr(Address(Assembler::ScratchRegister, qOffsetOf(ExecutionEngine, jsStackTop)), Assembler::LocalsRegister);
_as->addPtr(Assembler::TrustedImm32(sizeof(QV4::Value)*locals), Assembler::LocalsRegister);
_as->storePtr(Assembler::LocalsRegister, Address(Assembler::ScratchRegister, qOffsetOf(ExecutionEngine, jsStackTop)));
@@ -351,7 +264,7 @@ void InstructionSelection::run(int functionIndex)
foreach (IR::Stmt *s, _block->statements()) {
if (s->location.isValid()) {
if (int(s->location.startLine) != lastLine) {
- Assembler::Address lineAddr(Assembler::ContextRegister, qOffsetOf(QV4::ExecutionContext, lineNumber));
+ Assembler::Address lineAddr(Assembler::ContextRegister, qOffsetOf(QV4::ExecutionContext::Data, lineNumber));
_as->store32(Assembler::TrustedImm32(s->location.startLine), lineAddr);
lastLine = s->location.startLine;
}
@@ -385,10 +298,10 @@ const void *InstructionSelection::addConstantTable(QVector<Primitive> *values)
QV4::CompiledData::CompilationUnit *InstructionSelection::backendCompileStep()
{
- return compilationUnit;
+ return compilationUnit.take();
}
-void InstructionSelection::callBuiltinInvalid(IR::Name *func, IR::ExprList *args, IR::Temp *result)
+void InstructionSelection::callBuiltinInvalid(IR::Name *func, IR::ExprList *args, IR::Expr *result)
{
prepareCallData(args, 0);
@@ -407,52 +320,52 @@ void InstructionSelection::callBuiltinInvalid(IR::Name *func, IR::ExprList *args
}
void InstructionSelection::callBuiltinTypeofMember(IR::Expr *base, const QString &name,
- IR::Temp *result)
+ IR::Expr *result)
{
generateFunctionCall(result, Runtime::typeofMember, Assembler::ContextRegister,
Assembler::PointerToValue(base), Assembler::PointerToString(name));
}
void InstructionSelection::callBuiltinTypeofSubscript(IR::Expr *base, IR::Expr *index,
- IR::Temp *result)
+ IR::Expr *result)
{
generateFunctionCall(result, Runtime::typeofElement,
Assembler::ContextRegister,
Assembler::PointerToValue(base), Assembler::PointerToValue(index));
}
-void InstructionSelection::callBuiltinTypeofName(const QString &name, IR::Temp *result)
+void InstructionSelection::callBuiltinTypeofName(const QString &name, IR::Expr *result)
{
generateFunctionCall(result, Runtime::typeofName, Assembler::ContextRegister,
Assembler::PointerToString(name));
}
-void InstructionSelection::callBuiltinTypeofValue(IR::Expr *value, IR::Temp *result)
+void InstructionSelection::callBuiltinTypeofValue(IR::Expr *value, IR::Expr *result)
{
generateFunctionCall(result, Runtime::typeofValue, Assembler::ContextRegister,
Assembler::PointerToValue(value));
}
-void InstructionSelection::callBuiltinDeleteMember(IR::Temp *base, const QString &name, IR::Temp *result)
+void InstructionSelection::callBuiltinDeleteMember(IR::Expr *base, const QString &name, IR::Expr *result)
{
generateFunctionCall(result, Runtime::deleteMember, Assembler::ContextRegister,
Assembler::Reference(base), Assembler::PointerToString(name));
}
-void InstructionSelection::callBuiltinDeleteSubscript(IR::Temp *base, IR::Expr *index,
- IR::Temp *result)
+void InstructionSelection::callBuiltinDeleteSubscript(IR::Expr *base, IR::Expr *index,
+ IR::Expr *result)
{
generateFunctionCall(result, Runtime::deleteElement, Assembler::ContextRegister,
Assembler::Reference(base), Assembler::PointerToValue(index));
}
-void InstructionSelection::callBuiltinDeleteName(const QString &name, IR::Temp *result)
+void InstructionSelection::callBuiltinDeleteName(const QString &name, IR::Expr *result)
{
generateFunctionCall(result, Runtime::deleteName, Assembler::ContextRegister,
Assembler::PointerToString(name));
}
-void InstructionSelection::callBuiltinDeleteValue(IR::Temp *result)
+void InstructionSelection::callBuiltinDeleteValue(IR::Expr *result)
{
_as->storeValue(Primitive::fromBoolean(false), result);
}
@@ -468,7 +381,7 @@ void InstructionSelection::callBuiltinReThrow()
_as->jumpToExceptionHandler();
}
-void InstructionSelection::callBuiltinUnwindException(IR::Temp *result)
+void InstructionSelection::callBuiltinUnwindException(IR::Expr *result)
{
generateFunctionCall(result, Runtime::unwindException, Assembler::ContextRegister);
@@ -476,11 +389,10 @@ void InstructionSelection::callBuiltinUnwindException(IR::Temp *result)
void InstructionSelection::callBuiltinPushCatchScope(const QString &exceptionName)
{
- Assembler::Pointer s = _as->loadStringAddress(Assembler::ScratchRegister, exceptionName);
- generateFunctionCall(Assembler::ContextRegister, Runtime::pushCatchScope, Assembler::ContextRegister, s);
+ generateFunctionCall(Assembler::ContextRegister, Runtime::pushCatchScope, Assembler::ContextRegister, Assembler::PointerToString(exceptionName));
}
-void InstructionSelection::callBuiltinForeachIteratorObject(IR::Expr *arg, IR::Temp *result)
+void InstructionSelection::callBuiltinForeachIteratorObject(IR::Expr *arg, IR::Expr *result)
{
Q_ASSERT(arg);
Q_ASSERT(result);
@@ -488,7 +400,7 @@ void InstructionSelection::callBuiltinForeachIteratorObject(IR::Expr *arg, IR::T
generateFunctionCall(result, Runtime::foreachIterator, Assembler::ContextRegister, Assembler::PointerToValue(arg));
}
-void InstructionSelection::callBuiltinForeachNextPropertyname(IR::Temp *arg, IR::Temp *result)
+void InstructionSelection::callBuiltinForeachNextPropertyname(IR::Expr *arg, IR::Expr *result)
{
Q_ASSERT(arg);
Q_ASSERT(result);
@@ -496,7 +408,7 @@ void InstructionSelection::callBuiltinForeachNextPropertyname(IR::Temp *arg, IR:
generateFunctionCall(result, Runtime::foreachNextPropertyName, Assembler::Reference(arg));
}
-void InstructionSelection::callBuiltinPushWithScope(IR::Temp *arg)
+void InstructionSelection::callBuiltinPushWithScope(IR::Expr *arg)
{
Q_ASSERT(arg);
@@ -514,7 +426,7 @@ void InstructionSelection::callBuiltinDeclareVar(bool deletable, const QString &
Assembler::TrustedImm32(deletable), Assembler::PointerToString(name));
}
-void InstructionSelection::callBuiltinDefineArray(IR::Temp *result, IR::ExprList *args)
+void InstructionSelection::callBuiltinDefineArray(IR::Expr *result, IR::ExprList *args)
{
Q_ASSERT(result);
@@ -523,7 +435,7 @@ void InstructionSelection::callBuiltinDefineArray(IR::Temp *result, IR::ExprList
baseAddressForCallArguments(), Assembler::TrustedImm32(length));
}
-void InstructionSelection::callBuiltinDefineObjectLiteral(IR::Temp *result, int keyValuePairCount, IR::ExprList *keyValuePairs, IR::ExprList *arrayEntries, bool needSparseArray)
+void InstructionSelection::callBuiltinDefineObjectLiteral(IR::Expr *result, int keyValuePairCount, IR::ExprList *keyValuePairs, IR::ExprList *arrayEntries, bool needSparseArray)
{
Q_ASSERT(result);
@@ -604,7 +516,7 @@ void InstructionSelection::callBuiltinDefineObjectLiteral(IR::Temp *result, int
Assembler::TrustedImm32(arrayValueCount), Assembler::TrustedImm32(arrayGetterSetterCount | (needSparseArray << 30)));
}
-void InstructionSelection::callBuiltinSetupArgumentObject(IR::Temp *result)
+void InstructionSelection::callBuiltinSetupArgumentObject(IR::Expr *result)
{
generateFunctionCall(result, Runtime::setupArgumentsObject, Assembler::ContextRegister);
}
@@ -614,19 +526,24 @@ void InstructionSelection::callBuiltinConvertThisToObject()
generateFunctionCall(Assembler::Void, Runtime::convertThisToObject, Assembler::ContextRegister);
}
-void InstructionSelection::callValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result)
+void InstructionSelection::callValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result)
{
Q_ASSERT(value);
prepareCallData(args, 0);
- generateFunctionCall(result, Runtime::callValue, Assembler::ContextRegister,
- Assembler::Reference(value),
- baseAddressForCallData());
+ if (value->asConst())
+ generateFunctionCall(result, Runtime::callValue, Assembler::ContextRegister,
+ Assembler::PointerToValue(value),
+ baseAddressForCallData());
+ else
+ generateFunctionCall(result, Runtime::callValue, Assembler::ContextRegister,
+ Assembler::Reference(value),
+ baseAddressForCallData());
}
-void InstructionSelection::loadThisObject(IR::Temp *temp)
+void InstructionSelection::loadThisObject(IR::Expr *temp)
{
- _as->loadPtr(Address(Assembler::ContextRegister, qOffsetOf(ExecutionContext, callData)), Assembler::ScratchRegister);
+ _as->loadPtr(Address(Assembler::ContextRegister, qOffsetOf(ExecutionContext::Data, callData)), Assembler::ScratchRegister);
#if defined(VALUE_FITS_IN_REGISTER)
_as->load64(Pointer(Assembler::ScratchRegister, qOffsetOf(CallData, thisObject)),
Assembler::ReturnValueRegister);
@@ -636,60 +553,63 @@ void InstructionSelection::loadThisObject(IR::Temp *temp)
#endif
}
-void InstructionSelection::loadQmlIdArray(IR::Temp *temp)
+void InstructionSelection::loadQmlIdArray(IR::Expr *temp)
{
generateFunctionCall(temp, Runtime::getQmlIdArray, Assembler::ContextRegister);
}
-void InstructionSelection::loadQmlImportedScripts(IR::Temp *temp)
+void InstructionSelection::loadQmlImportedScripts(IR::Expr *temp)
{
generateFunctionCall(temp, Runtime::getQmlImportedScripts, Assembler::ContextRegister);
}
-void InstructionSelection::loadQmlContextObject(IR::Temp *temp)
+void InstructionSelection::loadQmlContextObject(IR::Expr *temp)
{
generateFunctionCall(temp, Runtime::getQmlContextObject, Assembler::ContextRegister);
}
-void InstructionSelection::loadQmlScopeObject(IR::Temp *temp)
+void InstructionSelection::loadQmlScopeObject(IR::Expr *temp)
{
generateFunctionCall(temp, Runtime::getQmlScopeObject, Assembler::ContextRegister);
}
-void InstructionSelection::loadQmlSingleton(const QString &name, IR::Temp *temp)
+void InstructionSelection::loadQmlSingleton(const QString &name, IR::Expr *temp)
{
generateFunctionCall(temp, Runtime::getQmlSingleton, Assembler::ContextRegister, Assembler::PointerToString(name));
}
-void InstructionSelection::loadConst(IR::Const *sourceConst, IR::Temp *targetTemp)
-{
- if (targetTemp->kind == IR::Temp::PhysicalRegister) {
- if (targetTemp->type == IR::DoubleType) {
- Q_ASSERT(sourceConst->type == IR::DoubleType);
- _as->toDoubleRegister(sourceConst, (Assembler::FPRegisterID) targetTemp->index);
- } else if (targetTemp->type == IR::SInt32Type) {
- Q_ASSERT(sourceConst->type == IR::SInt32Type);
- _as->toInt32Register(sourceConst, (Assembler::RegisterID) targetTemp->index);
- } else if (targetTemp->type == IR::UInt32Type) {
- Q_ASSERT(sourceConst->type == IR::UInt32Type);
- _as->toUInt32Register(sourceConst, (Assembler::RegisterID) targetTemp->index);
- } else if (targetTemp->type == IR::BoolType) {
- Q_ASSERT(sourceConst->type == IR::BoolType);
- _as->move(Assembler::TrustedImm32(convertToValue(sourceConst).int_32),
- (Assembler::RegisterID) targetTemp->index);
- } else {
- Q_UNREACHABLE();
+void InstructionSelection::loadConst(IR::Const *sourceConst, IR::Expr *target)
+{
+ if (IR::Temp *targetTemp = target->asTemp()) {
+ if (targetTemp->kind == IR::Temp::PhysicalRegister) {
+ if (targetTemp->type == IR::DoubleType) {
+ Q_ASSERT(sourceConst->type == IR::DoubleType);
+ _as->toDoubleRegister(sourceConst, (Assembler::FPRegisterID) targetTemp->index);
+ } else if (targetTemp->type == IR::SInt32Type) {
+ Q_ASSERT(sourceConst->type == IR::SInt32Type);
+ _as->toInt32Register(sourceConst, (Assembler::RegisterID) targetTemp->index);
+ } else if (targetTemp->type == IR::UInt32Type) {
+ Q_ASSERT(sourceConst->type == IR::UInt32Type);
+ _as->toUInt32Register(sourceConst, (Assembler::RegisterID) targetTemp->index);
+ } else if (targetTemp->type == IR::BoolType) {
+ Q_ASSERT(sourceConst->type == IR::BoolType);
+ _as->move(Assembler::TrustedImm32(convertToValue(sourceConst).int_32),
+ (Assembler::RegisterID) targetTemp->index);
+ } else {
+ Q_UNREACHABLE();
+ }
+ return;
}
- } else {
- _as->storeValue(convertToValue(sourceConst), targetTemp);
}
+
+ _as->storeValue(convertToValue(sourceConst), target);
}
-void InstructionSelection::loadString(const QString &str, IR::Temp *targetTemp)
+void InstructionSelection::loadString(const QString &str, IR::Expr *target)
{
Pointer srcAddr = _as->loadStringAddress(Assembler::ReturnValueRegister, str);
_as->loadPtr(srcAddr, Assembler::ReturnValueRegister);
- Pointer destAddr = _as->loadTempAddress(Assembler::ScratchRegister, targetTemp);
+ Pointer destAddr = _as->loadAddress(Assembler::ScratchRegister, target);
#if QT_POINTER_SIZE == 8
_as->store64(Assembler::ReturnValueRegister, destAddr);
#else
@@ -699,20 +619,20 @@ void InstructionSelection::loadString(const QString &str, IR::Temp *targetTemp)
#endif
}
-void InstructionSelection::loadRegexp(IR::RegExp *sourceRegexp, IR::Temp *targetTemp)
+void InstructionSelection::loadRegexp(IR::RegExp *sourceRegexp, IR::Expr *target)
{
int id = registerRegExp(sourceRegexp);
- generateFunctionCall(targetTemp, Runtime::regexpLiteral, Assembler::ContextRegister, Assembler::TrustedImm32(id));
+ generateFunctionCall(target, Runtime::regexpLiteral, Assembler::ContextRegister, Assembler::TrustedImm32(id));
}
-void InstructionSelection::getActivationProperty(const IR::Name *name, IR::Temp *temp)
+void InstructionSelection::getActivationProperty(const IR::Name *name, IR::Expr *target)
{
if (useFastLookups && name->global) {
uint index = registerGlobalGetterLookup(*name->id);
- generateLookupCall(temp, index, qOffsetOf(QV4::Lookup, globalGetter), Assembler::ContextRegister, Assembler::Void);
+ generateLookupCall(target, index, qOffsetOf(QV4::Lookup, globalGetter), Assembler::ContextRegister, Assembler::Void);
return;
}
- generateFunctionCall(temp, Runtime::getActivationProperty, Assembler::ContextRegister, Assembler::PointerToString(*name->id));
+ generateFunctionCall(target, Runtime::getActivationProperty, Assembler::ContextRegister, Assembler::PointerToString(*name->id));
}
void InstructionSelection::setActivationProperty(IR::Expr *source, const QString &targetName)
@@ -722,13 +642,13 @@ void InstructionSelection::setActivationProperty(IR::Expr *source, const QString
Assembler::ContextRegister, Assembler::PointerToString(targetName), Assembler::PointerToValue(source));
}
-void InstructionSelection::initClosure(IR::Closure *closure, IR::Temp *target)
+void InstructionSelection::initClosure(IR::Closure *closure, IR::Expr *target)
{
int id = closure->value;
generateFunctionCall(target, Runtime::closure, Assembler::ContextRegister, Assembler::TrustedImm32(id));
}
-void InstructionSelection::getProperty(IR::Expr *base, const QString &name, IR::Temp *target)
+void InstructionSelection::getProperty(IR::Expr *base, const QString &name, IR::Expr *target)
{
if (useFastLookups) {
uint index = registerGetterLookup(name);
@@ -739,7 +659,7 @@ void InstructionSelection::getProperty(IR::Expr *base, const QString &name, IR::
}
}
-void InstructionSelection::getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, IR::Temp *target)
+void InstructionSelection::getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, IR::Expr *target)
{
if (attachedPropertiesId != 0)
generateFunctionCall(target, Runtime::getQmlAttachedProperty, Assembler::ContextRegister, Assembler::TrustedImm32(attachedPropertiesId), Assembler::TrustedImm32(propertyIndex));
@@ -769,7 +689,7 @@ void InstructionSelection::setQObjectProperty(IR::Expr *source, IR::Expr *target
Assembler::TrustedImm32(propertyIndex), Assembler::PointerToValue(source));
}
-void InstructionSelection::getElement(IR::Expr *base, IR::Expr *index, IR::Temp *target)
+void InstructionSelection::getElement(IR::Expr *base, IR::Expr *index, IR::Expr *target)
{
if (useFastLookups) {
uint lookup = registerIndexedGetterLookup();
@@ -797,13 +717,20 @@ void InstructionSelection::setElement(IR::Expr *source, IR::Expr *targetBase, IR
Assembler::PointerToValue(source));
}
-void InstructionSelection::copyValue(IR::Temp *sourceTemp, IR::Temp *targetTemp)
+void InstructionSelection::copyValue(IR::Expr *source, IR::Expr *target)
{
- if (*sourceTemp == *targetTemp)
+ IR::Temp *sourceTemp = source->asTemp();
+ IR::Temp *targetTemp = target->asTemp();
+
+ if (sourceTemp && targetTemp && *sourceTemp == *targetTemp)
return;
+ if (IR::ArgLocal *sal = source->asArgLocal())
+ if (IR::ArgLocal *tal = target->asArgLocal())
+ if (*sal == *tal)
+ return;
- if (sourceTemp->kind == IR::Temp::PhysicalRegister) {
- if (targetTemp->kind == IR::Temp::PhysicalRegister) {
+ if (sourceTemp && sourceTemp->kind == IR::Temp::PhysicalRegister) {
+ if (targetTemp && targetTemp->kind == IR::Temp::PhysicalRegister) {
if (sourceTemp->type == IR::DoubleType)
_as->moveDouble((Assembler::FPRegisterID) sourceTemp->index,
(Assembler::FPRegisterID) targetTemp->index);
@@ -814,16 +741,16 @@ void InstructionSelection::copyValue(IR::Temp *sourceTemp, IR::Temp *targetTemp)
} else {
switch (sourceTemp->type) {
case IR::DoubleType:
- _as->storeDouble((Assembler::FPRegisterID) sourceTemp->index, targetTemp);
+ _as->storeDouble((Assembler::FPRegisterID) sourceTemp->index, target);
break;
case IR::SInt32Type:
- _as->storeInt32((Assembler::RegisterID) sourceTemp->index, targetTemp);
+ _as->storeInt32((Assembler::RegisterID) sourceTemp->index, target);
break;
case IR::UInt32Type:
- _as->storeUInt32((Assembler::RegisterID) sourceTemp->index, targetTemp);
+ _as->storeUInt32((Assembler::RegisterID) sourceTemp->index, target);
break;
case IR::BoolType:
- _as->storeBool((Assembler::RegisterID) sourceTemp->index, targetTemp);
+ _as->storeBool((Assembler::RegisterID) sourceTemp->index, target);
break;
default:
Q_ASSERT(!"Unreachable");
@@ -831,23 +758,23 @@ void InstructionSelection::copyValue(IR::Temp *sourceTemp, IR::Temp *targetTemp)
}
return;
}
- } else if (targetTemp->kind == IR::Temp::PhysicalRegister) {
+ } else if (targetTemp && targetTemp->kind == IR::Temp::PhysicalRegister) {
switch (targetTemp->type) {
case IR::DoubleType:
- Q_ASSERT(sourceTemp->type == IR::DoubleType);
- _as->toDoubleRegister(sourceTemp, (Assembler::FPRegisterID) targetTemp->index);
+ Q_ASSERT(source->type == IR::DoubleType);
+ _as->toDoubleRegister(source, (Assembler::FPRegisterID) targetTemp->index);
return;
case IR::BoolType:
- Q_ASSERT(sourceTemp->type == IR::BoolType);
- _as->toInt32Register(sourceTemp, (Assembler::RegisterID) targetTemp->index);
+ Q_ASSERT(source->type == IR::BoolType);
+ _as->toInt32Register(source, (Assembler::RegisterID) targetTemp->index);
return;
case IR::SInt32Type:
- Q_ASSERT(sourceTemp->type == IR::SInt32Type);
- _as->toInt32Register(sourceTemp, (Assembler::RegisterID) targetTemp->index);
+ Q_ASSERT(source->type == IR::SInt32Type);
+ _as->toInt32Register(source, (Assembler::RegisterID) targetTemp->index);
return;
case IR::UInt32Type:
- Q_ASSERT(sourceTemp->type == IR::UInt32Type);
- _as->toUInt32Register(sourceTemp, (Assembler::RegisterID) targetTemp->index);
+ Q_ASSERT(source->type == IR::UInt32Type);
+ _as->toUInt32Register(source, (Assembler::RegisterID) targetTemp->index);
return;
default:
Q_ASSERT(!"Unreachable");
@@ -856,14 +783,16 @@ void InstructionSelection::copyValue(IR::Temp *sourceTemp, IR::Temp *targetTemp)
}
// The target is not a physical register, nor is the source. So we can do a memory-to-memory copy:
- _as->memcopyValue(_as->loadTempAddress(Assembler::ReturnValueRegister, targetTemp), sourceTemp,
- Assembler::ScratchRegister);
+ _as->memcopyValue(_as->loadAddress(Assembler::ReturnValueRegister, target), source, Assembler::ScratchRegister);
}
-void InstructionSelection::swapValues(IR::Temp *sourceTemp, IR::Temp *targetTemp)
+void InstructionSelection::swapValues(IR::Expr *source, IR::Expr *target)
{
- if (sourceTemp->kind == IR::Temp::PhysicalRegister) {
- if (targetTemp->kind == IR::Temp::PhysicalRegister) {
+ IR::Temp *sourceTemp = source->asTemp();
+ IR::Temp *targetTemp = target->asTemp();
+
+ if (sourceTemp && sourceTemp->kind == IR::Temp::PhysicalRegister) {
+ if (targetTemp && targetTemp->kind == IR::Temp::PhysicalRegister) {
Q_ASSERT(sourceTemp->type == targetTemp->type);
if (sourceTemp->type == IR::DoubleType) {
@@ -877,11 +806,11 @@ void InstructionSelection::swapValues(IR::Temp *sourceTemp, IR::Temp *targetTemp
}
return;
}
- } else if (sourceTemp->kind == IR::Temp::StackSlot) {
- if (targetTemp->kind == IR::Temp::StackSlot) {
+ } else if (!sourceTemp || sourceTemp->kind == IR::Temp::StackSlot) {
+ if (!targetTemp || targetTemp->kind == IR::Temp::StackSlot) {
// Note: a swap for two stack-slots can involve different types.
- Assembler::Pointer sAddr = _as->stackSlotPointer(sourceTemp);
- Assembler::Pointer tAddr = _as->stackSlotPointer(targetTemp);
+ Assembler::Pointer sAddr = _as->loadAddress(Assembler::ScratchRegister, source);
+ Assembler::Pointer tAddr = _as->loadAddress(Assembler::ReturnValueRegister, target);
// use the implementation in JSC::MacroAssembler, as it doesn't do bit swizzling
_as->JSC::MacroAssembler::loadDouble(sAddr, Assembler::FPGpr0);
_as->JSC::MacroAssembler::loadDouble(tAddr, Assembler::FPGpr1);
@@ -891,25 +820,28 @@ void InstructionSelection::swapValues(IR::Temp *sourceTemp, IR::Temp *targetTemp
}
}
- IR::Temp *stackTemp = sourceTemp->kind == IR::Temp::StackSlot ? sourceTemp : targetTemp;
- IR::Temp *registerTemp = sourceTemp->kind == IR::Temp::PhysicalRegister ? sourceTemp
- : targetTemp;
- Assembler::Pointer addr = _as->stackSlotPointer(stackTemp);
- if (registerTemp->type == IR::DoubleType) {
+ IR::Expr *memExpr = !sourceTemp || sourceTemp->kind == IR::Temp::StackSlot ? source : target;
+ IR::Temp *regTemp = sourceTemp && sourceTemp->kind == IR::Temp::PhysicalRegister ? sourceTemp
+ : targetTemp;
+ Q_ASSERT(memExpr);
+ Q_ASSERT(regTemp);
+
+ Assembler::Pointer addr = _as->loadAddress(Assembler::ReturnValueRegister, memExpr);
+ if (regTemp->type == IR::DoubleType) {
_as->loadDouble(addr, Assembler::FPGpr0);
- _as->storeDouble((Assembler::FPRegisterID) registerTemp->index, addr);
- _as->moveDouble(Assembler::FPGpr0, (Assembler::FPRegisterID) registerTemp->index);
- } else if (registerTemp->type == IR::UInt32Type) {
+ _as->storeDouble((Assembler::FPRegisterID) regTemp->index, addr);
+ _as->moveDouble(Assembler::FPGpr0, (Assembler::FPRegisterID) regTemp->index);
+ } else if (regTemp->type == IR::UInt32Type) {
_as->toUInt32Register(addr, Assembler::ScratchRegister);
- _as->storeUInt32((Assembler::RegisterID) registerTemp->index, addr);
- _as->move(Assembler::ScratchRegister, (Assembler::RegisterID) registerTemp->index);
+ _as->storeUInt32((Assembler::RegisterID) regTemp->index, addr);
+ _as->move(Assembler::ScratchRegister, (Assembler::RegisterID) regTemp->index);
} else {
_as->load32(addr, Assembler::ScratchRegister);
- _as->store32((Assembler::RegisterID) registerTemp->index, addr);
- if (registerTemp->type != stackTemp->type) {
+ _as->store32((Assembler::RegisterID) regTemp->index, addr);
+ if (regTemp->type != memExpr->type) {
addr.offset += 4;
quint32 tag;
- switch (registerTemp->type) {
+ switch (regTemp->type) {
case IR::BoolType:
tag = QV4::Value::_Boolean_Type;
break;
@@ -922,7 +854,7 @@ void InstructionSelection::swapValues(IR::Temp *sourceTemp, IR::Temp *targetTemp
}
_as->store32(Assembler::TrustedImm32(tag), addr);
}
- _as->move(Assembler::ScratchRegister, (Assembler::RegisterID) registerTemp->index);
+ _as->move(Assembler::ScratchRegister, (Assembler::RegisterID) regTemp->index);
}
}
@@ -931,21 +863,21 @@ void InstructionSelection::swapValues(IR::Temp *sourceTemp, IR::Temp *targetTemp
#define setOpContext(op, opName, operation) \
do { opContext = operation; opName = isel_stringIfy(operation); } while (0)
-void InstructionSelection::unop(IR::AluOp oper, IR::Temp *sourceTemp, IR::Temp *targetTemp)
+void InstructionSelection::unop(IR::AluOp oper, IR::Expr *source, IR::Expr *target)
{
QV4::JIT::Unop unop(_as, oper);
- unop.generate(sourceTemp, targetTemp);
+ unop.generate(source, target);
}
-void InstructionSelection::binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target)
+void InstructionSelection::binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *target)
{
QV4::JIT::Binop binop(_as, oper);
binop.generate(leftSource, rightSource, target);
}
void InstructionSelection::callProperty(IR::Expr *base, const QString &name, IR::ExprList *args,
- IR::Temp *result)
+ IR::Expr *result)
{
Q_ASSERT(base != 0);
@@ -965,7 +897,7 @@ void InstructionSelection::callProperty(IR::Expr *base, const QString &name, IR:
}
void InstructionSelection::callSubscript(IR::Expr *base, IR::Expr *index, IR::ExprList *args,
- IR::Temp *result)
+ IR::Expr *result)
{
Q_ASSERT(base != 0);
@@ -975,7 +907,7 @@ void InstructionSelection::callSubscript(IR::Expr *base, IR::Expr *index, IR::Ex
baseAddressForCallData());
}
-void InstructionSelection::convertType(IR::Temp *source, IR::Temp *target)
+void InstructionSelection::convertType(IR::Expr *source, IR::Expr *target)
{
switch (target->type) {
case IR::DoubleType:
@@ -996,7 +928,7 @@ void InstructionSelection::convertType(IR::Temp *source, IR::Temp *target)
}
}
-void InstructionSelection::convertTypeSlowPath(IR::Temp *source, IR::Temp *target)
+void InstructionSelection::convertTypeSlowPath(IR::Expr *source, IR::Expr *target)
{
Q_ASSERT(target->type != IR::BoolType);
@@ -1006,7 +938,7 @@ void InstructionSelection::convertTypeSlowPath(IR::Temp *source, IR::Temp *targe
copyValue(source, target);
}
-void InstructionSelection::convertTypeToDouble(IR::Temp *source, IR::Temp *target)
+void InstructionSelection::convertTypeToDouble(IR::Expr *source, IR::Expr *target)
{
switch (source->type) {
case IR::SInt32Type:
@@ -1018,13 +950,13 @@ void InstructionSelection::convertTypeToDouble(IR::Temp *source, IR::Temp *targe
convertUIntToDouble(source, target);
break;
case IR::UndefinedType:
- _as->loadDouble(_as->loadTempAddress(Assembler::ScratchRegister, source), Assembler::FPGpr0);
+ _as->loadDouble(_as->loadAddress(Assembler::ScratchRegister, source), Assembler::FPGpr0);
_as->storeDouble(Assembler::FPGpr0, target);
break;
case IR::StringType:
case IR::VarType: {
// load the tag:
- Assembler::Pointer tagAddr = _as->loadTempAddress(Assembler::ScratchRegister, source);
+ Assembler::Pointer tagAddr = _as->loadAddress(Assembler::ScratchRegister, source);
tagAddr.offset += 4;
_as->load32(tagAddr, Assembler::ScratchRegister);
@@ -1051,17 +983,18 @@ void InstructionSelection::convertTypeToDouble(IR::Temp *source, IR::Temp *targe
// it is a double:
isDbl.link(_as);
- Assembler::Pointer addr2 = _as->loadTempAddress(Assembler::ScratchRegister, source);
- if (target->kind == IR::Temp::StackSlot) {
+ Assembler::Pointer addr2 = _as->loadAddress(Assembler::ScratchRegister, source);
+ IR::Temp *targetTemp = target->asTemp();
+ if (!targetTemp || targetTemp->kind == IR::Temp::StackSlot) {
#if QT_POINTER_SIZE == 8
_as->load64(addr2, Assembler::ScratchRegister);
- _as->store64(Assembler::ScratchRegister, _as->stackSlotPointer(target));
+ _as->store64(Assembler::ScratchRegister, _as->loadAddress(Assembler::ReturnValueRegister, target));
#else
_as->loadDouble(addr2, Assembler::FPGpr0);
- _as->storeDouble(Assembler::FPGpr0, _as->stackSlotPointer(target));
+ _as->storeDouble(Assembler::FPGpr0, _as->loadAddress(Assembler::ReturnValueRegister, target));
#endif
} else {
- _as->loadDouble(addr2, (Assembler::FPRegisterID) target->index);
+ _as->loadDouble(addr2, (Assembler::FPRegisterID) targetTemp->index);
}
noDoubleDone.link(_as);
@@ -1073,8 +1006,9 @@ void InstructionSelection::convertTypeToDouble(IR::Temp *source, IR::Temp *targe
}
}
-void InstructionSelection::convertTypeToBool(IR::Temp *source, IR::Temp *target)
+void InstructionSelection::convertTypeToBool(IR::Expr *source, IR::Expr *target)
{
+ IR::Temp *sourceTemp = source->asTemp();
switch (source->type) {
case IR::SInt32Type:
case IR::UInt32Type:
@@ -1085,8 +1019,8 @@ void InstructionSelection::convertTypeToBool(IR::Temp *source, IR::Temp *target)
// allocator was not used, then that means that we can use any register for to
// load the double into.
Assembler::FPRegisterID reg;
- if (source->kind == IR::Temp::PhysicalRegister)
- reg = (Assembler::FPRegisterID) source->index;
+ if (sourceTemp && sourceTemp->kind == IR::Temp::PhysicalRegister)
+ reg = (Assembler::FPRegisterID) sourceTemp->index;
else
reg = _as->toDoubleRegister(source, (Assembler::FPRegisterID) 1);
Assembler::Jump nonZero = _as->branchDoubleNonZero(reg, Assembler::FPGpr0);
@@ -1116,13 +1050,13 @@ void InstructionSelection::convertTypeToBool(IR::Temp *source, IR::Temp *target)
}
}
-void InstructionSelection::convertTypeToSInt32(IR::Temp *source, IR::Temp *target)
+void InstructionSelection::convertTypeToSInt32(IR::Expr *source, IR::Expr *target)
{
switch (source->type) {
case IR::VarType: {
#if QT_POINTER_SIZE == 8
- Assembler::Pointer addr = _as->loadTempAddress(Assembler::ScratchRegister, source);
+ Assembler::Pointer addr = _as->loadAddress(Assembler::ScratchRegister, source);
_as->load64(addr, Assembler::ScratchRegister);
_as->move(Assembler::ScratchRegister, Assembler::ReturnValueRegister);
@@ -1142,12 +1076,13 @@ void InstructionSelection::convertTypeToSInt32(IR::Temp *source, IR::Temp *targe
// not an int:
fallback.link(_as);
generateFunctionCall(Assembler::ReturnValueRegister, Runtime::toInt,
- _as->loadTempAddress(Assembler::ScratchRegister, source));
+ _as->loadAddress(Assembler::ScratchRegister, source));
isInt.link(_as);
success.link(_as);
- if (target->kind == IR::Temp::StackSlot) {
- Assembler::Pointer targetAddr = _as->stackSlotPointer(target);
+ IR::Temp *targetTemp = target->asTemp();
+ if (!targetTemp || targetTemp->kind == IR::Temp::StackSlot) {
+ Assembler::Pointer targetAddr = _as->loadAddress(Assembler::ScratchRegister, target);
_as->store32(Assembler::ReturnValueRegister, targetAddr);
targetAddr.offset += 4;
_as->store32(Assembler::TrustedImm32(Value::_Integer_Type), targetAddr);
@@ -1156,7 +1091,7 @@ void InstructionSelection::convertTypeToSInt32(IR::Temp *source, IR::Temp *targe
}
#else
// load the tag:
- Assembler::Pointer addr = _as->loadTempAddress(Assembler::ScratchRegister, source);
+ Assembler::Pointer addr = _as->loadAddress(Assembler::ScratchRegister, source);
Assembler::Pointer tagAddr = addr;
tagAddr.offset += 4;
_as->load32(tagAddr, Assembler::ReturnValueRegister);
@@ -1164,21 +1099,22 @@ void InstructionSelection::convertTypeToSInt32(IR::Temp *source, IR::Temp *targe
// check if it's an int32:
Assembler::Jump fallback = _as->branch32(Assembler::NotEqual, Assembler::ReturnValueRegister,
Assembler::TrustedImm32(Value::_Integer_Type));
- if (target->kind == IR::Temp::StackSlot) {
- _as->load32(addr, Assembler::ScratchRegister);
- Assembler::Pointer targetAddr = _as->stackSlotPointer(target);
- _as->store32(Assembler::ScratchRegister, targetAddr);
+ IR::Temp *targetTemp = target->asTemp();
+ if (!targetTemp || targetTemp->kind == IR::Temp::StackSlot) {
+ _as->load32(addr, Assembler::ReturnValueRegister);
+ Assembler::Pointer targetAddr = _as->loadAddress(Assembler::ScratchRegister, target);
+ _as->store32(Assembler::ReturnValueRegister, targetAddr);
targetAddr.offset += 4;
_as->store32(Assembler::TrustedImm32(Value::_Integer_Type), targetAddr);
} else {
- _as->load32(addr, (Assembler::RegisterID) target->index);
+ _as->load32(addr, (Assembler::RegisterID) targetTemp->index);
}
Assembler::Jump intDone = _as->jump();
// not an int:
fallback.link(_as);
generateFunctionCall(Assembler::ReturnValueRegister, Runtime::toInt,
- _as->loadTempAddress(Assembler::ScratchRegister, source));
+ _as->loadAddress(Assembler::ScratchRegister, source));
_as->storeInt32(Assembler::ReturnValueRegister, target);
intDone.link(_as);
@@ -1209,32 +1145,32 @@ void InstructionSelection::convertTypeToSInt32(IR::Temp *source, IR::Temp *targe
case IR::StringType:
default:
generateFunctionCall(Assembler::ReturnValueRegister, Runtime::toInt,
- _as->loadTempAddress(Assembler::ScratchRegister, source));
+ _as->loadAddress(Assembler::ScratchRegister, source));
_as->storeInt32(Assembler::ReturnValueRegister, target);
break;
} // switch (source->type)
}
-void InstructionSelection::convertTypeToUInt32(IR::Temp *source, IR::Temp *target)
+void InstructionSelection::convertTypeToUInt32(IR::Expr *source, IR::Expr *target)
{
switch (source->type) {
case IR::VarType: {
// load the tag:
- Assembler::Pointer tagAddr = _as->loadTempAddress(Assembler::ScratchRegister, source);
+ Assembler::Pointer tagAddr = _as->loadAddress(Assembler::ScratchRegister, source);
tagAddr.offset += 4;
_as->load32(tagAddr, Assembler::ScratchRegister);
// check if it's an int32:
Assembler::Jump isNoInt = _as->branch32(Assembler::NotEqual, Assembler::ScratchRegister,
Assembler::TrustedImm32(Value::_Integer_Type));
- Assembler::Pointer addr = _as->loadTempAddress(Assembler::ScratchRegister, source);
+ Assembler::Pointer addr = _as->loadAddress(Assembler::ScratchRegister, source);
_as->storeUInt32(_as->toInt32Register(addr, Assembler::ScratchRegister), target);
Assembler::Jump intDone = _as->jump();
// not an int:
isNoInt.link(_as);
generateFunctionCall(Assembler::ReturnValueRegister, Runtime::toUInt,
- _as->loadTempAddress(Assembler::ScratchRegister, source));
+ _as->loadAddress(Assembler::ScratchRegister, source));
_as->storeInt32(Assembler::ReturnValueRegister, target);
intDone.link(_as);
@@ -1268,7 +1204,7 @@ void InstructionSelection::convertTypeToUInt32(IR::Temp *source, IR::Temp *targe
} // switch (source->type)
}
-void InstructionSelection::constructActivationProperty(IR::Name *func, IR::ExprList *args, IR::Temp *result)
+void InstructionSelection::constructActivationProperty(IR::Name *func, IR::ExprList *args, IR::Expr *result)
{
Q_ASSERT(func != 0);
prepareCallData(args, 0);
@@ -1288,7 +1224,7 @@ void InstructionSelection::constructActivationProperty(IR::Name *func, IR::ExprL
}
-void InstructionSelection::constructProperty(IR::Temp *base, const QString &name, IR::ExprList *args, IR::Temp *result)
+void InstructionSelection::constructProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr *result)
{
prepareCallData(args, base);
if (useFastLookups) {
@@ -1305,7 +1241,7 @@ void InstructionSelection::constructProperty(IR::Temp *base, const QString &name
baseAddressForCallData());
}
-void InstructionSelection::constructValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result)
+void InstructionSelection::constructValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result)
{
Q_ASSERT(value != 0);
@@ -1324,16 +1260,17 @@ void InstructionSelection::visitJump(IR::Jump *s)
void InstructionSelection::visitCJump(IR::CJump *s)
{
- if (IR::Temp *t = s->cond->asTemp()) {
+ IR::Temp *t = s->cond->asTemp();
+ if (t || s->cond->asArgLocal()) {
Assembler::RegisterID reg;
- if (t->kind == IR::Temp::PhysicalRegister) {
+ if (t && t->kind == IR::Temp::PhysicalRegister) {
Q_ASSERT(t->type == IR::BoolType);
reg = (Assembler::RegisterID) t->index;
- } else if (t->kind == IR::Temp::StackSlot && t->type == IR::BoolType) {
+ } else if (t && t->kind == IR::Temp::StackSlot && t->type == IR::BoolType) {
reg = Assembler::ReturnValueRegister;
_as->toInt32Register(t, reg);
} else {
- Address temp = _as->loadTempAddress(Assembler::ScratchRegister, t);
+ Address temp = _as->loadAddress(Assembler::ScratchRegister, s->cond);
Address tag = temp;
tag.offset += qOffsetOf(QV4::Value, tag);
Assembler::Jump booleanConversion = _as->branch32(Assembler::NotEqual, tag, Assembler::TrustedImm32(QV4::Value::Boolean_Type));
@@ -1345,7 +1282,7 @@ void InstructionSelection::visitCJump(IR::CJump *s)
booleanConversion.link(_as);
reg = Assembler::ReturnValueRegister;
- generateFunctionCall(reg, Runtime::toBoolean, Assembler::Reference(t));
+ generateFunctionCall(reg, Runtime::toBoolean, Assembler::Reference(s->cond));
testBoolean.link(_as);
}
@@ -1455,7 +1392,7 @@ void InstructionSelection::visitRet(IR::Ret *s)
Q_UNREACHABLE();
}
} else {
- Pointer addr = _as->loadTempAddress(Assembler::ScratchRegister, t);
+ Pointer addr = _as->loadAddress(Assembler::ScratchRegister, t);
_as->load32(addr, lowReg);
addr.offset += 4;
_as->load32(addr, highReg);
@@ -1523,7 +1460,7 @@ void InstructionSelection::visitRet(IR::Ret *s)
const int locals = _as->stackLayout().calculateJSStackFrameSize();
_as->subPtr(Assembler::TrustedImm32(sizeof(QV4::Value)*locals), Assembler::LocalsRegister);
- _as->loadPtr(Address(Assembler::ContextRegister, qOffsetOf(ExecutionContext, engine)), Assembler::ScratchRegister);
+ _as->loadPtr(Address(Assembler::ContextRegister, qOffsetOf(ExecutionContext::Data, engine)), Assembler::ScratchRegister);
_as->storePtr(Assembler::LocalsRegister, Address(Assembler::ScratchRegister, qOffsetOf(ExecutionEngine, jsStackTop)));
_as->leaveStandardStackFrame();
@@ -1692,10 +1629,7 @@ bool InstructionSelection::visitCJumpStrictNullUndefined(IR::Type nullOrUndef, I
return true;
}
- IR::Temp *t = varSrc->asTemp();
- Q_ASSERT(t);
-
- Assembler::Pointer tagAddr = _as->loadTempAddress(Assembler::ScratchRegister, t);
+ Assembler::Pointer tagAddr = _as->loadAddress(Assembler::ScratchRegister, varSrc);
tagAddr.offset += 4;
const Assembler::RegisterID tagReg = Assembler::ScratchRegister;
_as->load32(tagAddr, tagReg);
@@ -1738,11 +1672,7 @@ bool InstructionSelection::visitCJumpStrictBool(IR::Binop *binop, IR::BasicBlock
return true;
}
- IR::Temp *otherTemp = otherSrc->asTemp();
- Q_ASSERT(otherTemp); // constants cannot have "var" type
- Q_ASSERT(otherTemp->kind != IR::Temp::PhysicalRegister);
-
- Assembler::Pointer otherAddr = _as->loadTempAddress(Assembler::ReturnValueRegister, otherTemp);
+ Assembler::Pointer otherAddr = _as->loadAddress(Assembler::ReturnValueRegister, otherSrc);
otherAddr.offset += 4; // tag address
// check if the tag of the var operand is indicates 'boolean'
@@ -1790,10 +1720,7 @@ bool InstructionSelection::visitCJumpNullUndefined(IR::Type nullOrUndef, IR::Bin
return true;
}
- IR::Temp *t = varSrc->asTemp();
- Q_ASSERT(t);
-
- Assembler::Pointer tagAddr = _as->loadTempAddress(Assembler::ScratchRegister, t);
+ Assembler::Pointer tagAddr = _as->loadAddress(Assembler::ScratchRegister, varSrc);
tagAddr.offset += 4;
const Assembler::RegisterID tagReg = Assembler::ScratchRegister;
_as->load32(tagAddr, tagReg);
diff --git a/src/qml/jit/qv4isel_masm_p.h b/src/qml/jit/qv4isel_masm_p.h
index d589223d7e..9c0bc73a65 100644
--- a/src/qml/jit/qv4isel_masm_p.h
+++ b/src/qml/jit/qv4isel_masm_p.h
@@ -76,54 +76,54 @@ public:
protected:
virtual QV4::CompiledData::CompilationUnit *backendCompileStep();
- virtual void callBuiltinInvalid(IR::Name *func, IR::ExprList *args, IR::Temp *result);
- virtual void callBuiltinTypeofMember(IR::Expr *base, const QString &name, IR::Temp *result);
- virtual void callBuiltinTypeofSubscript(IR::Expr *base, IR::Expr *index, IR::Temp *result);
- virtual void callBuiltinTypeofName(const QString &name, IR::Temp *result);
- virtual void callBuiltinTypeofValue(IR::Expr *value, IR::Temp *result);
- virtual void callBuiltinDeleteMember(IR::Temp *base, const QString &name, IR::Temp *result);
- virtual void callBuiltinDeleteSubscript(IR::Temp *base, IR::Expr *index, IR::Temp *result);
- virtual void callBuiltinDeleteName(const QString &name, IR::Temp *result);
- virtual void callBuiltinDeleteValue(IR::Temp *result);
+ virtual void callBuiltinInvalid(IR::Name *func, IR::ExprList *args, IR::Expr *result);
+ virtual void callBuiltinTypeofMember(IR::Expr *base, const QString &name, IR::Expr *result);
+ virtual void callBuiltinTypeofSubscript(IR::Expr *base, IR::Expr *index, IR::Expr *result);
+ virtual void callBuiltinTypeofName(const QString &name, IR::Expr *result);
+ virtual void callBuiltinTypeofValue(IR::Expr *value, IR::Expr *result);
+ virtual void callBuiltinDeleteMember(IR::Expr *base, const QString &name, IR::Expr *result);
+ virtual void callBuiltinDeleteSubscript(IR::Expr *base, IR::Expr *index, IR::Expr *result);
+ virtual void callBuiltinDeleteName(const QString &name, IR::Expr *result);
+ virtual void callBuiltinDeleteValue(IR::Expr *result);
virtual void callBuiltinThrow(IR::Expr *arg);
virtual void callBuiltinReThrow();
- virtual void callBuiltinUnwindException(IR::Temp *);
+ virtual void callBuiltinUnwindException(IR::Expr *);
virtual void callBuiltinPushCatchScope(const QString &exceptionName);
- virtual void callBuiltinForeachIteratorObject(IR::Expr *arg, IR::Temp *result);
- virtual void callBuiltinForeachNextPropertyname(IR::Temp *arg, IR::Temp *result);
- virtual void callBuiltinPushWithScope(IR::Temp *arg);
+ virtual void callBuiltinForeachIteratorObject(IR::Expr *arg, IR::Expr *result);
+ virtual void callBuiltinForeachNextPropertyname(IR::Expr *arg, IR::Expr *result);
+ virtual void callBuiltinPushWithScope(IR::Expr *arg);
virtual void callBuiltinPopScope();
virtual void callBuiltinDeclareVar(bool deletable, const QString &name);
- virtual void callBuiltinDefineArray(IR::Temp *result, IR::ExprList *args);
- virtual void callBuiltinDefineObjectLiteral(IR::Temp *result, int keyValuePairCount, IR::ExprList *keyValuePairs, IR::ExprList *arrayEntries, bool needSparseArray);
- virtual void callBuiltinSetupArgumentObject(IR::Temp *result);
+ virtual void callBuiltinDefineArray(IR::Expr *result, IR::ExprList *args);
+ virtual void callBuiltinDefineObjectLiteral(IR::Expr *result, int keyValuePairCount, IR::ExprList *keyValuePairs, IR::ExprList *arrayEntries, bool needSparseArray);
+ virtual void callBuiltinSetupArgumentObject(IR::Expr *result);
virtual void callBuiltinConvertThisToObject();
- virtual void callValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result);
- virtual void callProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Temp *result);
- virtual void callSubscript(IR::Expr *base, IR::Expr *index, IR::ExprList *args, IR::Temp *result);
- virtual void convertType(IR::Temp *source, IR::Temp *target);
- virtual void loadThisObject(IR::Temp *temp);
- virtual void loadQmlIdArray(IR::Temp *temp);
- virtual void loadQmlImportedScripts(IR::Temp *temp);
- virtual void loadQmlContextObject(IR::Temp *temp);
- virtual void loadQmlScopeObject(IR::Temp *temp);
- virtual void loadQmlSingleton(const QString &name, IR::Temp *temp);
- virtual void loadConst(IR::Const *sourceConst, IR::Temp *targetTemp);
- virtual void loadString(const QString &str, IR::Temp *targetTemp);
- virtual void loadRegexp(IR::RegExp *sourceRegexp, IR::Temp *targetTemp);
- virtual void getActivationProperty(const IR::Name *name, IR::Temp *temp);
+ virtual void callValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result);
+ virtual void callProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr *result);
+ virtual void callSubscript(IR::Expr *base, IR::Expr *index, IR::ExprList *args, IR::Expr *result);
+ virtual void convertType(IR::Expr *source, IR::Expr *target);
+ virtual void loadThisObject(IR::Expr *temp);
+ virtual void loadQmlIdArray(IR::Expr *target);
+ virtual void loadQmlImportedScripts(IR::Expr *target);
+ virtual void loadQmlContextObject(IR::Expr *target);
+ virtual void loadQmlScopeObject(IR::Expr *target);
+ virtual void loadQmlSingleton(const QString &name, IR::Expr *target);
+ virtual void loadConst(IR::Const *sourceConst, IR::Expr *target);
+ virtual void loadString(const QString &str, IR::Expr *target);
+ virtual void loadRegexp(IR::RegExp *sourceRegexp, IR::Expr *target);
+ virtual void getActivationProperty(const IR::Name *name, IR::Expr *target);
virtual void setActivationProperty(IR::Expr *source, const QString &targetName);
- virtual void initClosure(IR::Closure *closure, IR::Temp *target);
- virtual void getProperty(IR::Expr *base, const QString &name, IR::Temp *target);
+ virtual void initClosure(IR::Closure *closure, IR::Expr *target);
+ virtual void getProperty(IR::Expr *base, const QString &name, IR::Expr *target);
+ virtual void getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, IR::Expr *target);
virtual void setProperty(IR::Expr *source, IR::Expr *targetBase, const QString &targetName);
virtual void setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex);
- virtual void getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, IR::Temp *target);
- virtual void getElement(IR::Expr *base, IR::Expr *index, IR::Temp *target);
+ virtual void getElement(IR::Expr *base, IR::Expr *index, IR::Expr *target);
virtual void setElement(IR::Expr *source, IR::Expr *targetBase, IR::Expr *targetIndex);
- virtual void copyValue(IR::Temp *sourceTemp, IR::Temp *targetTemp);
- virtual void swapValues(IR::Temp *sourceTemp, IR::Temp *targetTemp);
- virtual void unop(IR::AluOp oper, IR::Temp *sourceTemp, IR::Temp *targetTemp);
- virtual void binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target);
+ virtual void copyValue(IR::Expr *source, IR::Expr *target);
+ virtual void swapValues(IR::Expr *source, IR::Expr *target);
+ virtual void unop(IR::AluOp oper, IR::Expr *sourceTemp, IR::Expr *target);
+ virtual void binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *target);
typedef Assembler::Address Address;
typedef Assembler::Pointer Pointer;
@@ -148,9 +148,9 @@ protected:
return _as->stackLayout().callDataAddress();
}
- virtual void constructActivationProperty(IR::Name *func, IR::ExprList *args, IR::Temp *result);
- virtual void constructProperty(IR::Temp *base, const QString &name, IR::ExprList *args, IR::Temp *result);
- virtual void constructValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result);
+ virtual void constructActivationProperty(IR::Name *func, IR::ExprList *args, IR::Expr *result);
+ virtual void constructProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr*result);
+ virtual void constructValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result);
virtual void visitJump(IR::Jump *);
virtual void visitCJump(IR::CJump *);
@@ -167,44 +167,51 @@ protected:
void visitCJumpEqual(IR::Binop *binop, IR::BasicBlock *trueBlock, IR::BasicBlock *falseBlock);
private:
- void convertTypeSlowPath(IR::Temp *source, IR::Temp *target);
- void convertTypeToDouble(IR::Temp *source, IR::Temp *target);
- void convertTypeToBool(IR::Temp *source, IR::Temp *target);
- void convertTypeToSInt32(IR::Temp *source, IR::Temp *target);
- void convertTypeToUInt32(IR::Temp *source, IR::Temp *target);
+ void convertTypeSlowPath(IR::Expr *source, IR::Expr *target);
+ void convertTypeToDouble(IR::Expr *source, IR::Expr *target);
+ void convertTypeToBool(IR::Expr *source, IR::Expr *target);
+ void convertTypeToSInt32(IR::Expr *source, IR::Expr *target);
+ void convertTypeToUInt32(IR::Expr *source, IR::Expr *target);
- void convertIntToDouble(IR::Temp *source, IR::Temp *target)
+ void convertIntToDouble(IR::Expr *source, IR::Expr *target)
{
- if (target->kind == IR::Temp::PhysicalRegister) {
- _as->convertInt32ToDouble(_as->toInt32Register(source, Assembler::ScratchRegister),
- (Assembler::FPRegisterID) target->index);
- } else {
- _as->convertInt32ToDouble(_as->toInt32Register(source, Assembler::ScratchRegister),
- Assembler::FPGpr0);
- _as->storeDouble(Assembler::FPGpr0, _as->stackSlotPointer(target));
+ if (IR::Temp *targetTemp = target->asTemp()) {
+ if (targetTemp->kind == IR::Temp::PhysicalRegister) {
+ _as->convertInt32ToDouble(_as->toInt32Register(source, Assembler::ScratchRegister),
+ (Assembler::FPRegisterID) targetTemp->index);
+ return;
+ }
}
+
+ _as->convertInt32ToDouble(_as->toInt32Register(source, Assembler::ScratchRegister),
+ Assembler::FPGpr0);
+ _as->storeDouble(Assembler::FPGpr0, _as->loadAddress(Assembler::ScratchRegister, target));
}
- void convertUIntToDouble(IR::Temp *source, IR::Temp *target)
+ void convertUIntToDouble(IR::Expr *source, IR::Expr *target)
{
Assembler::RegisterID tmpReg = Assembler::ScratchRegister;
Assembler::RegisterID reg = _as->toInt32Register(source, tmpReg);
- if (target->kind == IR::Temp::PhysicalRegister) {
- _as->convertUInt32ToDouble(reg, (Assembler::FPRegisterID) target->index, tmpReg);
- } else {
- _as->convertUInt32ToDouble(_as->toUInt32Register(source, tmpReg),
- Assembler::FPGpr0, tmpReg);
- _as->storeDouble(Assembler::FPGpr0, _as->stackSlotPointer(target));
+ if (IR::Temp *targetTemp = target->asTemp()) {
+ if (targetTemp->kind == IR::Temp::PhysicalRegister) {
+ _as->convertUInt32ToDouble(reg, (Assembler::FPRegisterID) targetTemp->index, tmpReg);
+ return;
+ }
}
+
+ _as->convertUInt32ToDouble(_as->toUInt32Register(source, tmpReg),
+ Assembler::FPGpr0, tmpReg);
+ _as->storeDouble(Assembler::FPGpr0, _as->loadAddress(tmpReg, target));
}
- void convertIntToBool(IR::Temp *source, IR::Temp *target)
+ void convertIntToBool(IR::Expr *source, IR::Expr *target)
{
- Assembler::RegisterID reg = target->kind == IR::Temp::PhysicalRegister
- ? (Assembler::RegisterID) target->index
- : Assembler::ScratchRegister;
+ Assembler::RegisterID reg = Assembler::ScratchRegister;
+ if (IR::Temp *targetTemp = target->asTemp())
+ if (targetTemp->kind == IR::Temp::PhysicalRegister)
+ reg = (Assembler::RegisterID) targetTemp->index;
_as->move(_as->toInt32Register(source, reg), reg);
_as->compare32(Assembler::NotEqual, reg, Assembler::TrustedImm32(0), reg);
_as->storeBool(reg, target);
@@ -247,7 +254,7 @@ private:
QSet<IR::Jump *> _removableJumps;
Assembler* _as;
- CompilationUnit *compilationUnit;
+ QScopedPointer<CompilationUnit> compilationUnit;
QQmlEnginePrivate *qmlEngine;
};
diff --git a/src/qml/jit/qv4regalloc.cpp b/src/qml/jit/qv4regalloc.cpp
index b5765cd589..52c2936352 100644
--- a/src/qml/jit/qv4regalloc.cpp
+++ b/src/qml/jit/qv4regalloc.cpp
@@ -44,9 +44,9 @@
#include <algorithm>
-//#define DEBUG_REGALLOC
-
namespace {
+enum { DebugRegAlloc = 0 };
+
struct Use {
enum RegisterFlag { MustHaveRegister = 0, CouldHaveRegister = 1 };
unsigned flag : 1;
@@ -68,45 +68,135 @@ using namespace QV4::IR;
namespace QV4 {
namespace JIT {
+namespace {
+class IRPrinterWithPositions: public IRPrinter
+{
+ LifeTimeIntervals::Ptr intervals;
+ const int positionSize;
+
+public:
+ IRPrinterWithPositions(QTextStream *out, const LifeTimeIntervals::Ptr &intervals)
+ : IRPrinter(out)
+ , intervals(intervals)
+ , positionSize(QString::number(intervals->lastPosition()).size())
+ {}
+
+protected:
+ void addStmtNr(Stmt *s)
+ {
+ QString posStr;
+ int pos = intervals->positionForStatement(s);
+ if (pos != Stmt::InvalidId)
+ posStr = QString::number(pos);
+ *out << posStr.rightJustified(positionSize);
+ if (pos == Stmt::InvalidId)
+ *out << " ";
+ else
+ *out << ": ";
+ }
+};
+
+class IRPrinterWithRegisters: public IRPrinterWithPositions
+{
+ const RegisterInformation &_registerInformation;
+ QHash<int, const RegisterInfo *> _infoForRegularRegister;
+ QHash<int, const RegisterInfo *> _infoForFPRegister;
+
+public:
+ IRPrinterWithRegisters(QTextStream *out, const LifeTimeIntervals::Ptr &intervals,
+ const RegisterInformation &registerInformation)
+ : IRPrinterWithPositions(out, intervals)
+ , _registerInformation(registerInformation)
+ {
+ for (int i = 0, ei = _registerInformation.size(); i != ei; ++i)
+ if (_registerInformation.at(i).isRegularRegister())
+ _infoForRegularRegister.insert(_registerInformation.at(i).reg<int>(),
+ &_registerInformation.at(i));
+ else
+ _infoForFPRegister.insert(_registerInformation.at(i).reg<int>(),
+ &_registerInformation.at(i));
+ }
+
+protected:
+ void visitTemp(Temp *e)
+ {
+ switch (e->kind) {
+ case Temp::PhysicalRegister: {
+ const RegisterInfo *ri = e->type == DoubleType ? _infoForFPRegister.value(e->index, 0)
+ : _infoForRegularRegister.value(e->index, 0);
+ if (ri) {
+ *out << dumpStart(e);
+ *out << ri->prettyName();
+ *out << dumpEnd(e);
+ break;
+ }
+ }
+ default:
+ IRPrinterWithPositions::visitTemp(e);
+ }
+ }
+};
+}
+
class RegAllocInfo: public IRDecoder
{
struct Def {
- unsigned defStmt : 30;
+ unsigned valid : 1;
unsigned canHaveReg : 1;
unsigned isPhiTarget : 1;
- Def(): defStmt(0), canHaveReg(0), isPhiTarget(0) {}
- Def(int defStmt, bool canHaveReg, bool isPhiTarget)
- : defStmt(defStmt), canHaveReg(canHaveReg), isPhiTarget(isPhiTarget)
+ Def(): valid(0), canHaveReg(0), isPhiTarget(0) {}
+ Def(bool canHaveReg, bool isPhiTarget)
+ : valid(1), canHaveReg(canHaveReg), isPhiTarget(isPhiTarget)
{
- Q_ASSERT(defStmt > 0);
- Q_ASSERT(defStmt < (1 << 30));
}
- bool isValid() const { return defStmt != 0; } // 0 is invalid, as stmt numbers start at 1.
+ bool isValid() const { return valid != 0; }
};
+ IR::LifeTimeIntervals::Ptr _lifeTimeIntervals;
+ BasicBlock *_currentBB;
Stmt *_currentStmt;
- QHash<Temp, Def> _defs;
- QHash<Temp, QList<Use> > _uses;
- QList<int> _calls;
- QHash<Temp, QList<Temp> > _hints;
+ std::vector<Def> _defs;
+ std::vector<std::vector<Use> > _uses;
+ std::vector<int> _calls;
+ std::vector<QList<Temp> > _hints;
+
+ int defPosition(Stmt *s) const
+ {
+ return usePosition(s) + 1;
+ }
+
+ int usePosition(Stmt *s) const
+ {
+ return _lifeTimeIntervals->positionForStatement(s);
+ }
public:
- RegAllocInfo(): _currentStmt(0) {}
+ RegAllocInfo(): _currentBB(0), _currentStmt(0) {}
- void collect(IR::Function *function)
+ void collect(IR::Function *function, const IR::LifeTimeIntervals::Ptr &lifeTimeIntervals)
{
+ _lifeTimeIntervals = lifeTimeIntervals;
+ _defs.resize(function->tempCount);
+ _uses.resize(function->tempCount);
+ _calls.reserve(function->statementCount() / 3);
+ _hints.resize(function->tempCount);
+
foreach (BasicBlock *bb, function->basicBlocks()) {
+ _currentBB = bb;
foreach (Stmt *s, bb->statements()) {
- Q_ASSERT(s->id > 0);
_currentStmt = s;
s->accept(this);
}
}
}
- QList<Use> uses(const Temp &t) const { return _uses[t]; }
+ const std::vector<Use> &uses(const Temp &t) const
+ {
+ return _uses[t.index];
+ }
+
bool useMustHaveReg(const Temp &t, int position) {
foreach (const Use &use, uses(t))
if (use.pos == position)
@@ -121,45 +211,52 @@ public:
return false;
}
- int def(const Temp &t) const {
- Q_ASSERT(_defs[t].isValid());
- return _defs[t].defStmt;
- }
bool canHaveRegister(const Temp &t) const {
- Q_ASSERT(_defs[t].isValid());
- return _defs[t].canHaveReg;
+ Q_ASSERT(_defs[t.index].isValid());
+ return _defs[t.index].canHaveReg;
}
bool isPhiTarget(const Temp &t) const {
- Q_ASSERT(_defs[t].isValid());
- return _defs[t].isPhiTarget;
+ Q_ASSERT(_defs[t.index].isValid());
+ return _defs[t.index].isPhiTarget;
}
- const QList<int> &calls() const { return _calls; }
- QList<Temp> hints(const Temp &t) const { return _hints[t]; }
+ const std::vector<int> &calls() const { return _calls; }
+ const QList<Temp> &hints(const Temp &t) const { return _hints[t.index]; }
void addHint(const Temp &t, int physicalRegister)
+ { addHint(t, Temp::PhysicalRegister, physicalRegister); }
+
+ void addHint(const Temp &t, Temp::Kind kind, int hintedIndex)
{
+ QList<Temp> &hints = _hints[t.index];
+ foreach (const Temp &hint, hints)
+ if (hint.index == hintedIndex)
+ return;
+
Temp hint;
- hint.init(Temp::PhysicalRegister, physicalRegister, 0);
- _hints[t].append(hint);
+ hint.init(kind, hintedIndex);
+ hints.append(hint);
}
-#ifdef DEBUG_REGALLOC
void dump() const
{
+ if (!DebugRegAlloc)
+ return;
+
QTextStream qout(stdout, QIODevice::WriteOnly);
+ IRPrinterWithPositions printer(&qout, _lifeTimeIntervals);
qout << "RegAllocInfo:" << endl << "Defs/uses:" << endl;
- QList<Temp> temps = _defs.keys();
- std::sort(temps.begin(), temps.end());
- foreach (const Temp &t, temps) {
- t.dump(qout);
- qout << " def at " << _defs[t].defStmt << " ("
+ for (unsigned t = 0; t < _defs.size(); ++t) {
+ const std::vector<Use> &uses = _uses[t];
+ if (uses.empty())
+ continue;
+ qout << "%" << t <<": "
+ << " ("
<< (_defs[t].canHaveReg ? "can" : "can NOT")
<< " have a register, and "
- << (isPhiTarget(t) ? "is" : "is NOT")
+ << (_defs[t].isPhiTarget ? "is" : "is NOT")
<< " defined by a phi node), uses at: ";
- const QList<Use> &uses = _uses[t];
- for (int i = 0; i < uses.size(); ++i) {
+ for (unsigned i = 0; i < uses.size(); ++i) {
if (i > 0) qout << ", ";
qout << uses[i].pos;
if (uses[i].mustHaveRegister()) qout << "(R)"; else qout << "(S)";
@@ -168,66 +265,62 @@ public:
}
qout << "Calls at: ";
- for (int i = 0; i < _calls.size(); ++i) {
+ for (unsigned i = 0; i < _calls.size(); ++i) {
if (i > 0) qout << ", ";
qout << _calls[i];
}
qout << endl;
qout << "Hints:" << endl;
- QList<Temp> hinted = _hints.keys();
- if (hinted.isEmpty())
- qout << "\t(none)" << endl;
- std::sort(hinted.begin(), hinted.end());
- foreach (const Temp &t, hinted) {
- qout << "\t";
- t.dump(qout);
- qout << ": ";
+ for (unsigned t = 0; t < _hints.size(); ++t) {
+ if (_uses[t].empty())
+ continue;
+ qout << "\t%" << t << ": ";
QList<Temp> hints = _hints[t];
for (int i = 0; i < hints.size(); ++i) {
if (i > 0) qout << ", ";
- hints[i].dump(qout);
+ printer.print(hints[i]);
}
qout << endl;
}
}
-#endif // DEBUG_REGALLOC
protected: // IRDecoder
- virtual void callBuiltinInvalid(IR::Name *, IR::ExprList *, IR::Temp *) {}
- virtual void callBuiltinTypeofMember(IR::Expr *, const QString &, IR::Temp *) {}
- virtual void callBuiltinTypeofSubscript(IR::Expr *, IR::Expr *, IR::Temp *) {}
- virtual void callBuiltinTypeofName(const QString &, IR::Temp *) {}
- virtual void callBuiltinTypeofValue(IR::Expr *, IR::Temp *) {}
- virtual void callBuiltinDeleteMember(IR::Temp *, const QString &, IR::Temp *) {}
- virtual void callBuiltinDeleteSubscript(IR::Temp *, IR::Expr *, IR::Temp *) {}
- virtual void callBuiltinDeleteName(const QString &, IR::Temp *) {}
- virtual void callBuiltinDeleteValue(IR::Temp *) {}
+ virtual void callBuiltinInvalid(IR::Name *, IR::ExprList *, IR::Expr *) {}
+ virtual void callBuiltinTypeofMember(IR::Expr *, const QString &, IR::Expr *) {}
+ virtual void callBuiltinTypeofSubscript(IR::Expr *, IR::Expr *, IR::Expr *) {}
+ virtual void callBuiltinTypeofName(const QString &, IR::Expr *) {}
+ virtual void callBuiltinTypeofValue(IR::Expr *, IR::Expr *) {}
+ virtual void callBuiltinDeleteMember(IR::Expr *, const QString &, IR::Expr *) {}
+ virtual void callBuiltinDeleteSubscript(IR::Expr *, IR::Expr *, IR::Expr *) {}
+ virtual void callBuiltinDeleteName(const QString &, IR::Expr *) {}
+ virtual void callBuiltinDeleteValue(IR::Expr *) {}
virtual void callBuiltinThrow(IR::Expr *) {}
virtual void callBuiltinReThrow() {}
- virtual void callBuiltinUnwindException(IR::Temp *) {}
+ virtual void callBuiltinUnwindException(IR::Expr *) {}
virtual void callBuiltinPushCatchScope(const QString &) {};
- virtual void callBuiltinForeachIteratorObject(IR::Expr *, IR::Temp *) {}
+ virtual void callBuiltinForeachIteratorObject(IR::Expr *, IR::Expr *) {}
virtual void callBuiltinForeachNextProperty(IR::Temp *, IR::Temp *) {}
- virtual void callBuiltinForeachNextPropertyname(IR::Temp *, IR::Temp *) {}
- virtual void callBuiltinPushWithScope(IR::Temp *) {}
+ virtual void callBuiltinForeachNextPropertyname(IR::Expr *, IR::Expr *) {}
+ virtual void callBuiltinPushWithScope(IR::Expr *) {}
virtual void callBuiltinPopScope() {}
virtual void callBuiltinDeclareVar(bool , const QString &) {}
- virtual void callBuiltinDefineArray(IR::Temp *, IR::ExprList *) {}
- virtual void callBuiltinDefineObjectLiteral(IR::Temp *, int, IR::ExprList *, IR::ExprList *, bool) {}
- virtual void callBuiltinSetupArgumentObject(IR::Temp *) {}
+ virtual void callBuiltinDefineArray(IR::Expr *, IR::ExprList *) {}
+ virtual void callBuiltinDefineObjectLiteral(IR::Expr *, int, IR::ExprList *, IR::ExprList *, bool) {}
+ virtual void callBuiltinSetupArgumentObject(IR::Expr *) {}
virtual void callBuiltinConvertThisToObject() {}
- virtual void callValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result)
+ virtual void callValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result)
{
addDef(result);
- addUses(value, Use::CouldHaveRegister);
+ if (IR::Temp *tempValue = value->asTemp())
+ addUses(tempValue, Use::CouldHaveRegister);
addUses(args, Use::CouldHaveRegister);
addCall();
}
virtual void callProperty(IR::Expr *base, const QString &name, IR::ExprList *args,
- IR::Temp *result)
+ IR::Expr *result)
{
Q_UNUSED(name)
@@ -238,7 +331,7 @@ protected: // IRDecoder
}
virtual void callSubscript(IR::Expr *base, IR::Expr *index, IR::ExprList *args,
- IR::Temp *result)
+ IR::Expr *result)
{
addDef(result);
addUses(base->asTemp(), Use::CouldHaveRegister);
@@ -247,7 +340,7 @@ protected: // IRDecoder
addCall();
}
- virtual void convertType(IR::Temp *source, IR::Temp *target)
+ virtual void convertType(IR::Expr *source, IR::Expr *target)
{
addDef(target);
@@ -310,22 +403,24 @@ protected: // IRDecoder
break;
}
- addUses(source, sourceReg);
+ Temp *sourceTemp = source->asTemp();
+ if (sourceTemp)
+ addUses(sourceTemp, sourceReg);
if (needsCall)
addCall();
- else
- addHint(target, source);
+ else if (target->asTemp())
+ addHint(target->asTemp(), sourceTemp);
}
- virtual void constructActivationProperty(IR::Name *, IR::ExprList *args, IR::Temp *result)
+ virtual void constructActivationProperty(IR::Name *, IR::ExprList *args, IR::Expr *result)
{
addDef(result);
addUses(args, Use::CouldHaveRegister);
addCall();
}
- virtual void constructProperty(IR::Temp *base, const QString &, IR::ExprList *args, IR::Temp *result)
+ virtual void constructProperty(IR::Expr *base, const QString &, IR::ExprList *args, IR::Expr *result)
{
addDef(result);
addUses(base, Use::CouldHaveRegister);
@@ -333,7 +428,7 @@ protected: // IRDecoder
addCall();
}
- virtual void constructValue(IR::Temp *value, IR::ExprList *args, IR::Temp *result)
+ virtual void constructValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result)
{
addDef(result);
addUses(value, Use::CouldHaveRegister);
@@ -341,30 +436,30 @@ protected: // IRDecoder
addCall();
}
- virtual void loadThisObject(IR::Temp *temp)
+ virtual void loadThisObject(IR::Expr *temp)
{
addDef(temp);
}
- virtual void loadQmlIdArray(IR::Temp *temp)
+ virtual void loadQmlIdArray(IR::Expr *temp)
{
addDef(temp);
addCall();
}
- virtual void loadQmlImportedScripts(IR::Temp *temp)
+ virtual void loadQmlImportedScripts(IR::Expr *temp)
{
addDef(temp);
addCall();
}
- virtual void loadQmlContextObject(Temp *temp)
+ virtual void loadQmlContextObject(Expr *temp)
{
addDef(temp);
addCall();
}
- virtual void loadQmlScopeObject(Temp *temp)
+ virtual void loadQmlScopeObject(Expr *temp)
{
Q_UNUSED(temp);
@@ -372,7 +467,7 @@ protected: // IRDecoder
addCall();
}
- virtual void loadQmlSingleton(const QString &/*name*/, Temp *temp)
+ virtual void loadQmlSingleton(const QString &/*name*/, Expr *temp)
{
Q_UNUSED(temp);
@@ -380,21 +475,21 @@ protected: // IRDecoder
addCall();
}
- virtual void loadConst(IR::Const *sourceConst, IR::Temp *targetTemp)
+ virtual void loadConst(IR::Const *sourceConst, Expr *targetTemp)
{
Q_UNUSED(sourceConst);
addDef(targetTemp);
}
- virtual void loadString(const QString &str, IR::Temp *targetTemp)
+ virtual void loadString(const QString &str, Expr *targetTemp)
{
Q_UNUSED(str);
addDef(targetTemp);
}
- virtual void loadRegexp(IR::RegExp *sourceRegexp, IR::Temp *targetTemp)
+ virtual void loadRegexp(IR::RegExp *sourceRegexp, Expr *targetTemp)
{
Q_UNUSED(sourceRegexp);
@@ -402,7 +497,7 @@ protected: // IRDecoder
addCall();
}
- virtual void getActivationProperty(const IR::Name *, IR::Temp *temp)
+ virtual void getActivationProperty(const IR::Name *, Expr *temp)
{
addDef(temp);
addCall();
@@ -414,7 +509,7 @@ protected: // IRDecoder
addCall();
}
- virtual void initClosure(IR::Closure *closure, IR::Temp *target)
+ virtual void initClosure(IR::Closure *closure, Expr *target)
{
Q_UNUSED(closure);
@@ -422,7 +517,7 @@ protected: // IRDecoder
addCall();
}
- virtual void getProperty(IR::Expr *base, const QString &, IR::Temp *target)
+ virtual void getProperty(IR::Expr *base, const QString &, Expr *target)
{
addDef(target);
addUses(base->asTemp(), Use::CouldHaveRegister);
@@ -443,14 +538,14 @@ protected: // IRDecoder
addCall();
}
- virtual void getQObjectProperty(IR::Expr *base, int /*propertyIndex*/, bool /*captureRequired*/, int /*attachedPropertiesId*/, IR::Temp *target)
+ virtual void getQObjectProperty(IR::Expr *base, int /*propertyIndex*/, bool /*captureRequired*/, int /*attachedPropertiesId*/, IR::Expr *target)
{
addDef(target);
addUses(base->asTemp(), Use::CouldHaveRegister);
addCall();
}
- virtual void getElement(IR::Expr *base, IR::Expr *index, IR::Temp *target)
+ virtual void getElement(IR::Expr *base, IR::Expr *index, Expr *target)
{
addDef(target);
addUses(base->asTemp(), Use::CouldHaveRegister);
@@ -466,25 +561,30 @@ protected: // IRDecoder
addCall();
}
- virtual void copyValue(IR::Temp *sourceTemp, IR::Temp *targetTemp)
+ virtual void copyValue(Expr *source, Expr *target)
{
- addDef(targetTemp);
+ addDef(target);
+ Temp *sourceTemp = source->asTemp();
+ if (!sourceTemp)
+ return;
addUses(sourceTemp, Use::CouldHaveRegister);
- addHint(targetTemp, sourceTemp);
+ Temp *targetTemp = target->asTemp();
+ if (targetTemp)
+ addHint(targetTemp, sourceTemp);
}
- virtual void swapValues(IR::Temp *, IR::Temp *)
+ virtual void swapValues(Expr *, Expr *)
{
// Inserted by the register allocator, so it cannot occur here.
Q_UNREACHABLE();
}
- virtual void unop(AluOp oper, Temp *sourceTemp, Temp *targetTemp)
+ virtual void unop(AluOp oper, Expr *source, Expr *target)
{
- addDef(targetTemp);
+ addDef(target);
bool needsCall = true;
- if (oper == OpNot && sourceTemp->type == IR::BoolType && targetTemp->type == IR::BoolType)
+ if (oper == OpNot && source->type == IR::BoolType && target->type == IR::BoolType)
needsCall = false;
#if 0 // TODO: change masm to generate code
@@ -504,15 +604,18 @@ protected: // IRDecoder
}
#endif
+ IR::Temp *sourceTemp = source->asTemp();
if (needsCall) {
- addUses(sourceTemp, Use::CouldHaveRegister);
+ if (sourceTemp)
+ addUses(sourceTemp, Use::CouldHaveRegister);
addCall();
} else {
- addUses(sourceTemp, Use::MustHaveRegister);
+ if (sourceTemp)
+ addUses(sourceTemp, Use::MustHaveRegister);
}
}
- virtual void binop(AluOp oper, Expr *leftSource, Expr *rightSource, Temp *target)
+ virtual void binop(AluOp oper, Expr *leftSource, Expr *rightSource, Expr *target)
{
bool needsCall = true;
@@ -590,25 +693,31 @@ protected: // IRDecoder
if (Temp *t = e->asTemp()) {
addUses(t, Use::CouldHaveRegister);
addHint(s->targetTemp, t);
+ addHint(t, s->targetTemp);
}
}
}
protected:
- virtual void callBuiltin(IR::Call *c, IR::Temp *result)
+ virtual void callBuiltin(IR::Call *c, IR::Expr *result)
{
addDef(result);
- addUses(c->base->asTemp(), Use::CouldHaveRegister);
+ addUses(c->base, Use::CouldHaveRegister);
addUses(c->args, Use::CouldHaveRegister);
addCall();
}
private:
- void addDef(Temp *t, bool isPhiTarget = false)
+ void addDef(Expr *e, bool isPhiTarget = false)
{
+ if (!e)
+ return;
+ Temp *t = e->asTemp();
+ if (!t)
+ return;
if (!t || t->kind != Temp::VirtualRegister)
return;
- Q_ASSERT(!_defs.contains(*t));
+ Q_ASSERT(!_defs[t->index].isValid());
bool canHaveReg = true;
switch (t->type) {
case QObjectType:
@@ -622,25 +731,40 @@ private:
break;
}
- _defs[*t] = Def(_currentStmt->id, canHaveReg, isPhiTarget);
+ _defs[t->index] = Def(canHaveReg, isPhiTarget);
}
- void addUses(Temp *t, Use::RegisterFlag flag)
+ void addUses(Expr *e, Use::RegisterFlag flag)
{
- Q_ASSERT(_currentStmt->id > 0);
+ int usePos = usePosition(_currentStmt);
+ if (usePos == Stmt::InvalidId)
+ usePos = _lifeTimeIntervals->startPosition(_currentBB);
+ Q_ASSERT(usePos > 0);
+ if (!e)
+ return;
+ Temp *t = e->asTemp();
+ if (!t)
+ return;
if (t && t->kind == Temp::VirtualRegister)
- _uses[*t].append(Use(_currentStmt->id, flag));
+ _uses[t->index].push_back(Use(usePosition(_currentStmt), flag));
}
void addUses(ExprList *l, Use::RegisterFlag flag)
{
for (ExprList *it = l; it; it = it->next)
- addUses(it->expr->asTemp(), flag);
+ addUses(it->expr, flag);
}
void addCall()
{
- _calls.append(_currentStmt->id);
+ _calls.push_back(usePosition(_currentStmt));
+ }
+
+ void addHint(Expr *hinted, Temp *hint1, Temp *hint2 = 0)
+ {
+ if (hinted)
+ if (Temp *hintedTemp = hinted->asTemp())
+ addHint(hintedTemp, hint1, hint2);
}
void addHint(Temp *hinted, Temp *hint1, Temp *hint2 = 0)
@@ -648,9 +772,9 @@ private:
if (!hinted || hinted->kind != Temp::VirtualRegister)
return;
if (hint1 && hint1->kind == Temp::VirtualRegister && hinted->type == hint1->type)
- _hints[*hinted].append(*hint1);
+ addHint(*hinted, Temp::VirtualRegister, hint1->index);
if (hint2 && hint2->kind == Temp::VirtualRegister && hinted->type == hint2->type)
- _hints[*hinted].append(*hint2);
+ addHint(*hinted, Temp::VirtualRegister, hint2->index);
}
};
@@ -666,16 +790,15 @@ using namespace QT_PREPEND_NAMESPACE(QV4);
namespace {
class ResolutionPhase: protected StmtVisitor, protected ExprVisitor {
- const QVector<LifeTimeInterval> &_intervals;
- QVector<const LifeTimeInterval *> _unprocessed;
+ Q_DISABLE_COPY(ResolutionPhase)
+
+ LifeTimeIntervals::Ptr _intervals;
+ QVector<LifeTimeInterval *> _unprocessed;
IR::Function *_function;
-#if !defined(QT_NO_DEBUG)
- RegAllocInfo *_info;
-#endif
- const QHash<IR::Temp, int> &_assignedSpillSlots;
+ const std::vector<int> &_assignedSpillSlots;
QHash<IR::Temp, const LifeTimeInterval *> _intervalForTemp;
- const QVector<int> &_intRegs;
- const QVector<int> &_fpRegs;
+ const QVector<const RegisterInfo *> &_intRegs;
+ const QVector<const RegisterInfo *> &_fpRegs;
Stmt *_currentStmt;
QVector<Move *> _loads;
@@ -685,54 +808,64 @@ class ResolutionPhase: protected StmtVisitor, protected ExprVisitor {
QHash<BasicBlock *, QList<const LifeTimeInterval *> > _liveAtEnd;
public:
- ResolutionPhase(const QVector<LifeTimeInterval> &intervals, IR::Function *function, RegAllocInfo *info,
- const QHash<IR::Temp, int> &assignedSpillSlots,
- const QVector<int> &intRegs, const QVector<int> &fpRegs)
+ ResolutionPhase(const QVector<LifeTimeInterval *> &unprocessed,
+ const LifeTimeIntervals::Ptr &intervals,
+ IR::Function *function,
+ const std::vector<int> &assignedSpillSlots,
+ const QVector<const RegisterInfo *> &intRegs,
+ const QVector<const RegisterInfo *> &fpRegs)
: _intervals(intervals)
, _function(function)
-#if !defined(QT_NO_DEBUG)
- , _info(info)
-#endif
, _assignedSpillSlots(assignedSpillSlots)
, _intRegs(intRegs)
, _fpRegs(fpRegs)
{
-#if defined(QT_NO_DEBUG)
- Q_UNUSED(info)
-#endif
-
- _unprocessed.resize(_intervals.size());
- for (int i = 0, ei = _intervals.size(); i != ei; ++i)
- _unprocessed[i] = &_intervals[i];
-
+ _unprocessed = unprocessed;
_liveAtStart.reserve(function->basicBlockCount());
_liveAtEnd.reserve(function->basicBlockCount());
}
void run() {
renumber();
- Optimizer::showMeTheCode(_function);
+ if (DebugRegAlloc) {
+ QTextStream qout(stdout, QIODevice::WriteOnly);
+ IRPrinterWithPositions(&qout, _intervals).print(_function);
+ }
resolve();
}
private:
+ int defPosition(Stmt *s) const
+ {
+ return usePosition(s) + 1;
+ }
+
+ int usePosition(Stmt *s) const
+ {
+ return _intervals->positionForStatement(s);
+ }
+
void renumber()
{
foreach (BasicBlock *bb, _function->basicBlocks()) {
+ _currentStmt = 0;
+
QVector<Stmt *> statements = bb->statements();
QVector<Stmt *> newStatements;
newStatements.reserve(bb->statements().size() + 7);
- bool seenFirstNonPhiStmt = false;
+ cleanOldIntervals(_intervals->startPosition(bb));
+ addNewIntervals(_intervals->startPosition(bb));
+ _liveAtStart[bb] = _intervalForTemp.values();
+
for (int i = 0, ei = statements.size(); i != ei; ++i) {
- _currentStmt = statements[i];
+ _currentStmt = statements.at(i);
_loads.clear();
_stores.clear();
- addNewIntervals();
- if (!seenFirstNonPhiStmt && !_currentStmt->asPhi()) {
- seenFirstNonPhiStmt = true;
- _liveAtStart[bb] = _intervalForTemp.values();
- }
+ if (_currentStmt->asTerminator())
+ addNewIntervals(usePosition(_currentStmt));
+ else
+ addNewIntervals(defPosition(_currentStmt));
_currentStmt->accept(this);
foreach (Move *load, _loads)
newStatements.append(load);
@@ -744,90 +877,71 @@ private:
newStatements.append(store);
}
- cleanOldIntervals();
+ cleanOldIntervals(_intervals->endPosition(bb));
_liveAtEnd[bb] = _intervalForTemp.values();
-#ifdef DEBUG_REGALLOC
- QTextStream os(stdout, QIODevice::WriteOnly);
- os << "Intervals live at the start of L" << bb->index << ":" << endl;
- if (_liveAtStart[bb].isEmpty())
- os << "\t(none)" << endl;
- foreach (const LifeTimeInterval *i, _liveAtStart[bb]) {
- os << "\t";
- i->dump(os);
- os << endl;
- }
- os << "Intervals live at the end of L" << bb->index << ":" << endl;
- if (_liveAtEnd[bb].isEmpty())
- os << "\t(none)" << endl;
- foreach (const LifeTimeInterval *i, _liveAtEnd[bb]) {
- os << "\t";
- i->dump(os);
- os << endl;
+ if (DebugRegAlloc) {
+ QTextStream os(stdout, QIODevice::WriteOnly);
+ os << "Intervals live at the start of L" << bb->index() << ":" << endl;
+ if (_liveAtStart[bb].isEmpty())
+ os << "\t(none)" << endl;
+ foreach (const LifeTimeInterval *i, _liveAtStart[bb]) {
+ os << "\t";
+ i->dump(os);
+ os << endl;
+ }
+ os << "Intervals live at the end of L" << bb->index() << ":" << endl;
+ if (_liveAtEnd[bb].isEmpty())
+ os << "\t(none)" << endl;
+ foreach (const LifeTimeInterval *i, _liveAtEnd[bb]) {
+ os << "\t";
+ i->dump(os);
+ os << endl;
+ }
}
-#endif
bb->setStatements(newStatements);
}
}
- void activate(const LifeTimeInterval *i)
+ void maybeGenerateSpill(Temp *t)
{
- Q_ASSERT(!i->isFixedInterval());
- _intervalForTemp[i->temp()] = i;
+ const LifeTimeInterval *i = _intervalForTemp[*t];
+ if (i->reg() == LifeTimeInterval::InvalidRegister)
+ return;
- if (i->reg() != LifeTimeInterval::Invalid) {
- // check if we need to generate spill/unspill instructions
- if (i->start() == _currentStmt->id) {
- if (i->isSplitFromInterval()) {
- int pReg = platformRegister(*i);
- _loads.append(generateUnspill(i->temp(), pReg));
- } else {
- int pReg = platformRegister(*i);
- int spillSlot = _assignedSpillSlots.value(i->temp(), -1);
- if (spillSlot != -1)
- _stores.append(generateSpill(spillSlot, i->temp().type, pReg));
- }
- }
- }
+ const RegisterInfo *pReg = platformRegister(*i);
+ Q_ASSERT(pReg);
+ int spillSlot = _assignedSpillSlots[i->temp().index];
+ if (spillSlot != RegisterAllocator::InvalidSpillSlot)
+ _stores.append(generateSpill(spillSlot, i->temp().type, pReg->reg<int>()));
}
- void addNewIntervals()
+ void addNewIntervals(int position)
{
- if (Phi *phi = _currentStmt->asPhi()) {
- // for phi nodes, only activate the range belonging to that node
- for (int it = 0, eit = _unprocessed.size(); it != eit; ++it) {
- const LifeTimeInterval *i = _unprocessed.at(it);
- if (i->start() > _currentStmt->id)
- break;
- if (i->temp() == *phi->targetTemp) {
- activate(i);
- _unprocessed.remove(it);
- break;
- }
- }
+ if (position == Stmt::InvalidId)
return;
- }
while (!_unprocessed.isEmpty()) {
const LifeTimeInterval *i = _unprocessed.first();
- if (i->start() > _currentStmt->id)
+ if (i->start() > position)
break;
- activate(i);
+ Q_ASSERT(!i->isFixedInterval());
+ _intervalForTemp[i->temp()] = i;
+// qDebug() << "-- Activating interval for temp" << i->temp().index;
_unprocessed.removeFirst();
}
}
- void cleanOldIntervals()
+ void cleanOldIntervals(int position)
{
- const int id = _currentStmt->id;
QMutableHashIterator<Temp, const LifeTimeInterval *> it(_intervalForTemp);
while (it.hasNext()) {
const LifeTimeInterval *i = it.next().value();
- if (i->end() < id || i->isFixedInterval())
+ if (i->end() < position || i->isFixedInterval())
it.remove();
}
}
@@ -840,77 +954,75 @@ private:
}
}
- void resolveEdge(BasicBlock *predecessor, BasicBlock *successor)
+ Phi *findDefPhi(const Temp &t, BasicBlock *bb) const
{
-#ifdef DEBUG_REGALLOC
- Optimizer::showMeTheCode(_function);
- qDebug() << "Resolving edge" << predecessor->index << "->" << successor->index;
-#endif // DEBUG_REGALLOC
+ foreach (Stmt *s, bb->statements()) {
+ Phi *phi = s->asPhi();
+ if (!phi)
+ return 0;
- MoveMapping mapping;
+ if (*phi->targetTemp == t)
+ return phi;
+ }
- const int predecessorEnd = predecessor->terminator()->id; // the terminator is always last and always has an id set...
- Q_ASSERT(predecessorEnd > 0); // ... but we verify it anyway for good measure.
+ Q_UNREACHABLE();
+ }
- int successorStart = -1;
- foreach (Stmt *s, successor->statements()) {
- if (s && s->id > 0) {
- successorStart = s->id;
- break;
- }
+ void resolveEdge(BasicBlock *predecessor, BasicBlock *successor)
+ {
+ if (DebugRegAlloc) {
+ qDebug() << "Resolving edge" << predecessor->index() << "->" << successor->index();
+ QTextStream qout(stdout, QIODevice::WriteOnly);
+ IRPrinterWithPositions printer(&qout, _intervals);
+ printer.print(predecessor);
+ printer.print(successor);
+ qout.flush();
}
+ MoveMapping mapping;
+
+ const int predecessorEnd = _intervals->endPosition(predecessor);
+ Q_ASSERT(predecessorEnd > 0);
+
+ int successorStart = _intervals->startPosition(successor);
Q_ASSERT(successorStart > 0);
foreach (const LifeTimeInterval *it, _liveAtStart[successor]) {
- if (it->end() < successorStart)
- continue;
-
bool isPhiTarget = false;
Expr *moveFrom = 0;
if (it->start() == successorStart) {
- foreach (Stmt *s, successor->statements()) {
- if (!s || s->id < 1)
- continue;
- if (Phi *phi = s->asPhi()) {
- if (*phi->targetTemp == it->temp()) {
- isPhiTarget = true;
- Expr *opd = phi->d->incoming[successor->in.indexOf(predecessor)];
- if (opd->asConst()) {
- moveFrom = opd;
- } else {
- Temp *t = opd->asTemp();
- Q_ASSERT(t);
-
- foreach (const LifeTimeInterval *it2, _liveAtEnd[predecessor]) {
- if (it2->temp() == *t
- && it2->reg() != LifeTimeInterval::Invalid
- && it2->covers(predecessorEnd)) {
- moveFrom = createTemp(Temp::PhysicalRegister,
- platformRegister(*it2), t->type);
- break;
- }
- }
- if (!moveFrom)
- moveFrom = createTemp(Temp::StackSlot,
- _assignedSpillSlots.value(*t, -1),
- t->type);
+ if (Phi *phi = findDefPhi(it->temp(), successor)) {
+ isPhiTarget = true;
+ Expr *opd = phi->d->incoming[successor->in.indexOf(predecessor)];
+ if (opd->asConst()) {
+ moveFrom = opd;
+ } else {
+ Temp *t = opd->asTemp();
+ Q_ASSERT(t);
+
+ foreach (const LifeTimeInterval *it2, _liveAtEnd[predecessor]) {
+ if (it2->temp() == *t
+ && it2->reg() != LifeTimeInterval::InvalidRegister
+ && it2->covers(predecessorEnd)) {
+ moveFrom = createPhysicalRegister(it2, t->type);
+ break;
}
}
- } else {
- break;
+ if (!moveFrom)
+ moveFrom = createTemp(Temp::StackSlot,
+ _assignedSpillSlots[t->index],
+ t->type);
}
}
} else {
foreach (const LifeTimeInterval *predIt, _liveAtEnd[predecessor]) {
if (predIt->temp() == it->temp()) {
- if (predIt->reg() != LifeTimeInterval::Invalid
+ if (predIt->reg() != LifeTimeInterval::InvalidRegister
&& predIt->covers(predecessorEnd)) {
- moveFrom = createTemp(Temp::PhysicalRegister, platformRegister(*predIt),
- predIt->temp().type);
+ moveFrom = createPhysicalRegister(predIt, predIt->temp().type);
} else {
- int spillSlot = _assignedSpillSlots.value(predIt->temp(), -1);
+ int spillSlot = _assignedSpillSlots[predIt->temp().index];
if (spillSlot != -1)
moveFrom = createTemp(Temp::StackSlot, spillSlot, predIt->temp().type);
}
@@ -919,14 +1031,14 @@ private:
}
}
if (!moveFrom) {
-#if !defined(QT_NO_DEBUG)
+#if !defined(QT_NO_DEBUG) && 0
bool lifeTimeHole = false;
if (it->ranges().first().start <= successorStart && it->ranges().last().end >= successorStart)
lifeTimeHole = !it->covers(successorStart);
Q_ASSERT(!_info->isPhiTarget(it->temp()) || it->isSplitFromInterval() || lifeTimeHole);
if (_info->def(it->temp()) != successorStart && !it->isSplitFromInterval()) {
- const int successorEnd = successor->terminator()->id;
+ const int successorEnd = successor->terminator()->id();
const int idx = successor->in.indexOf(predecessor);
foreach (const Use &use, _info->uses(it->temp())) {
if (use.pos == static_cast<unsigned>(successorStart)) {
@@ -956,15 +1068,15 @@ private:
}
Temp *moveTo;
- if (it->reg() == LifeTimeInterval::Invalid || !it->covers(successorStart)) {
+ if (it->reg() == LifeTimeInterval::InvalidRegister || !it->covers(successorStart)) {
if (!isPhiTarget) // if it->temp() is a phi target, skip it.
continue;
- const int spillSlot = _assignedSpillSlots.value(it->temp(), -1);
- if (spillSlot == -1)
+ const int spillSlot = _assignedSpillSlots[it->temp().index];
+ if (spillSlot == RegisterAllocator::InvalidSpillSlot)
continue; // it has a life-time hole here.
moveTo = createTemp(Temp::StackSlot, spillSlot, it->temp().type);
} else {
- moveTo = createTemp(Temp::PhysicalRegister, platformRegister(*it), it->temp().type);
+ moveTo = createPhysicalRegister(it, it->temp().type);
}
// add move to mapping
@@ -972,37 +1084,52 @@ private:
}
mapping.order();
-#ifdef DEBUG_REGALLOC
- mapping.dump();
-#endif // DEBUG_REGALLOC
+ if (DebugRegAlloc)
+ mapping.dump();
bool insertIntoPredecessor = successor->in.size() > 1;
mapping.insertMoves(insertIntoPredecessor ? predecessor : successor, _function,
insertIntoPredecessor);
+
+ if (DebugRegAlloc) {
+ qDebug() << ".. done, result:";
+ QTextStream qout(stdout, QIODevice::WriteOnly);
+ IRPrinterWithPositions printer(&qout, _intervals);
+ printer.print(predecessor);
+ printer.print(successor);
+ qout.flush();
+ }
}
Temp *createTemp(Temp::Kind kind, int index, Type type) const
{
Q_ASSERT(index >= 0);
Temp *t = _function->New<Temp>();
- t->init(kind, index, 0);
+ t->init(kind, index);
t->type = type;
return t;
}
- int platformRegister(const LifeTimeInterval &i) const
+ Temp *createPhysicalRegister(const LifeTimeInterval *i, Type type) const
+ {
+ const RegisterInfo *ri = platformRegister(*i);
+ Q_ASSERT(ri);
+ return createTemp(Temp::PhysicalRegister, ri->reg<int>(), type);
+ }
+
+ const RegisterInfo *platformRegister(const LifeTimeInterval &i) const
{
if (i.isFP())
- return _fpRegs.value(i.reg(), -1);
+ return _fpRegs.value(i.reg(), 0);
else
- return _intRegs.value(i.reg(), -1);
+ return _intRegs.value(i.reg(), 0);
}
Move *generateSpill(int spillSlot, Type type, int pReg) const
{
Q_ASSERT(spillSlot >= 0);
- Move *store = _function->New<Move>();
+ Move *store = _function->NewStmt<Move>();
store->init(createTemp(Temp::StackSlot, spillSlot, type),
createTemp(Temp::PhysicalRegister, pReg, type));
return store;
@@ -1011,9 +1138,9 @@ private:
Move *generateUnspill(const Temp &t, int pReg) const
{
Q_ASSERT(pReg >= 0);
- int spillSlot = _assignedSpillSlots.value(t, -1);
+ int spillSlot = _assignedSpillSlots[t.index];
Q_ASSERT(spillSlot != -1);
- Move *load = _function->New<Move>();
+ Move *load = _function->NewStmt<Move>();
load->init(createTemp(Temp::PhysicalRegister, pReg, t.type),
createTemp(Temp::StackSlot, spillSlot, t.type));
return load;
@@ -1027,18 +1154,30 @@ protected:
const LifeTimeInterval *i = _intervalForTemp[*t];
Q_ASSERT(i->isValid());
- if (i->reg() != LifeTimeInterval::Invalid && i->covers(_currentStmt->id)) {
- int pReg = platformRegister(*i);
+
+ if (_currentStmt != 0 && i->start() == usePosition(_currentStmt)) {
+ Q_ASSERT(i->isSplitFromInterval());
+ const RegisterInfo *pReg = platformRegister(*i);
+ Q_ASSERT(pReg);
+ _loads.append(generateUnspill(i->temp(), pReg->reg<int>()));
+ }
+
+ if (i->reg() != LifeTimeInterval::InvalidRegister &&
+ (i->covers(defPosition(_currentStmt)) ||
+ i->covers(usePosition(_currentStmt)))) {
+ const RegisterInfo *pReg = platformRegister(*i);
+ Q_ASSERT(pReg);
t->kind = Temp::PhysicalRegister;
- t->index = pReg;
+ t->index = pReg->reg<unsigned>();
} else {
- int stackSlot = _assignedSpillSlots.value(*t, -1);
+ int stackSlot = _assignedSpillSlots[t->index];
Q_ASSERT(stackSlot >= 0);
t->kind = Temp::StackSlot;
t->index = stackSlot;
}
}
+ virtual void visitArgLocal(ArgLocal *) {}
virtual void visitConst(Const *) {}
virtual void visitString(IR::String *) {}
virtual void visitRegExp(IR::RegExp *) {}
@@ -1063,21 +1202,41 @@ protected:
}
virtual void visitExp(Exp *s) { s->expr->accept(this); }
- virtual void visitMove(Move *s) { s->source->accept(this); s->target->accept(this); }
+
+ virtual void visitMove(Move *s)
+ {
+ if (Temp *t = s->target->asTemp())
+ maybeGenerateSpill(t);
+
+ s->source->accept(this);
+ s->target->accept(this);
+ }
+
virtual void visitJump(Jump *) {}
virtual void visitCJump(CJump *s) { s->cond->accept(this); }
virtual void visitRet(Ret *s) { s->expr->accept(this); }
- virtual void visitPhi(Phi *) {}
+ virtual void visitPhi(Phi *s)
+ {
+ maybeGenerateSpill(s->targetTemp);
+ }
};
} // anonymous namespace
-RegisterAllocator::RegisterAllocator(const QVector<int> &normalRegisters, const QVector<int> &fpRegisters)
- : _normalRegisters(normalRegisters)
- , _fpRegisters(fpRegisters)
+RegisterAllocator::RegisterAllocator(const QV4::JIT::RegisterInformation &registerInformation)
+ : _registerInformation(registerInformation)
{
- Q_ASSERT(normalRegisters.size() >= 2);
- Q_ASSERT(fpRegisters.size() >= 2);
- _active.reserve((normalRegisters.size() + fpRegisters.size()) * 2);
+ for (int i = 0, ei = registerInformation.size(); i != ei; ++i) {
+ const RegisterInfo &regInfo = registerInformation.at(i);
+ if (regInfo.useForRegAlloc()) {
+ if (regInfo.isRegularRegister())
+ _normalRegisters.append(&regInfo);
+ else
+ _fpRegisters.append(&regInfo);
+ }
+ }
+ Q_ASSERT(_normalRegisters.size() >= 2);
+ Q_ASSERT(_fpRegisters.size() >= 2);
+ _active.reserve((_normalRegisters.size() + _fpRegisters.size()) * 2);
_inactive.reserve(_active.size());
}
@@ -1087,54 +1246,58 @@ RegisterAllocator::~RegisterAllocator()
void RegisterAllocator::run(IR::Function *function, const Optimizer &opt)
{
- _lastAssignedRegister.reserve(function->tempCount);
- _assignedSpillSlots.reserve(function->tempCount);
+ _lastAssignedRegister.assign(function->tempCount, LifeTimeInterval::InvalidRegister);
+ _assignedSpillSlots.assign(function->tempCount, InvalidSpillSlot);
_activeSpillSlots.resize(function->tempCount);
-#ifdef DEBUG_REGALLOC
- qDebug() << "*** Running regalloc for function" << (function->name ? qPrintable(*function->name) : "NO NAME") << "***";
-#endif // DEBUG_REGALLOC
+ if (DebugRegAlloc)
+ qDebug() << "*** Running regalloc for function" << (function->name ? qPrintable(*function->name) : "NO NAME") << "***";
+
+ _lifeTimeIntervals = opt.lifeTimeIntervals();
- _unhandled = opt.lifeTimeIntervals();
+ _unhandled = _lifeTimeIntervals->intervals();
_handled.reserve(_unhandled.size());
_info.reset(new RegAllocInfo);
- _info->collect(function);
+ _info->collect(function, _lifeTimeIntervals);
-#ifdef DEBUG_REGALLOC
- {
+ if (DebugRegAlloc) {
QTextStream qout(stdout, QIODevice::WriteOnly);
qout << "Ranges:" << endl;
- QVector<LifeTimeInterval> intervals = _unhandled;
- std::sort(intervals.begin(), intervals.end(), LifeTimeInterval::lessThanForTemp);
- foreach (const LifeTimeInterval &r, intervals) {
- r.dump(qout);
+ QVector<LifeTimeInterval *> intervals = _unhandled;
+ std::reverse(intervals.begin(), intervals.end());
+ foreach (const LifeTimeInterval *r, intervals) {
+ r->dump(qout);
qout << endl;
}
+ _info->dump();
}
- _info->dump();
-#endif // DEBUG_REGALLOC
+ if (DebugRegAlloc) {
+ qDebug() << "*** Before register allocation:";
+ QTextStream qout(stdout, QIODevice::WriteOnly);
+ IRPrinterWithPositions(&qout, _lifeTimeIntervals).print(function);
+ }
prepareRanges();
- Optimizer::showMeTheCode(function);
-
linearScan();
-#ifdef DEBUG_REGALLOC
- dump();
-#endif // DEBUG_REGALLOC
+ if (DebugRegAlloc)
+ dump(function);
std::sort(_handled.begin(), _handled.end(), LifeTimeInterval::lessThan);
- ResolutionPhase(_handled, function, _info.data(), _assignedSpillSlots, _normalRegisters, _fpRegisters).run();
+ ResolutionPhase(_handled, _lifeTimeIntervals, function, _assignedSpillSlots, _normalRegisters, _fpRegisters).run();
- function->tempCount = QSet<int>::fromList(_assignedSpillSlots.values()).size();
+ function->tempCount = *std::max_element(_assignedSpillSlots.begin(), _assignedSpillSlots.end()) + 1;
- Optimizer::showMeTheCode(function);
+ if (DebugRegAlloc)
+ qDebug() << "*** Finished regalloc , result:";
-#ifdef DEBUG_REGALLOC
- qDebug() << "*** Finished regalloc for function" << (function->name ? qPrintable(*function->name) : "NO NAME") << "***";
-#endif // DEBUG_REGALLOC
+ static bool showCode = !qgetenv("QV4_SHOW_IR").isNull();
+ if (showCode) {
+ QTextStream qout(stdout, QIODevice::WriteOnly);
+ IRPrinterWithRegisters(&qout, _lifeTimeIntervals, _registerInformation).print(function);
+ }
}
static inline LifeTimeInterval createFixedInterval(int rangeCount)
@@ -1143,26 +1306,30 @@ static inline LifeTimeInterval createFixedInterval(int rangeCount)
i.setReg(0);
Temp t;
- t.init(Temp::PhysicalRegister, 0, 0);
+ t.init(Temp::PhysicalRegister, 0);
t.type = IR::SInt32Type;
i.setTemp(t);
return i;
}
-static inline LifeTimeInterval cloneFixedInterval(int reg, bool isFP, LifeTimeInterval lti)
+LifeTimeInterval *RegisterAllocator::cloneFixedInterval(int reg, bool isFP, const LifeTimeInterval &original)
{
- lti.setReg(reg);
- lti.setFixedInterval(true);
+ LifeTimeInterval *lti = new LifeTimeInterval(original);
+ _lifeTimeIntervals->add(lti);
+ lti->setReg(reg);
+ lti->setFixedInterval(true);
Temp t;
- t.init(Temp::PhysicalRegister, reg, 0);
+ t.init(Temp::PhysicalRegister, reg);
t.type = isFP ? IR::DoubleType : IR::SInt32Type;
- lti.setTemp(t);
+ lti->setTemp(t);
return lti;
}
+// Creates the intervals with fixed ranges. See [Wimmer2]. Note that this only applies to callee-
+// saved registers.
void RegisterAllocator::prepareRanges()
{
LifeTimeInterval ltiWithCalls = createFixedInterval(_info->calls().size());
@@ -1172,37 +1339,41 @@ void RegisterAllocator::prepareRanges()
const int regCount = _normalRegisters.size();
_fixedRegisterRanges.reserve(regCount);
for (int reg = 0; reg < regCount; ++reg) {
- LifeTimeInterval lti = cloneFixedInterval(reg, false, ltiWithCalls);
- _fixedRegisterRanges.append(lti);
- if (lti.isValid())
- _active.append(lti);
+ if (_normalRegisters.at(reg)->isCallerSaved()) {
+ LifeTimeInterval *lti = cloneFixedInterval(reg, false, ltiWithCalls);
+ _fixedRegisterRanges.append(lti);
+ if (lti->isValid())
+ _active.append(lti);
+ }
}
const int fpRegCount = _fpRegisters.size();
_fixedFPRegisterRanges.reserve(fpRegCount);
for (int fpReg = 0; fpReg < fpRegCount; ++fpReg) {
- LifeTimeInterval lti = cloneFixedInterval(fpReg, true, ltiWithCalls);
- _fixedFPRegisterRanges.append(lti);
- if (lti.isValid())
- _active.append(lti);
+ if (_fpRegisters.at(fpReg)->isCallerSaved()) {
+ LifeTimeInterval *lti = cloneFixedInterval(fpReg, true, ltiWithCalls);
+ _fixedFPRegisterRanges.append(lti);
+ if (lti->isValid())
+ _active.append(lti);
+ }
}
}
void RegisterAllocator::linearScan()
{
while (!_unhandled.isEmpty()) {
- LifeTimeInterval current = _unhandled.first();
- _unhandled.removeFirst();
- int position = current.start();
+ LifeTimeInterval *current = _unhandled.back();
+ _unhandled.pop_back();
+ const int position = current->start();
// check for intervals in active that are handled or inactive
for (int i = 0; i < _active.size(); ) {
- const LifeTimeInterval &it = _active.at(i);
- if (it.end() < position) {
- if (!it.isFixedInterval())
+ LifeTimeInterval *it = _active.at(i);
+ if (it->end() < position) {
+ if (!it->isFixedInterval())
_handled += it;
_active.remove(i);
- } else if (!it.covers(position)) {
+ } else if (!it->covers(position)) {
_inactive += it;
_active.remove(i);
} else {
@@ -1212,13 +1383,13 @@ void RegisterAllocator::linearScan()
// check for intervals in inactive that are handled or active
for (int i = 0; i < _inactive.size(); ) {
- const LifeTimeInterval &it = _inactive.at(i);
- if (it.end() < position) {
- if (!it.isFixedInterval())
+ LifeTimeInterval *it = _inactive.at(i);
+ if (it->end() < position) {
+ if (!it->isFixedInterval())
_handled += it;
_inactive.remove(i);
- } else if (it.covers(position)) {
- if (it.reg() != LifeTimeInterval::Invalid) {
+ } else if (it->covers(position)) {
+ if (it->reg() != LifeTimeInterval::InvalidRegister) {
_active += it;
_inactive.remove(i);
} else {
@@ -1231,34 +1402,33 @@ void RegisterAllocator::linearScan()
}
}
- Q_ASSERT(!current.isFixedInterval());
+ Q_ASSERT(!current->isFixedInterval());
#ifdef DEBUG_REGALLOC
qDebug() << "** Position" << position;
#endif // DEBUG_REGALLOC
- if (_info->canHaveRegister(current.temp())) {
- tryAllocateFreeReg(current, position);
- if (current.reg() == LifeTimeInterval::Invalid)
- allocateBlockedReg(current, position);
- if (current.reg() != LifeTimeInterval::Invalid)
+ if (_info->canHaveRegister(current->temp())) {
+ tryAllocateFreeReg(*current);
+ if (current->reg() == LifeTimeInterval::InvalidRegister)
+ allocateBlockedReg(*current);
+ if (current->reg() != LifeTimeInterval::InvalidRegister)
_active += current;
} else {
- assignSpillSlot(current.temp(), current.start(), current.end());
+ assignSpillSlot(current->temp(), current->start(), current->end());
_inactive += current;
-#ifdef DEBUG_REGALLOC
- qDebug() << "*** allocating stack slot" << _assignedSpillSlots[current.temp()]
- << "for %" << current.temp().index << "as it cannot be loaded in a register";
-#endif // DEBUG_REGALLOC
+ if (DebugRegAlloc)
+ qDebug() << "*** allocating stack slot" << _assignedSpillSlots[current->temp().index]
+ << "for %" << current->temp().index << "as it cannot be loaded in a register";
}
}
- foreach (const LifeTimeInterval &r, _active)
- if (!r.isFixedInterval())
+ foreach (LifeTimeInterval *r, _active)
+ if (!r->isFixedInterval())
_handled.append(r);
_active.clear();
- foreach (const LifeTimeInterval &r, _inactive)
- if (!r.isFixedInterval())
+ foreach (LifeTimeInterval *r, _inactive)
+ if (!r->isFixedInterval())
_handled.append(r);
_inactive.clear();
}
@@ -1284,45 +1454,75 @@ static inline int intersectionPosition(const LifeTimeInterval::Range &one, const
static inline bool isFP(const Temp &t)
{ return t.type == DoubleType; }
-void RegisterAllocator::tryAllocateFreeReg(LifeTimeInterval &current, const int position)
+static inline bool candidateIsBetterFit(int bestSizeSoFar, int idealSize, int candidateSize)
{
- Q_ASSERT(!current.isFixedInterval());
- Q_ASSERT(current.reg() == LifeTimeInterval::Invalid);
+ // If the candidateSize is larger than the current we take it only if the current size does not
+ // yet fit for the whole interval.
+ if (bestSizeSoFar < candidateSize && bestSizeSoFar < idealSize)
+ return true;
- const bool needsFPReg = isFP(current.temp());
- QVector<int> freeUntilPos(needsFPReg ? _fpRegisters.size() : _normalRegisters.size(), INT_MAX);
- Q_ASSERT(freeUntilPos.size() > 0);
+ // If the candidateSize is smaller we only take it if it still fits the whole interval.
+ if (bestSizeSoFar > candidateSize && candidateSize >= idealSize)
+ return true;
- const bool isPhiTarget = _info->isPhiTarget(current.temp());
- foreach (const LifeTimeInterval &it, _active) {
- if (it.isFP() == needsFPReg) {
- if (!isPhiTarget && it.isFixedInterval() && !current.isSplitFromInterval()) {
- const int idx = indexOfRangeCoveringPosition(it.ranges(), position);
- if (it.ranges().at(idx).end == current.start()) {
- if (it.ranges().size() > idx + 1)
- freeUntilPos[it.reg()] = it.ranges().at(idx + 1).start;
- continue;
- }
- }
+ // Other wise: no luck.
+ return false;
+}
- if (isPhiTarget || it.end() >= current.firstPossibleUsePosition(isPhiTarget))
- freeUntilPos[it.reg()] = 0; // mark register as unavailable
+// Out of all available registers (with their next-uses), choose the one that fits the requested
+// duration best. This can return a register that is not free for the whole interval, but that's
+// fine: we just have to split the current interval.
+static void longestAvailableReg(int *nextUses, int nextUseCount, int &reg, int &freeUntilPos_reg, int lastUse)
+{
+ reg = LifeTimeInterval::InvalidRegister;
+ freeUntilPos_reg = 0;
+
+ for (int candidate = 0, candidateEnd = nextUseCount; candidate != candidateEnd; ++candidate) {
+ int fp = nextUses[candidate];
+ if (candidateIsBetterFit(freeUntilPos_reg, lastUse, fp)) {
+ reg = candidate;
+ freeUntilPos_reg = fp;
}
}
+}
- foreach (const LifeTimeInterval &it, _inactive) {
- if (current.isSplitFromInterval() || it.isFixedInterval()) {
- if (it.isFP() == needsFPReg && it.reg() != LifeTimeInterval::Invalid) {
- const int intersectionPos = nextIntersection(current, it, position);
- if (!isPhiTarget && it.isFixedInterval() && current.end() == intersectionPos)
- freeUntilPos[it.reg()] = qMin(freeUntilPos[it.reg()], intersectionPos + 1);
- else if (intersectionPos != -1)
- freeUntilPos[it.reg()] = qMin(freeUntilPos[it.reg()], intersectionPos);
- }
+#define CALLOC_ON_STACK(ty, ptr, sz, val) \
+ Q_ASSERT(sz > 0); \
+ ty *ptr = reinterpret_cast<ty *>(alloca(sizeof(ty) * (sz))); \
+ for (ty *it = ptr, *eit = ptr + (sz); it != eit; ++it) \
+ *it = val;
+
+// Try to allocate a register that's currently free.
+void RegisterAllocator::tryAllocateFreeReg(LifeTimeInterval &current)
+{
+ Q_ASSERT(!current.isFixedInterval());
+ Q_ASSERT(current.reg() == LifeTimeInterval::InvalidRegister);
+
+ const bool needsFPReg = isFP(current.temp());
+ const int freeUntilPosCount = needsFPReg ? _fpRegisters.size() : _normalRegisters.size();
+ CALLOC_ON_STACK(int, freeUntilPos, freeUntilPosCount, INT_MAX);
+
+ for (Intervals::const_iterator i = _active.constBegin(), ei = _active.constEnd(); i != ei; ++i) {
+ const LifeTimeInterval *it = *i;
+ if (it->isFP() == needsFPReg)
+ freeUntilPos[it->reg()] = 0; // mark register as unavailable
+ }
+
+ for (Intervals::const_iterator i = _inactive.constBegin(), ei = _inactive.constEnd(); i != ei; ++i) {
+ const LifeTimeInterval *it = *i;
+ if (it->isFP() != needsFPReg)
+ continue; // different register type, so not applicable.
+ if (it->reg() == LifeTimeInterval::InvalidRegister)
+ continue; // this range does not block a register from being used, as it has no register assigned
+
+ if (current.isSplitFromInterval() || it->isFixedInterval()) {
+ const int intersectionPos = nextIntersection(current, *it);
+ if (intersectionPos != -1)
+ freeUntilPos[it->reg()] = qMin(freeUntilPos[it->reg()], intersectionPos);
}
}
- int reg = LifeTimeInterval::Invalid;
+ int reg = LifeTimeInterval::InvalidRegister;
int freeUntilPos_reg = 0;
foreach (const Temp &hint, _info->hints(current.temp())) {
@@ -1330,173 +1530,165 @@ void RegisterAllocator::tryAllocateFreeReg(LifeTimeInterval &current, const int
if (hint.kind == Temp::PhysicalRegister)
candidate = hint.index;
else
- candidate = _lastAssignedRegister.value(hint, LifeTimeInterval::Invalid);
+ candidate = _lastAssignedRegister[hint.index];
const int end = current.end();
- if (candidate != LifeTimeInterval::Invalid) {
- if (current.isFP() == (hint.type == DoubleType)) {
- int fp = freeUntilPos[candidate];
- if ((freeUntilPos_reg < end && fp > freeUntilPos_reg)
- || (freeUntilPos_reg >= end && fp >= end && freeUntilPos_reg > fp)) {
- reg = candidate;
- freeUntilPos_reg = fp;
- }
- }
+ if (candidate == LifeTimeInterval::InvalidRegister)
+ continue; // the candidate has no register assigned, so it cannot be (re-)used
+ if (current.isFP() != isFP(hint))
+ continue; // different register type, so not applicable.
+
+ const int fp = freeUntilPos[candidate];
+ if (candidateIsBetterFit(freeUntilPos_reg, end, fp)) {
+ reg = candidate;
+ freeUntilPos_reg = fp;
}
}
- if (reg == LifeTimeInterval::Invalid)
- longestAvailableReg(freeUntilPos, reg, freeUntilPos_reg, current.end());
+ // None of the hinted registers could fit the interval, so try all registers next.
+ if (reg == LifeTimeInterval::InvalidRegister)
+ longestAvailableReg(freeUntilPos, freeUntilPosCount, reg, freeUntilPos_reg, current.end());
if (freeUntilPos_reg == 0) {
// no register available without spilling
-#ifdef DEBUG_REGALLOC
- qDebug() << "*** no register available for %" << current.temp().index;
-#endif // DEBUG_REGALLOC
+ if (DebugRegAlloc)
+ qDebug() << "*** no register available for %" << current.temp().index;
return;
} else if (current.end() < freeUntilPos_reg) {
// register available for the whole interval
-#ifdef DEBUG_REGALLOC
- qDebug() << "*** allocating register" << reg << "for the whole interval of %" << current.temp().index;
-#endif // DEBUG_REGALLOC
+ if (DebugRegAlloc)
+ qDebug() << "*** allocating register" << reg << "for the whole interval of %" << current.temp().index;
current.setReg(reg);
- _lastAssignedRegister.insert(current.temp(), reg);
+ _lastAssignedRegister[current.temp().index] = reg;
} else {
// register available for the first part of the interval
+
+ // TODO: this is slightly inefficient in the following case:
+ // %1 = something
+ // some_call(%1)
+ // %2 = %1 + 1
+ // Now %1 will get a register assigned, and will be spilled to the stack immediately. It
+ // would be better to check if there are actually uses in the range before the split.
+
current.setReg(reg);
- _lastAssignedRegister.insert(current.temp(), reg);
-#ifdef DEBUG_REGALLOC
- qDebug() << "*** allocating register" << reg << "for the first part of interval of %" << current.temp().index;
-#endif // DEBUG_REGALLOC
+ _lastAssignedRegister[current.temp().index] = reg;
+ if (DebugRegAlloc)
+ qDebug() << "*** allocating register" << reg << "for the first part of interval of %" << current.temp().index;
split(current, freeUntilPos_reg, true);
}
}
-void RegisterAllocator::allocateBlockedReg(LifeTimeInterval &current, const int position)
+// This gets called when all registers are currently in use.
+void RegisterAllocator::allocateBlockedReg(LifeTimeInterval &current)
{
Q_ASSERT(!current.isFixedInterval());
- Q_ASSERT(current.reg() == LifeTimeInterval::Invalid);
+ Q_ASSERT(current.reg() == LifeTimeInterval::InvalidRegister);
+ const int position = current.start();
const bool isPhiTarget = _info->isPhiTarget(current.temp());
if (isPhiTarget && !current.isSplitFromInterval()) {
+ // Special case: storing to a phi-node's target will result in a single move. So, if we
+ // would spill another interval to the stack (that's 1 store), and then do the move for the
+ // phi target (at least 1 move or a load), that would result in 2 instructions. Instead, we
+ // force the phi-node's target to go to the stack immediately, which is always a single
+ // store.
split(current, position + 1, true);
- _inactive.append(current);
+ _inactive.append(&current);
return;
}
const bool needsFPReg = isFP(current.temp());
- QVector<int> nextUsePos(needsFPReg ? _fpRegisters.size() : _normalRegisters.size(), INT_MAX);
- QVector<LifeTimeInterval *> nextUseRangeForReg(nextUsePos.size(), 0);
- Q_ASSERT(nextUsePos.size() > 0);
-
- const bool definedAtCurrentPosition = !current.isSplitFromInterval() && current.start() == position;
-
- for (int i = 0, ei = _active.size(); i != ei; ++i) {
- LifeTimeInterval &it = _active[i];
- if (it.isFP() == needsFPReg) {
- int nu = it.isFixedInterval() ? 0 : nextUse(it.temp(), current.firstPossibleUsePosition(isPhiTarget));
- if (nu == position && !definedAtCurrentPosition) {
- nextUsePos[it.reg()] = 0;
- } else if (nu != -1 && nu < nextUsePos[it.reg()]) {
- nextUsePos[it.reg()] = nu;
- nextUseRangeForReg[it.reg()] = &it;
- } else if (nu == -1 && nextUsePos[it.reg()] == INT_MAX) {
- // in a loop, the range can be active, but only used before the current position (e.g. in a loop header or phi node)
- nextUseRangeForReg[it.reg()] = &it;
- }
+ const int nextUsePosCount = needsFPReg ? _fpRegisters.size() : _normalRegisters.size();
+ CALLOC_ON_STACK(int, nextUsePos, nextUsePosCount, INT_MAX);
+ QVector<LifeTimeInterval *> nextUseRangeForReg(nextUsePosCount, 0);
+
+ for (Intervals::const_iterator i = _active.constBegin(), ei = _active.constEnd(); i != ei; ++i) {
+ LifeTimeInterval &it = **i;
+ if (it.isFP() != needsFPReg)
+ continue; // different register type, so not applicable.
+
+ const int nu = it.isFixedInterval() ? 0 : nextUse(it.temp(), current.start());
+ if (nu == position) {
+ nextUsePos[it.reg()] = 0;
+ } else if (nu != -1 && nu < nextUsePos[it.reg()]) {
+ nextUsePos[it.reg()] = nu;
+ nextUseRangeForReg[it.reg()] = &it;
+ } else if (nu == -1 && nextUsePos[it.reg()] == INT_MAX) {
+ // in a loop, the range can be active, but the result might only be used before the
+ // current position (e.g. the induction variable being used in the phi node in the loop
+ // header). So, we can use this register, but we need to remember to split the interval
+ // in order to have the edge-resolving generate a load at the edge going back to the
+ // loop header.
+ nextUseRangeForReg[it.reg()] = &it;
}
}
- for (int i = 0, ei = _inactive.size(); i != ei; ++i) {
- LifeTimeInterval &it = _inactive[i];
+ for (Intervals::const_iterator i = _inactive.constBegin(), ei = _inactive.constEnd(); i != ei; ++i) {
+ LifeTimeInterval &it = **i;
+ if (it.isFP() != needsFPReg)
+ continue; // different register type, so not applicable.
+ if (it.reg() == LifeTimeInterval::InvalidRegister)
+ continue; // this range does not block a register from being used, as it has no register assigned
+
if (current.isSplitFromInterval() || it.isFixedInterval()) {
- if (it.isFP() == needsFPReg && it.reg() != LifeTimeInterval::Invalid) {
- if (nextIntersection(current, it, position) != -1) {
- int nu = nextUse(it.temp(), current.firstPossibleUsePosition(isPhiTarget));
- if (nu != -1 && nu < nextUsePos[it.reg()]) {
- nextUsePos[it.reg()] = nu;
- nextUseRangeForReg[it.reg()] = &it;
- }
+ if (nextIntersection(current, it) != -1) {
+ const int nu = nextUse(it.temp(), current.start());
+ if (nu != -1 && nu < nextUsePos[it.reg()]) {
+ nextUsePos[it.reg()] = nu;
+ nextUseRangeForReg[it.reg()] = &it;
}
}
}
}
int reg, nextUsePos_reg;
- longestAvailableReg(nextUsePos, reg, nextUsePos_reg, current.end());
+ longestAvailableReg(nextUsePos, nextUsePosCount, reg, nextUsePos_reg, current.end());
- if (current.start() > nextUsePos_reg) {
- // all other intervals are used before current, so it is best to spill current itself
-#ifdef DEBUG_REGALLOC
- QTextStream out(stderr, QIODevice::WriteOnly);
- out << "*** splitting current for range ";current.dump(out);out<<endl;
-#endif // DEBUG_REGALLOC
- Q_ASSERT(!_info->useMustHaveReg(current.temp(), position));
- split(current, position + 1, true);
- _inactive.append(current);
- } else {
- // spill intervals that currently block reg
-#ifdef DEBUG_REGALLOC
- QTextStream out(stderr, QIODevice::WriteOnly);
- out << "*** spilling intervals that block reg "<<reg<<" for interval ";current.dump(out);out<<endl;
-#endif // DEBUG_REGALLOC
- current.setReg(reg);
- _lastAssignedRegister.insert(current.temp(), reg);
- LifeTimeInterval *nextUse = nextUseRangeForReg[reg];
- Q_ASSERT(nextUse);
- Q_ASSERT(!nextUse->isFixedInterval());
-
- if (_info->isUsedAt(nextUse->temp(), position)) {
- Q_ASSERT(!_info->isUsedAt(current.temp(), position));
- // the register is used (as an incoming parameter) at the current position, so split
- // the interval immediately after the (use at the) current position
- split(*nextUse, position + 1);
- } else {
- // the register was used before the current position
- split(*nextUse, position);
- }
+ Q_ASSERT(current.start() <= nextUsePos_reg);
- splitInactiveAtEndOfLifetimeHole(reg, needsFPReg, position);
-
- // make sure that current does not intersect with the fixed interval for reg
- const LifeTimeInterval &fixedRegRange = needsFPReg ? _fixedFPRegisterRanges.at(reg)
- : _fixedRegisterRanges.at(reg);
- int ni = nextIntersection(current, fixedRegRange, position);
- if (ni != -1) {
-#ifdef DEBUG_REGALLOC
- out << "***-- current range intersects with a fixed reg use at "<<ni<<", so splitting it."<<endl;
-#endif // DEBUG_REGALLOC
- split(current, ni, true);
- }
- }
-}
-
-void RegisterAllocator::longestAvailableReg(const QVector<int> &nextUses, int &reg,
- int &freeUntilPos_reg, int lastUse) const
-{
- reg = LifeTimeInterval::Invalid;
- freeUntilPos_reg = 0;
-
- for (int candidate = 0, candidateEnd = nextUses.size(); candidate != candidateEnd; ++candidate) {
- int fp = nextUses[candidate];
- if ((freeUntilPos_reg < lastUse && fp > freeUntilPos_reg)
- || (freeUntilPos_reg >= lastUse && fp >= lastUse && freeUntilPos_reg > fp)) {
- reg = candidate;
- freeUntilPos_reg = fp;
+ // spill interval that currently block reg
+ if (DebugRegAlloc) {
+ QTextStream out(stderr, QIODevice::WriteOnly);
+ out << "*** spilling intervals that block reg " <<reg<< " for interval ";
+ current.dump(out);
+ out << endl;
+ }
+ current.setReg(reg);
+ _lastAssignedRegister[current.temp().index] = reg;
+ LifeTimeInterval *nextUse = nextUseRangeForReg[reg];
+ Q_ASSERT(nextUse);
+ Q_ASSERT(!nextUse->isFixedInterval());
+
+ split(*nextUse, position);
+
+ // We might have chosen a register that is used by a range that has a hole in its life time.
+ // If that's the case, check if the current interval completely fits in the hole. Or rephrased:
+ // check if the current interval will use the register after that hole ends (so that range, and
+ // if so, split that interval so that it gets a new register assigned when it needs one.
+ splitInactiveAtEndOfLifetimeHole(reg, needsFPReg, position);
+
+ // make sure that current does not intersect with the fixed interval for reg
+ const LifeTimeInterval &fixedRegRange = needsFPReg ? *_fixedFPRegisterRanges.at(reg)
+ : *_fixedRegisterRanges.at(reg);
+ int ni = nextIntersection(current, fixedRegRange);
+ if (ni != -1) {
+ if (DebugRegAlloc) {
+ QTextStream out(stderr, QIODevice::WriteOnly);
+ out << "***-- current range intersects with a fixed reg use at " << ni << ", so splitting it." << endl;
}
+ // current does overlap with a fixed interval, so split current before that intersection.
+ split(current, ni, true);
}
}
int RegisterAllocator::nextIntersection(const LifeTimeInterval &current,
- const LifeTimeInterval &another, const int position) const
+ const LifeTimeInterval &another) const
{
- LifeTimeInterval::Ranges currentRanges = current.ranges();
- int currentIt = indexOfRangeCoveringPosition(currentRanges, position);
- if (currentIt == -1)
- return -1;
+ const LifeTimeInterval::Ranges &currentRanges = current.ranges();
+ int currentIt = 0;
- LifeTimeInterval::Ranges anotherRanges = another.ranges();
- const int anotherItStart = indexOfRangeCoveringPosition(anotherRanges, position);
+ const LifeTimeInterval::Ranges &anotherRanges = another.ranges();
+ const int anotherItStart = indexOfRangeCoveringPosition(anotherRanges, current.start());
if (anotherItStart == -1)
return -1;
@@ -1515,11 +1707,12 @@ int RegisterAllocator::nextIntersection(const LifeTimeInterval &current,
return -1;
}
+/// Find the first use after the start position for the given temp.
int RegisterAllocator::nextUse(const Temp &t, int startPosition) const
{
- QList<Use> usePositions = _info->uses(t);
- for (int i = 0, ei = usePositions.size(); i != ei; ++i) {
- int usePos = usePositions[i].pos;
+ const std::vector<Use> &usePositions = _info->uses(t);
+ for (int i = 0, ei = usePositions.size(); i != ei; ++i) { //### FIXME: use an iterator
+ const int usePos = usePositions.at(i).pos;
if (usePos >= startPosition)
return usePos;
}
@@ -1527,16 +1720,16 @@ int RegisterAllocator::nextUse(const Temp &t, int startPosition) const
return -1;
}
-static inline void insertSorted(QVector<LifeTimeInterval> &intervals, const LifeTimeInterval &newInterval)
+static inline void insertReverseSorted(QVector<LifeTimeInterval *> &intervals, LifeTimeInterval *newInterval)
{
- newInterval.validate();
- for (int i = 0, ei = intervals.size(); i != ei; ++i) {
- if (LifeTimeInterval::lessThan(newInterval, intervals.at(i))) {
- intervals.insert(i, newInterval);
+ newInterval->validate();
+ for (int i = intervals.size(); i > 0;) {
+ if (LifeTimeInterval::lessThan(newInterval, intervals.at(--i))) {
+ intervals.insert(i + 1, newInterval);
return;
}
}
- intervals.append(newInterval);
+ intervals.insert(0, newInterval);
}
void RegisterAllocator::split(LifeTimeInterval &current, int beforePosition,
@@ -1544,28 +1737,21 @@ void RegisterAllocator::split(LifeTimeInterval &current, int beforePosition,
{ // TODO: check if we can always skip the optional register uses
Q_ASSERT(!current.isFixedInterval());
-#ifdef DEBUG_REGALLOC
- QTextStream out(stderr, QIODevice::WriteOnly);
- out << "***** split request for range ";current.dump(out);out<<" before position "<<beforePosition<<" and skipOptionalRegisterUses = "<<skipOptionalRegisterUses<<endl;
-#endif // DEBUG_REGALLOC
+ if (DebugRegAlloc) {
+ QTextStream out(stderr, QIODevice::WriteOnly);
+ out << "***** split request for range ";current.dump(out);out<<" before position "<<beforePosition<<" and skipOptionalRegisterUses = "<<skipOptionalRegisterUses<<endl;
+ }
assignSpillSlot(current.temp(), current.start(), current.end());
- const int defPosition = _info->def(current.temp());
- if (beforePosition < defPosition) {
-#ifdef DEBUG_REGALLOC
- out << "***** split before position is before or at definition, so not splitting."<<endl;
-#endif // DEBUG_REGALLOC
- return;
- }
+ const int firstPosition = current.start();
+ Q_ASSERT(beforePosition > firstPosition && "split before start");
- int lastUse = -1;
- if (defPosition < beforePosition)
- lastUse = defPosition;
+ int lastUse = firstPosition;
int nextUse = -1;
- QList<Use> usePositions = _info->uses(current.temp());
+ const std::vector<Use> &usePositions = _info->uses(current.temp());
for (int i = 0, ei = usePositions.size(); i != ei; ++i) {
- const Use &usePosition = usePositions[i];
+ const Use &usePosition = usePositions.at(i);
const int usePos = usePosition.pos;
if (lastUse < usePos && usePos < beforePosition) {
lastUse = usePos;
@@ -1576,31 +1762,30 @@ void RegisterAllocator::split(LifeTimeInterval &current, int beforePosition,
}
}
}
- if (lastUse == -1)
- lastUse = beforePosition - 1;
-
+ Q_ASSERT(lastUse != -1);
Q_ASSERT(lastUse < beforePosition);
-#ifdef DEBUG_REGALLOC
- out << "***** last use = "<<lastUse<<", nextUse = " << nextUse<<endl;
-#endif // DEBUG_REGALLOC
LifeTimeInterval newInterval = current.split(lastUse, nextUse);
-#ifdef DEBUG_REGALLOC
- out << "***** new interval: "; newInterval.dump(out); out << endl;
- out << "***** preceding interval: "; current.dump(out); out << endl;
-#endif // DEBUG_REGALLOC
+ if (DebugRegAlloc) {
+ QTextStream out(stderr, QIODevice::WriteOnly);
+ out << "***** last use = "<<lastUse<<", nextUse = " << nextUse<<endl;
+ out << "***** new interval: "; newInterval.dump(out); out << endl;
+ out << "***** preceding interval: "; current.dump(out); out << endl;
+ }
if (newInterval.isValid()) {
- if (current.reg() != LifeTimeInterval::Invalid)
+ if (current.reg() != LifeTimeInterval::InvalidRegister)
_info->addHint(current.temp(), current.reg());
- newInterval.setReg(LifeTimeInterval::Invalid);
- insertSorted(_unhandled, newInterval);
+ newInterval.setReg(LifeTimeInterval::InvalidRegister);
+ LifeTimeInterval *newIntervalPtr = new LifeTimeInterval(newInterval);
+ _lifeTimeIntervals->add(newIntervalPtr);
+ insertReverseSorted(_unhandled, newIntervalPtr);
}
}
void RegisterAllocator::splitInactiveAtEndOfLifetimeHole(int reg, bool isFPReg, int position)
{
for (int i = 0, ei = _inactive.size(); i != ei; ++i) {
- LifeTimeInterval &interval = _inactive[i];
+ LifeTimeInterval &interval = *_inactive[i];
if (interval.isFixedInterval())
continue;
if (isFPReg == interval.isFP() && interval.reg() == reg) {
@@ -1618,13 +1803,13 @@ void RegisterAllocator::splitInactiveAtEndOfLifetimeHole(int reg, bool isFPReg,
void RegisterAllocator::assignSpillSlot(const Temp &t, int startPos, int endPos)
{
- if (_assignedSpillSlots.contains(t))
+ if (_assignedSpillSlots[t.index] != InvalidSpillSlot)
return;
for (int i = 0, ei = _activeSpillSlots.size(); i != ei; ++i) {
if (_activeSpillSlots.at(i) < startPos) {
_activeSpillSlots[i] = endPos;
- _assignedSpillSlots.insert(t, i);
+ _assignedSpillSlots[t.index] = i;
return;
}
}
@@ -1632,32 +1817,33 @@ void RegisterAllocator::assignSpillSlot(const Temp &t, int startPos, int endPos)
Q_UNREACHABLE();
}
-void RegisterAllocator::dump() const
+void RegisterAllocator::dump(IR::Function *function) const
{
-#ifdef DEBUG_REGALLOC
QTextStream qout(stdout, QIODevice::WriteOnly);
+ IRPrinterWithPositions printer(&qout, _lifeTimeIntervals);
- {
- qout << "Ranges:" << endl;
- QVector<LifeTimeInterval> handled = _handled;
- std::sort(handled.begin(), handled.end(), LifeTimeInterval::lessThanForTemp);
- foreach (const LifeTimeInterval &r, handled) {
- r.dump(qout);
- qout << endl;
- }
+ qout << "Ranges:" << endl;
+ QVector<LifeTimeInterval *> handled = _handled;
+ std::sort(handled.begin(), handled.end(), LifeTimeInterval::lessThanForTemp);
+ foreach (const LifeTimeInterval *r, handled) {
+ r->dump(qout);
+ qout << endl;
}
- {
- qout << "Spill slots:" << endl;
- QList<Temp> temps = _assignedSpillSlots.keys();
- if (temps.isEmpty())
- qout << "\t(none)" << endl;
- std::sort(temps.begin(), temps.end());
- foreach (const Temp &t, temps) {
- qout << "\t";
- t.dump(qout);
- qout << " -> " << _assignedSpillSlots[t] << endl;
- }
- }
-#endif // DEBUG_REGALLOC
+ qout << "Spill slots:" << endl;
+ for (unsigned i = 0; i < _assignedSpillSlots.size(); ++i)
+ if (_assignedSpillSlots[i] != InvalidSpillSlot)
+ qout << "\t%" << i << " -> " << _assignedSpillSlots[i] << endl;
+
+ printer.print(function);
}
+
+// References:
+// [Wimmer1] C. Wimmer and M. Franz. Linear Scan Register Allocation on SSA Form. In Proceedings of
+// CGO’10, ACM Press, 2010
+// [Wimmer2] C. Wimmer and H. Mossenbock. Optimized Interval Splitting in a Linear Scan Register
+// Allocator. In Proceedings of the ACM/USENIX International Conference on Virtual
+// Execution Environments, pages 132–141. ACM Press, 2005.
+// [Traub] Omri Traub, Glenn Holloway, and Michael D. Smith. Quality and Speed in Linear-scan
+// Register Allocation. In Proceedings of the ACM SIGPLAN 1998 Conference on Programming
+// Language Design and Implementation, pages 142–151, June 1998.
diff --git a/src/qml/jit/qv4regalloc_p.h b/src/qml/jit/qv4regalloc_p.h
index 030fb4bf50..34ae19dfec 100644
--- a/src/qml/jit/qv4regalloc_p.h
+++ b/src/qml/jit/qv4regalloc_p.h
@@ -44,6 +44,7 @@
#include "qv4global_p.h"
#include "qv4isel_p.h"
#include "qv4ssa_p.h"
+#include "qv4registerinfo_p.h"
#include <config.h>
@@ -54,46 +55,68 @@ namespace JIT {
class RegAllocInfo;
+// This class implements a linear-scan register allocator, with a couple of tweaks:
+// - Second-chance allocation is used when an interval becomes active after a spill, which results
+// in fewer differences between edges, and hence fewer moves before jumps.
+// - Use positions are flagged with either "must have" register or "could have" register. This is
+// used to decide whether a register is really needed when a temporary is used after a spill
+// occurred.
+// - Fixed intervals are used to denotate IR positions where certain registers are needed in order
+// to implement the operation, and cannot be used by a temporary on that position. An example is
+// caller saved registers, where the call will use/clobber those registers.
+// - Hints are used to indicate which registers could be used to generate more compact code. An
+// example is an addition, where one (or both) operands' life-time ends at that instruction. In
+// this case, re-using an operand register for the result will result in an in-place add.
+// - SSA form properties are used:
+// - to simplify life-times (two temporaries will never interfere as long as their intervals
+// are not split), resulting in a slightly faster algorithm;
+// - when a temporary needs to be spilled, it is done directly after calculating it, so that
+// 1 store is generated even if multiple spills/splits happen.
+// - phi-node elimination (SSA form deconstruction) is done when resolving differences between
+// CFG edges
class RegisterAllocator
{
typedef IR::LifeTimeInterval LifeTimeInterval;
- QVector<int> _normalRegisters;
- QVector<int> _fpRegisters;
+ const RegisterInformation &_registerInformation;
+ QVector<const RegisterInfo *> _normalRegisters;
+ QVector<const RegisterInfo *> _fpRegisters;
QScopedPointer<RegAllocInfo> _info;
- QVector<LifeTimeInterval> _fixedRegisterRanges, _fixedFPRegisterRanges;
+ QVector<LifeTimeInterval *> _fixedRegisterRanges, _fixedFPRegisterRanges;
- QVector<LifeTimeInterval> _unhandled, _active, _inactive, _handled;
+ IR::LifeTimeIntervals::Ptr _lifeTimeIntervals;
+ typedef QVector<LifeTimeInterval *> Intervals;
+ Intervals _unhandled, _active, _inactive, _handled;
- QHash<IR::Temp, int> _lastAssignedRegister;
- QHash<IR::Temp, int> _assignedSpillSlots;
+ std::vector<int> _lastAssignedRegister;
+ std::vector<int> _assignedSpillSlots;
QVector<int> _activeSpillSlots;
Q_DISABLE_COPY(RegisterAllocator)
public:
- RegisterAllocator(const QVector<int> &normalRegisters, const QVector<int> &fpRegisters);
+ enum { InvalidSpillSlot = -1 };
+
+ RegisterAllocator(const RegisterInformation &registerInformation);
~RegisterAllocator();
void run(IR::Function *function, const IR::Optimizer &opt);
private:
+ LifeTimeInterval *cloneFixedInterval(int reg, bool isFP, const LifeTimeInterval &original);
void prepareRanges();
void linearScan();
- void tryAllocateFreeReg(LifeTimeInterval &current, const int position);
- void allocateBlockedReg(LifeTimeInterval &current, const int position);
- void longestAvailableReg(const QVector<int> &nextUses, int &reg, int &nextUsePos_reg,
- int lastUse) const;
- int nextIntersection(const LifeTimeInterval &current, const LifeTimeInterval &another,
- const int position) const;
+ void tryAllocateFreeReg(LifeTimeInterval &current);
+ void allocateBlockedReg(LifeTimeInterval &current);
+ int nextIntersection(const LifeTimeInterval &current, const LifeTimeInterval &another) const;
int nextUse(const IR::Temp &t, int startPosition) const;
void split(LifeTimeInterval &current, int beforePosition, bool skipOptionalRegisterUses =false);
void splitInactiveAtEndOfLifetimeHole(int reg, bool isFPReg, int position);
void assignSpillSlot(const IR::Temp &t, int startPos, int endPos);
void resolve(IR::Function *function, const IR::Optimizer &opt);
- void dump() const;
+ void dump(IR::Function *function) const;
};
} // end of namespace JIT
diff --git a/src/qml/jit/qv4registerinfo_p.h b/src/qml/jit/qv4registerinfo_p.h
new file mode 100644
index 0000000000..b8701d72f4
--- /dev/null
+++ b/src/qml/jit/qv4registerinfo_p.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QV4REGISTERINFO_P_H
+#define QV4REGISTERINFO_P_H
+
+#include <QtCore/QString>
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+namespace JIT {
+
+class RegisterInfo
+{
+public:
+ enum { InvalidRegister = -1 };
+ enum SavedBy { CallerSaved, CalleeSaved };
+ enum RegisterType { RegularRegister, FloatingPointRegister };
+ enum Usage { Predefined, RegAlloc };
+
+public:
+ RegisterInfo()
+ : _reg(InvalidRegister)
+ , _type(RegularRegister)
+ , _savedBy(CallerSaved)
+ , _usage(Predefined)
+ {}
+
+ RegisterInfo(int reg, const QString &prettyName, RegisterType type, SavedBy savedBy, Usage usage)
+ : _reg(reg)
+ , _prettyName(prettyName)
+ , _type(type)
+ , _savedBy(savedBy)
+ , _usage(usage)
+ {}
+
+ bool isValid() const { return _reg != InvalidRegister; }
+ template <typename T> T reg() const { return static_cast<T>(_reg); }
+ QString prettyName() const { return _prettyName; }
+ bool isCallerSaved() const { return _savedBy == CallerSaved; }
+ bool isCalleeSaved() const { return _savedBy == CalleeSaved; }
+ bool isFloatingPoint() const { return _type == FloatingPointRegister; }
+ bool isRegularRegister() const { return _type == RegularRegister; }
+ bool useForRegAlloc() const { return _usage == RegAlloc; }
+
+private:
+ int _reg;
+ QString _prettyName;
+ RegisterType _type;
+ SavedBy _savedBy;
+ Usage _usage;
+};
+typedef QVector<RegisterInfo> RegisterInformation;
+
+} // JIT namespace
+} // QV4 namespace
+
+QT_END_NAMESPACE
+
+#endif // QV4REGISTERINFO_P_H
diff --git a/src/qml/jit/qv4targetplatform_p.h b/src/qml/jit/qv4targetplatform_p.h
new file mode 100644
index 0000000000..4b384d2fe9
--- /dev/null
+++ b/src/qml/jit/qv4targetplatform_p.h
@@ -0,0 +1,390 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QV4TARGETPLATFORM_P_H
+#define QV4TARGETPLATFORM_P_H
+
+#include <config.h>
+
+#if ENABLE(ASSEMBLER)
+
+#include "qv4registerinfo_p.h"
+#include <assembler/MacroAssembler.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+namespace JIT {
+
+// The TargetPlatform class describes how the stack and the registers work on a CPU+ABI combination.
+//
+// All combinations have a separate definition, guarded by #ifdefs. The exceptions are:
+// - Linux/x86 and win32, which are the same, except that linux non-PIC/PIE code does not need to
+// restore ebx (which holds the GOT ptr) before a call
+// - All (supported) ARM platforms, where the only variety is the platform specific usage of r9,
+// and the frame-pointer in Thumb/Thumb2 v.s. ARM mode.
+//
+// Specific handling of ebx when it holds the GOT:
+// In this case we can use it, but it needs to be restored when doing a call. So, the handling is as
+// follows: it is marked as caller saved, meaning the value in it won't survive a call. When
+// calculating the list of callee saved registers in getCalleeSavedRegisters (which is used to
+// generate push/pop instructions in the prelude/postlude), we add ebx too. Then when synthesizing
+// a call, we add a load it right before emitting the call instruction.
+//
+// NOTE: When adding new architecture, do not forget to whitelist it in qv4global_p.h!
+class TargetPlatform
+{
+public:
+#if CPU(X86) && (OS(LINUX) || OS(WINDOWS) || OS(QNX) || OS(FREEBSD))
+ enum { RegAllocIsSupported = 1 };
+
+ static const JSC::MacroAssembler::RegisterID StackFrameRegister = JSC::X86Registers::ebp;
+ static const JSC::MacroAssembler::RegisterID StackPointerRegister = JSC::X86Registers::esp;
+ static const JSC::MacroAssembler::RegisterID LocalsRegister = JSC::X86Registers::edi;
+ static const JSC::MacroAssembler::RegisterID ContextRegister = JSC::X86Registers::esi;
+ static const JSC::MacroAssembler::RegisterID ReturnValueRegister = JSC::X86Registers::eax;
+ static const JSC::MacroAssembler::RegisterID ScratchRegister = JSC::X86Registers::ecx;
+ static const JSC::MacroAssembler::FPRegisterID FPGpr0 = JSC::X86Registers::xmm0;
+ static const JSC::MacroAssembler::FPRegisterID FPGpr1 = JSC::X86Registers::xmm1;
+
+ static RegisterInformation getPlatformRegisterInfo()
+ {
+ typedef RegisterInfo RI;
+ return RegisterInformation()
+ << RI(JSC::X86Registers::edx, QStringLiteral("edx"), RI::RegularRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::X86Registers::ebx, QStringLiteral("ebx"), RI::RegularRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::X86Registers::edi, QStringLiteral("edi"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined)
+ << RI(JSC::X86Registers::esi, QStringLiteral("esi"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined)
+ << RI(JSC::X86Registers::xmm2, QStringLiteral("xmm2"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::X86Registers::xmm3, QStringLiteral("xmm3"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::X86Registers::xmm4, QStringLiteral("xmm4"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::X86Registers::xmm5, QStringLiteral("xmm5"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::X86Registers::xmm6, QStringLiteral("xmm6"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::X86Registers::xmm7, QStringLiteral("xmm7"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc)
+ ;
+ }
+
+# define HAVE_ALU_OPS_WITH_MEM_OPERAND 1
+# undef VALUE_FITS_IN_REGISTER
+ static const int RegisterSize = 4;
+
+# undef ARGUMENTS_IN_REGISTERS
+ static const int RegisterArgumentCount = 0;
+ static JSC::MacroAssembler::RegisterID registerForArgument(int) { Q_UNREACHABLE(); }
+
+ static const int StackAlignment = 16;
+ static const int StackShadowSpace = 0;
+ static const int StackSpaceAllocatedUponFunctionEntry = RegisterSize; // Return address is pushed onto stack by the CPU.
+ static void platformEnterStandardStackFrame(JSC::MacroAssembler *as) { Q_UNUSED(as); }
+ static void platformLeaveStandardStackFrame(JSC::MacroAssembler *as) { Q_UNUSED(as); }
+
+#if OS(WINDOWS) || OS(QNX) || \
+ ((OS(LINUX) || OS(FREEBSD)) && (defined(__PIC__) || defined(__PIE__)))
+
+#define RESTORE_EBX_ON_CALL
+ static JSC::MacroAssembler::Address ebxAddressOnStack()
+ {
+ static int ebxIdx = -1;
+ if (ebxIdx == -1) {
+ int calleeSaves = 0;
+ foreach (const RegisterInfo &info, getRegisterInfo()) {
+ if (info.reg<JSC::X86Registers::RegisterID>() == JSC::X86Registers::ebx) {
+ ebxIdx = calleeSaves;
+ break;
+ } else if (info.isCalleeSaved()) {
+ ++calleeSaves;
+ }
+ }
+ Q_ASSERT(ebxIdx >= 0);
+ ebxIdx += 1;
+ }
+ return JSC::MacroAssembler::Address(StackFrameRegister, ebxIdx * -int(sizeof(void*)));
+ }
+#endif
+
+#endif // Windows on x86
+
+#if CPU(X86_64) && (OS(LINUX) || OS(MAC_OS_X) || OS(FREEBSD))
+ enum { RegAllocIsSupported = 1 };
+
+ static const JSC::MacroAssembler::RegisterID StackFrameRegister = JSC::X86Registers::ebp;
+ static const JSC::MacroAssembler::RegisterID StackPointerRegister = JSC::X86Registers::esp;
+ static const JSC::MacroAssembler::RegisterID LocalsRegister = JSC::X86Registers::r12;
+ static const JSC::MacroAssembler::RegisterID ContextRegister = JSC::X86Registers::r14;
+ static const JSC::MacroAssembler::RegisterID ReturnValueRegister = JSC::X86Registers::eax;
+ static const JSC::MacroAssembler::RegisterID ScratchRegister = JSC::X86Registers::r10;
+ static const JSC::MacroAssembler::FPRegisterID FPGpr0 = JSC::X86Registers::xmm0;
+ static const JSC::MacroAssembler::FPRegisterID FPGpr1 = JSC::X86Registers::xmm1;
+
+ static RegisterInformation getPlatformRegisterInfo()
+ {
+ typedef RegisterInfo RI;
+ return RegisterInformation()
+ << RI(JSC::X86Registers::ebx, QStringLiteral("rbx"), RI::RegularRegister, RI::CalleeSaved, RI::RegAlloc)
+ << RI(JSC::X86Registers::edi, QStringLiteral("rdi"), RI::RegularRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::X86Registers::esi, QStringLiteral("rsi"), RI::RegularRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::X86Registers::edx, QStringLiteral("rdx"), RI::RegularRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::X86Registers::r9, QStringLiteral("r9"), RI::RegularRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::X86Registers::r8, QStringLiteral("r8"), RI::RegularRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::X86Registers::r12, QStringLiteral("r12"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined)
+ << RI(JSC::X86Registers::r13, QStringLiteral("r13"), RI::RegularRegister, RI::CalleeSaved, RI::RegAlloc)
+ << RI(JSC::X86Registers::r14, QStringLiteral("r14"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined)
+ << RI(JSC::X86Registers::r15, QStringLiteral("r15"), RI::RegularRegister, RI::CalleeSaved, RI::RegAlloc)
+ << RI(JSC::X86Registers::xmm2, QStringLiteral("xmm2"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::X86Registers::xmm3, QStringLiteral("xmm3"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::X86Registers::xmm4, QStringLiteral("xmm4"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::X86Registers::xmm5, QStringLiteral("xmm5"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::X86Registers::xmm6, QStringLiteral("xmm6"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::X86Registers::xmm7, QStringLiteral("xmm7"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc)
+ ;
+ }
+
+#define HAVE_ALU_OPS_WITH_MEM_OPERAND 1
+#define VALUE_FITS_IN_REGISTER
+ static const int RegisterSize = 8;
+
+#define ARGUMENTS_IN_REGISTERS
+ static const int RegisterArgumentCount = 6;
+ static JSC::MacroAssembler::RegisterID registerForArgument(int index)
+ {
+ static JSC::MacroAssembler::RegisterID regs[RegisterArgumentCount] = {
+ JSC::X86Registers::edi,
+ JSC::X86Registers::esi,
+ JSC::X86Registers::edx,
+ JSC::X86Registers::ecx,
+ JSC::X86Registers::r8,
+ JSC::X86Registers::r9
+ };
+ Q_ASSERT(index >= 0 && index < RegisterArgumentCount);
+ return regs[index];
+ };
+
+ static const int StackAlignment = 16;
+ static const int StackShadowSpace = 0;
+ static const int StackSpaceAllocatedUponFunctionEntry = RegisterSize; // Return address is pushed onto stack by the CPU.
+ static void platformEnterStandardStackFrame(JSC::MacroAssembler *as) { Q_UNUSED(as); }
+ static void platformLeaveStandardStackFrame(JSC::MacroAssembler *as) { Q_UNUSED(as); }
+#endif // Linux/MacOS on x86_64
+
+#if CPU(X86_64) && OS(WINDOWS)
+ // Register allocation is not (yet) supported on win64, because the ABI related stack handling
+ // is not completely implemented. Specifically, the saving of xmm registers, and the saving of
+ // incoming function parameters to the shadow space is missing.
+ enum { RegAllocIsSupported = 0 };
+
+ static const JSC::MacroAssembler::RegisterID StackFrameRegister = JSC::X86Registers::ebp;
+ static const JSC::MacroAssembler::RegisterID StackPointerRegister = JSC::X86Registers::esp;
+ static const JSC::MacroAssembler::RegisterID LocalsRegister = JSC::X86Registers::r12;
+ static const JSC::MacroAssembler::RegisterID ContextRegister = JSC::X86Registers::r14;
+ static const JSC::MacroAssembler::RegisterID ReturnValueRegister = JSC::X86Registers::eax;
+ static const JSC::MacroAssembler::RegisterID ScratchRegister = JSC::X86Registers::r10;
+ static const JSC::MacroAssembler::FPRegisterID FPGpr0 = JSC::X86Registers::xmm0;
+ static const JSC::MacroAssembler::FPRegisterID FPGpr1 = JSC::X86Registers::xmm1;
+
+ static RegisterInformation getPlatformRegisterInfo()
+ {
+ typedef RegisterInfo RI;
+ return RegisterInformation()
+ << RI(JSC::X86Registers::ebx, QStringLiteral("rbx"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined)
+ << RI(JSC::X86Registers::edi, QStringLiteral("rdi"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined)
+ << RI(JSC::X86Registers::esi, QStringLiteral("rsi"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined)
+ << RI(JSC::X86Registers::edx, QStringLiteral("rdx"), RI::RegularRegister, RI::CallerSaved, RI::Predefined)
+ << RI(JSC::X86Registers::r9, QStringLiteral("r9"), RI::RegularRegister, RI::CallerSaved, RI::Predefined)
+ << RI(JSC::X86Registers::r8, QStringLiteral("r8"), RI::RegularRegister, RI::CallerSaved, RI::Predefined)
+ << RI(JSC::X86Registers::r12, QStringLiteral("r12"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined)
+ << RI(JSC::X86Registers::r13, QStringLiteral("r13"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined)
+ << RI(JSC::X86Registers::r14, QStringLiteral("r14"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined)
+ << RI(JSC::X86Registers::r15, QStringLiteral("r15"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined)
+ ;
+ }
+
+#define HAVE_ALU_OPS_WITH_MEM_OPERAND 1
+#define VALUE_FITS_IN_REGISTER
+ static const int RegisterSize = 8;
+
+#define ARGUMENTS_IN_REGISTERS
+ static const int RegisterArgumentCount = 4;
+ static JSC::MacroAssembler::RegisterID registerForArgument(int index)
+ {
+ static JSC::MacroAssembler::RegisterID regs[RegisterArgumentCount] = {
+ JSC::X86Registers::ecx,
+ JSC::X86Registers::edx,
+ JSC::X86Registers::r8,
+ JSC::X86Registers::r9
+ };
+ Q_ASSERT(index >= 0 && index < RegisterArgumentCount);
+ return regs[index];
+ };
+
+ static const int StackAlignment = 16;
+ static const int StackShadowSpace = 32;
+ static const int StackSpaceAllocatedUponFunctionEntry = RegisterSize; // Return address is pushed onto stack by the CPU.
+ static void platformEnterStandardStackFrame(JSC::MacroAssembler *as) { Q_UNUSED(as); }
+ static void platformLeaveStandardStackFrame(JSC::MacroAssembler *as) { Q_UNUSED(as); }
+#endif // Windows on x86_64
+
+#if CPU(ARM)
+ enum { RegAllocIsSupported = 1 };
+
+ // The AAPCS specifies that the platform ABI has to define the usage of r9. Known are:
+ // - The GNU/Linux ABI defines it as an additional callee-saved variable register (v6).
+ // - iOS (for which we cannot JIT, but still...) defines it as having a special use, so we do
+ // not touch it, nor use it.
+ // - Any other platform has not been verified, so we conservatively assume we cannot use it.
+#if OS(LINUX)
+#define CAN_USE_R9
+#endif
+
+ // There are two designated frame-pointer registers on ARM, depending on which instruction set
+ // is used for the subroutine: r7 for Thumb or Thumb2, and r11 for ARM. We assign the constants
+ // accordingly, and assign the locals-register to the "other" register.
+#if CPU(ARM_THUMB2)
+ static const JSC::MacroAssembler::RegisterID StackFrameRegister = JSC::ARMRegisters::r7;
+ static const JSC::MacroAssembler::RegisterID LocalsRegister = JSC::ARMRegisters::r11;
+#else // Thumbs down
+ static const JSC::MacroAssembler::RegisterID StackFrameRegister = JSC::ARMRegisters::r11;
+ static const JSC::MacroAssembler::RegisterID LocalsRegister = JSC::ARMRegisters::r7;
+#endif
+ static const JSC::MacroAssembler::RegisterID StackPointerRegister = JSC::ARMRegisters::r13;
+ static const JSC::MacroAssembler::RegisterID ScratchRegister = JSC::ARMRegisters::r6;
+ static const JSC::MacroAssembler::RegisterID ContextRegister = JSC::ARMRegisters::r5;
+ static const JSC::MacroAssembler::RegisterID ReturnValueRegister = JSC::ARMRegisters::r0;
+ static const JSC::MacroAssembler::FPRegisterID FPGpr0 = JSC::ARMRegisters::d0;
+ static const JSC::MacroAssembler::FPRegisterID FPGpr1 = JSC::ARMRegisters::d1;
+
+ static RegisterInformation getPlatformRegisterInfo()
+ {
+ typedef RegisterInfo RI;
+ return RegisterInformation()
+ << RI(JSC::ARMRegisters::r0, QStringLiteral("r0"), RI::RegularRegister, RI::CallerSaved, RI::Predefined)
+ << RI(JSC::ARMRegisters::r1, QStringLiteral("r1"), RI::RegularRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::ARMRegisters::r2, QStringLiteral("r2"), RI::RegularRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::ARMRegisters::r3, QStringLiteral("r3"), RI::RegularRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::ARMRegisters::r4, QStringLiteral("r4"), RI::RegularRegister, RI::CalleeSaved, RI::RegAlloc)
+ << RI(JSC::ARMRegisters::r5, QStringLiteral("r5"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined)
+ << RI(JSC::ARMRegisters::r6, QStringLiteral("r6"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined)
+#if !CPU(ARM_THUMB2)
+ << RI(JSC::ARMRegisters::r7, QStringLiteral("r7"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined)
+#endif
+ << RI(JSC::ARMRegisters::r8, QStringLiteral("r8"), RI::RegularRegister, RI::CalleeSaved, RI::RegAlloc)
+#ifdef CAN_USE_R9
+ << RI(JSC::ARMRegisters::r9, QStringLiteral("r9"), RI::RegularRegister, RI::CalleeSaved, RI::RegAlloc)
+#endif
+ << RI(JSC::ARMRegisters::r10, QStringLiteral("r10"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined)
+#if CPU(ARM_THUMB2)
+ << RI(JSC::ARMRegisters::r11, QStringLiteral("r11"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined)
+#endif
+ << RI(JSC::ARMRegisters::d2, QStringLiteral("d2"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::ARMRegisters::d3, QStringLiteral("d3"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::ARMRegisters::d4, QStringLiteral("d4"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::ARMRegisters::d5, QStringLiteral("d5"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc)
+ << RI(JSC::ARMRegisters::d6, QStringLiteral("d6"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc)
+ ;
+ // TODO: someone should check what's up with d8-d15: are they alway available, and are they caller or callee saved?
+ }
+
+#undef HAVE_ALU_OPS_WITH_MEM_OPERAND
+#undef VALUE_FITS_IN_REGISTER
+ static const int RegisterSize = 4;
+
+#define ARGUMENTS_IN_REGISTERS
+ static const int RegisterArgumentCount = 4;
+ static JSC::MacroAssembler::RegisterID registerForArgument(int index)
+ {
+ static JSC::MacroAssembler::RegisterID regs[RegisterArgumentCount] = {
+ JSC::ARMRegisters::r0,
+ JSC::ARMRegisters::r1,
+ JSC::ARMRegisters::r2,
+ JSC::ARMRegisters::r3
+ };
+
+ Q_ASSERT(index >= 0 && index < RegisterArgumentCount);
+ return regs[index];
+ };
+
+ static const int StackAlignment = 8; // Per AAPCS
+ static const int StackShadowSpace = 0;
+ static const int StackSpaceAllocatedUponFunctionEntry = 1 * RegisterSize; // Registers saved in platformEnterStandardStackFrame below.
+ static void platformEnterStandardStackFrame(JSC::MacroAssembler *as) { as->push(JSC::ARMRegisters::lr); }
+ static void platformLeaveStandardStackFrame(JSC::MacroAssembler *as) { as->pop(JSC::ARMRegisters::lr); }
+#endif // Linux on ARM (32 bit)
+
+public: // utility functions
+ static RegisterInformation getRegisterInfo()
+ {
+ static const RegisterInformation info = getPlatformRegisterInfo();
+
+ return info;
+ }
+
+ static RegisterInformation &getCalleeSavedRegisters()
+ {
+ static RegisterInformation regs;
+ if (regs.isEmpty()) {
+ foreach (const RegisterInfo &info, getRegisterInfo()) {
+#if defined(RESTORE_EBX_ON_CALL)
+ if (info.reg<JSC::X86Registers::RegisterID>() == JSC::X86Registers::ebx) {
+ regs.append(info);
+ continue;
+ }
+#endif // RESTORE_EBX_ON_CALL
+ if (info.isCalleeSaved())
+ regs.append(info);
+ }
+ }
+
+ return regs;
+ }
+
+ static int calleeSavedRegisterCount()
+ {
+ return getCalleeSavedRegisters().size();
+ }
+};
+
+} // JIT namespace
+} // QV4 namespace
+
+QT_END_NAMESPACE
+
+#endif // ENABLE(ASSEMBLER)
+
+#endif // QV4TARGETPLATFORM_P_H
diff --git a/src/qml/jit/qv4unop.cpp b/src/qml/jit/qv4unop.cpp
index 40f86f91b5..d92b5797cd 100644
--- a/src/qml/jit/qv4unop.cpp
+++ b/src/qml/jit/qv4unop.cpp
@@ -51,7 +51,7 @@ using namespace JIT;
#define setOp(operation) \
do { call = operation; name = stringIfy(operation); } while (0)
-void Unop::generate(IR::Temp *source, IR::Temp *target)
+void Unop::generate(IR::Expr *source, IR::Expr *target)
{
Runtime::UnaryOperation call = 0;
const char *name = 0;
@@ -77,16 +77,17 @@ void Unop::generate(IR::Temp *source, IR::Temp *target)
}
}
-void Unop::generateUMinus(IR::Temp *source, IR::Temp *target)
+void Unop::generateUMinus(IR::Expr *source, IR::Expr *target)
{
+ IR::Temp *targetTemp = target->asTemp();
if (source->type == IR::SInt32Type) {
Assembler::RegisterID tReg = Assembler::ScratchRegister;
- if (target->kind == IR::Temp::PhysicalRegister)
- tReg = (Assembler::RegisterID) target->index;
+ if (targetTemp && targetTemp->kind == IR::Temp::PhysicalRegister)
+ tReg = (Assembler::RegisterID) targetTemp->index;
Assembler::RegisterID sReg = as->toInt32Register(source, tReg);
as->move(sReg, tReg);
as->neg32(tReg);
- if (target->kind != IR::Temp::PhysicalRegister)
+ if (!targetTemp || targetTemp->kind != IR::Temp::PhysicalRegister)
as->storeInt32(tReg, target);
return;
}
@@ -94,24 +95,25 @@ void Unop::generateUMinus(IR::Temp *source, IR::Temp *target)
as->generateFunctionCallImp(target, "Runtime::uMinus", Runtime::uMinus, Assembler::PointerToValue(source));
}
-void Unop::generateNot(IR::Temp *source, IR::Temp *target)
+void Unop::generateNot(IR::Expr *source, IR::Expr *target)
{
+ IR::Temp *targetTemp = target->asTemp();
if (source->type == IR::BoolType) {
Assembler::RegisterID tReg = Assembler::ScratchRegister;
- if (target->kind == IR::Temp::PhysicalRegister)
- tReg = (Assembler::RegisterID) target->index;
+ if (targetTemp && targetTemp->kind == IR::Temp::PhysicalRegister)
+ tReg = (Assembler::RegisterID) targetTemp->index;
as->xor32(Assembler::TrustedImm32(0x1), as->toInt32Register(source, tReg), tReg);
- if (target->kind != IR::Temp::PhysicalRegister)
+ if (!targetTemp || targetTemp->kind != IR::Temp::PhysicalRegister)
as->storeBool(tReg, target);
return;
} else if (source->type == IR::SInt32Type) {
Assembler::RegisterID tReg = Assembler::ScratchRegister;
- if (target->kind == IR::Temp::PhysicalRegister)
- tReg = (Assembler::RegisterID) target->index;
+ if (targetTemp && targetTemp->kind == IR::Temp::PhysicalRegister)
+ tReg = (Assembler::RegisterID) targetTemp->index;
as->compare32(Assembler::Equal,
as->toInt32Register(source, Assembler::ScratchRegister), Assembler::TrustedImm32(0),
tReg);
- if (target->kind != IR::Temp::PhysicalRegister)
+ if (!targetTemp || targetTemp->kind != IR::Temp::PhysicalRegister)
as->storeBool(tReg, target);
return;
} else if (source->type == IR::DoubleType) {
@@ -122,14 +124,15 @@ void Unop::generateNot(IR::Temp *source, IR::Temp *target)
as->generateFunctionCallImp(target, "Runtime::uNot", Runtime::uNot, Assembler::PointerToValue(source));
}
-void Unop::generateCompl(IR::Temp *source, IR::Temp *target)
+void Unop::generateCompl(IR::Expr *source, IR::Expr *target)
{
+ IR::Temp *targetTemp = target->asTemp();
if (source->type == IR::SInt32Type) {
Assembler::RegisterID tReg = Assembler::ScratchRegister;
- if (target->kind == IR::Temp::PhysicalRegister)
- tReg = (Assembler::RegisterID) target->index;
+ if (targetTemp && targetTemp->kind == IR::Temp::PhysicalRegister)
+ tReg = (Assembler::RegisterID) targetTemp->index;
as->xor32(Assembler::TrustedImm32(0xffffffff), as->toInt32Register(source, tReg), tReg);
- if (target->kind != IR::Temp::PhysicalRegister)
+ if (!targetTemp || targetTemp->kind != IR::Temp::PhysicalRegister)
as->storeInt32(tReg, target);
return;
}
diff --git a/src/qml/jit/qv4unop_p.h b/src/qml/jit/qv4unop_p.h
index a8c62182ad..07fb6e5ad6 100644
--- a/src/qml/jit/qv4unop_p.h
+++ b/src/qml/jit/qv4unop_p.h
@@ -59,11 +59,11 @@ struct Unop {
, op(operation)
{}
- void generate(IR::Temp *source, IR::Temp *target);
+ void generate(IR::Expr *source, IR::Expr *target);
- void generateUMinus(IR::Temp *source, IR::Temp *target);
- void generateNot(IR::Temp *source, IR::Temp *target);
- void generateCompl(IR::Temp *source, IR::Temp *target);
+ void generateUMinus(IR::Expr *source, IR::Expr *target);
+ void generateNot(IR::Expr *source, IR::Expr *target);
+ void generateCompl(IR::Expr *source, IR::Expr *target);
Assembler *as;
IR::AluOp op;
diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp
index 9cb727dd63..929361bf72 100644
--- a/src/qml/jsapi/qjsengine.cpp
+++ b/src/qml/jsapi/qjsengine.cpp
@@ -50,6 +50,7 @@
#include "private/qv4globalobject_p.h"
#include "private/qv4script_p.h"
#include "private/qv4runtime_p.h"
+#include <private/qqmlbuiltinfunctions_p.h>
#include <QtCore/qdatetime.h>
#include <QtCore/qmetaobject.h>
@@ -232,6 +233,45 @@ void QJSEngine::collectGarbage()
}
/*!
+ \since 5.4
+
+ Installs translator functions on the given \a object, or on the Global
+ Object if no object is specified.
+
+ The relation between script translator functions and C++ translator
+ functions is described in the following table:
+
+ \table
+ \header \li Script Function \li Corresponding C++ Function
+ \row \li qsTr() \li QObject::tr()
+ \row \li QT_TR_NOOP() \li QT_TR_NOOP()
+ \row \li qsTranslate() \li QCoreApplication::translate()
+ \row \li QT_TRANSLATE_NOOP() \li QT_TRANSLATE_NOOP()
+ \row \li qsTrId() \li qtTrId()
+ \row \li QT_TRID_NOOP() \li QT_TRID_NOOP()
+ \endtable
+
+ \sa {Internationalization with Qt}
+*/
+void QJSEngine::installTranslatorFunctions(const QJSValue &object)
+{
+ QV4::ExecutionEngine *v4 = d->m_v4Engine;
+ QV4::Scope scope(v4);
+ QJSValuePrivate *vp = QJSValuePrivate::get(object);
+ QV4::ScopedObject obj(scope, vp->getValue(v4));
+ if (!obj)
+ obj = v4->globalObject;
+#ifndef QT_NO_TRANSLATION
+ obj->defineDefaultProperty(QStringLiteral("qsTranslate"), QV4::GlobalExtensions::method_qsTranslate);
+ obj->defineDefaultProperty(QStringLiteral("QT_TRANSLATE_NOOP"), QV4::GlobalExtensions::method_qsTranslateNoOp);
+ obj->defineDefaultProperty(QStringLiteral("qsTr"), QV4::GlobalExtensions::method_qsTr);
+ obj->defineDefaultProperty(QStringLiteral("QT_TR_NOOP"), QV4::GlobalExtensions::method_qsTrNoOp);
+ obj->defineDefaultProperty(QStringLiteral("qsTrId"), QV4::GlobalExtensions::method_qsTrId);
+ obj->defineDefaultProperty(QStringLiteral("QT_TRID_NOOP"), QV4::GlobalExtensions::method_qsTrIdNoOp);
+#endif
+}
+
+/*!
Evaluates \a program, using \a lineNumber as the base line number,
and returns the result of the evaluation.
@@ -269,7 +309,7 @@ QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, in
QV4::ScopedValue result(scope);
QV4::Script script(ctx, program, fileName, lineNumber);
- script.strictMode = ctx->strictMode;
+ script.strictMode = ctx->d()->strictMode;
script.inheritContext = true;
script.parse();
if (!scope.engine->hasException)
diff --git a/src/qml/jsapi/qjsengine.h b/src/qml/jsapi/qjsengine.h
index 0a575f84e9..9d810a85d1 100644
--- a/src/qml/jsapi/qjsengine.h
+++ b/src/qml/jsapi/qjsengine.h
@@ -89,6 +89,8 @@ public:
void collectGarbage();
+ void installTranslatorFunctions(const QJSValue &object = QJSValue());
+
QV8Engine *handle() const { return d; }
private:
diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp
index b17ac17752..ec45ce9374 100644
--- a/src/qml/jsapi/qjsvalue.cpp
+++ b/src/qml/jsapi/qjsvalue.cpp
@@ -385,7 +385,7 @@ double QJSValue::toNumber() const
QV4::ExecutionContext *ctx = d->engine ? d->engine->currentContext() : 0;
double dbl = d->value.toNumber();
- if (ctx && ctx->engine->hasException) {
+ if (ctx && ctx->d()->engine->hasException) {
ctx->catchException();
return 0;
}
@@ -411,7 +411,7 @@ bool QJSValue::toBool() const
QV4::ExecutionContext *ctx = d->engine ? d->engine->currentContext() : 0;
bool b = d->value.toBoolean();
- if (ctx && ctx->engine->hasException) {
+ if (ctx && ctx->d()->engine->hasException) {
ctx->catchException();
return false;
}
@@ -437,7 +437,7 @@ qint32 QJSValue::toInt() const
QV4::ExecutionContext *ctx = d->engine ? d->engine->currentContext() : 0;
qint32 i = d->value.toInt32();
- if (ctx && ctx->engine->hasException) {
+ if (ctx && ctx->d()->engine->hasException) {
ctx->catchException();
return 0;
}
@@ -463,7 +463,7 @@ quint32 QJSValue::toUInt() const
QV4::ExecutionContext *ctx = d->engine ? d->engine->currentContext() : 0;
quint32 u = d->value.toUInt32();
- if (ctx && ctx->engine->hasException) {
+ if (ctx && ctx->d()->engine->hasException) {
ctx->catchException();
return 0;
}
@@ -682,7 +682,7 @@ QJSValue QJSValue::prototype() const
Scoped<Object> p(scope, o->prototype());
if (!p)
return QJSValue(NullValue);
- return new QJSValuePrivate(o->internalClass->engine, p);
+ return new QJSValuePrivate(o->internalClass()->engine, p);
}
/*!
@@ -861,7 +861,7 @@ QJSValue QJSValue::property(const QString& name) const
s->makeIdentifier();
QV4::ExecutionContext *ctx = engine->currentContext();
QV4::ScopedValue result(scope);
- result = o->get(s);
+ result = o->get(s.getPointer());
if (scope.hasException())
result = ctx->catchException();
@@ -893,7 +893,7 @@ QJSValue QJSValue::property(quint32 arrayIndex) const
QV4::ExecutionContext *ctx = engine->currentContext();
QV4::ScopedValue result(scope);
- result = arrayIndex == UINT_MAX ? o->get(engine->id_uintMax) : o->getIndexed(arrayIndex);
+ result = arrayIndex == UINT_MAX ? o->get(engine->id_uintMax.getPointer()) : o->getIndexed(arrayIndex);
if (scope.hasException())
result = ctx->catchException();
return new QJSValuePrivate(engine, result);
@@ -936,7 +936,7 @@ void QJSValue::setProperty(const QString& name, const QJSValue& value)
QV4::ExecutionContext *ctx = engine->currentContext();
s->makeIdentifier();
QV4::ScopedValue v(scope, value.d->getValue(engine));
- o->put(s, v);
+ o->put(s.getPointer(), v);
if (scope.hasException())
ctx->catchException();
}
@@ -969,7 +969,7 @@ void QJSValue::setProperty(quint32 arrayIndex, const QJSValue& value)
if (arrayIndex != UINT_MAX)
o->putIndexed(arrayIndex, v);
else
- o->put(engine->id_uintMax, v);
+ o->put(engine->id_uintMax.getPointer(), v);
if (scope.hasException())
ctx->catchException();
}
@@ -1004,7 +1004,7 @@ bool QJSValue::deleteProperty(const QString &name)
return false;
ScopedString s(scope, engine->newString(name));
- bool b = o->deleteProperty(s);
+ bool b = o->deleteProperty(s.getPointer());
if (scope.hasException())
ctx->catchException();
return b;
@@ -1028,7 +1028,7 @@ bool QJSValue::hasProperty(const QString &name) const
return false;
ScopedString s(scope, engine->newIdentifier(name));
- return o->hasProperty(s);
+ return o->hasProperty(s.getPointer());
}
/*!
@@ -1049,7 +1049,7 @@ bool QJSValue::hasOwnProperty(const QString &name) const
return false;
ScopedString s(scope, engine->newIdentifier(name));
- return o->hasOwnProperty(s);
+ return o->hasOwnProperty(s.getPointer());
}
/*!
diff --git a/src/qml/jsapi/qjsvalueiterator.cpp b/src/qml/jsapi/qjsvalueiterator.cpp
index 6dcfafaa27..449fb8235a 100644
--- a/src/qml/jsapi/qjsvalueiterator.cpp
+++ b/src/qml/jsapi/qjsvalueiterator.cpp
@@ -108,8 +108,10 @@ QJSValueIterator::QJSValueIterator(const QJSValue& object)
return;
QV4::Scope scope(v4);
QV4::Scoped<QV4::ForEachIteratorObject> it(scope, d_ptr->iterator.value());
- it->it.flags = QV4::ObjectIterator::NoFlags;
- it->it.next(d_ptr->nextName, &d_ptr->nextIndex, &d_ptr->nextProperty, &d_ptr->nextAttributes);
+ it->d()->it.flags = QV4::ObjectIterator::NoFlags;
+ QV4::String *nm = 0;
+ it->d()->it.next(nm, &d_ptr->nextIndex, &d_ptr->nextProperty, &d_ptr->nextAttributes);
+ d_ptr->nextName = nm;
}
/*!
@@ -155,7 +157,9 @@ bool QJSValueIterator::next()
return false;
QV4::Scope scope(v4);
QV4::Scoped<QV4::ForEachIteratorObject> it(scope, d_ptr->iterator.value());
- it->it.next(d_ptr->nextName, &d_ptr->nextIndex, &d_ptr->nextProperty, &d_ptr->nextAttributes);
+ QV4::String *nm = 0;
+ it->d()->it.next(nm, &d_ptr->nextIndex, &d_ptr->nextProperty, &d_ptr->nextAttributes);
+ d_ptr->nextName = nm;
return !!d_ptr->currentName || d_ptr->currentIndex != UINT_MAX;
}
@@ -229,8 +233,10 @@ QJSValueIterator& QJSValueIterator::operator=(QJSValue& object)
QV4::ScopedObject o(scope, jsp->value);
d_ptr->iterator = v4->newForEachIteratorObject(v4->currentContext(), o)->asReturnedValue();
QV4::Scoped<QV4::ForEachIteratorObject> it(scope, d_ptr->iterator.value());
- it->it.flags = QV4::ObjectIterator::NoFlags;
- it->it.next(d_ptr->nextName, &d_ptr->nextIndex, &d_ptr->nextProperty, &d_ptr->nextAttributes);
+ it->d()->it.flags = QV4::ObjectIterator::NoFlags;
+ QV4::String *nm = 0;
+ it->d()->it.next(nm, &d_ptr->nextIndex, &d_ptr->nextProperty, &d_ptr->nextAttributes);
+ d_ptr->nextName = nm;
return *this;
}
diff --git a/src/qml/jsruntime/jsruntime.pri b/src/qml/jsruntime/jsruntime.pri
index 72010d3fa8..c27aaa90d8 100644
--- a/src/qml/jsruntime/jsruntime.pri
+++ b/src/qml/jsruntime/jsruntime.pri
@@ -105,13 +105,6 @@ SOURCES += \
$$PWD/qv4string.cpp \
$$PWD/qv4value.cpp
-# Use SSE2 floating point math on 32 bit instead of the default
-# 387 to make test results pass on 32 and on 64 bit builds.
-linux-g++*:isEqual(QT_ARCH,i386) {
- QMAKE_CFLAGS += -march=pentium4 -msse2 -mfpmath=sse
- QMAKE_CXXFLAGS += -march=pentium4 -msse2 -mfpmath=sse
-}
-
valgrind {
DEFINES += V4_USE_VALGRIND
}
diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp
index 987b228209..71563b7b0d 100644
--- a/src/qml/jsruntime/qv4argumentsobject.cpp
+++ b/src/qml/jsruntime/qv4argumentsobject.cpp
@@ -46,63 +46,58 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(ArgumentsObject);
-ArgumentsObject::ArgumentsObject(CallContext *context)
- : Object(context->strictMode ? context->engine->strictArgumentsObjectClass : context->engine->argumentsObjectClass)
+ArgumentsObject::Data::Data(CallContext *context)
+ : Object::Data(context->d()->strictMode ? context->d()->engine->strictArgumentsObjectClass : context->d()->engine->argumentsObjectClass)
, context(context)
, fullyCreated(false)
{
- ExecutionEngine *v4 = context->engine;
+ Q_ASSERT(internalClass->vtable == staticVTable());
+
+ ExecutionEngine *v4 = context->d()->engine;
Scope scope(v4);
- ScopedObject protectThis(scope, this);
+ Scoped<ArgumentsObject> args(scope, this);
- setArrayType(ArrayData::Complex);
+ args->setArrayType(ArrayData::Complex);
- if (context->strictMode) {
- Q_ASSERT(CalleePropertyIndex == internalClass->find(context->engine->id_callee));
- Q_ASSERT(CallerPropertyIndex == internalClass->find(context->engine->id_caller));
- propertyAt(CalleePropertyIndex)->value = v4->thrower;
- propertyAt(CalleePropertyIndex)->set = v4->thrower;
- propertyAt(CallerPropertyIndex)->value = v4->thrower;
- propertyAt(CallerPropertyIndex)->set = v4->thrower;
+ if (context->d()->strictMode) {
+ Q_ASSERT(CalleePropertyIndex == args->internalClass()->find(context->d()->engine->id_callee));
+ Q_ASSERT(CallerPropertyIndex == args->internalClass()->find(context->d()->engine->id_caller));
+ args->propertyAt(CalleePropertyIndex)->value = v4->thrower;
+ args->propertyAt(CalleePropertyIndex)->set = v4->thrower;
+ args->propertyAt(CallerPropertyIndex)->value = v4->thrower;
+ args->propertyAt(CallerPropertyIndex)->set = v4->thrower;
- arrayReserve(context->callData->argc);
- arrayPut(0, context->callData->args, context->callData->argc);
- fullyCreated = true;
+ args->arrayReserve(context->d()->callData->argc);
+ args->arrayPut(0, context->d()->callData->args, context->d()->callData->argc);
+ args->d()->fullyCreated = true;
} else {
- hasAccessorProperty = 1;
- Q_ASSERT(CalleePropertyIndex == internalClass->find(context->engine->id_callee));
- memberData[CalleePropertyIndex] = context->function->asReturnedValue();
+ args->setHasAccessorProperty();
+ Q_ASSERT(CalleePropertyIndex == args->internalClass()->find(context->d()->engine->id_callee));
+ args->memberData()[CalleePropertyIndex] = context->d()->function->asReturnedValue();
}
- Q_ASSERT(LengthPropertyIndex == internalClass->find(context->engine->id_length));
- memberData[LengthPropertyIndex] = Primitive::fromInt32(context->realArgumentCount);
-
- Q_ASSERT(internalClass->vtable == staticVTable());
-}
-
-void ArgumentsObject::destroy(Managed *that)
-{
- static_cast<ArgumentsObject *>(that)->~ArgumentsObject();
+ Q_ASSERT(LengthPropertyIndex == args->internalClass()->find(context->d()->engine->id_length));
+ args->memberData()[LengthPropertyIndex] = Primitive::fromInt32(context->d()->realArgumentCount);
}
void ArgumentsObject::fullyCreate()
{
- if (fullyCreated)
+ if (fullyCreated())
return;
- uint numAccessors = qMin((int)context->function->formalParameterCount(), context->realArgumentCount);
- uint argCount = qMin(context->realArgumentCount, context->callData->argc);
+ uint numAccessors = qMin((int)context()->d()->function->formalParameterCount(), context()->d()->realArgumentCount);
+ uint argCount = qMin(context()->d()->realArgumentCount, context()->d()->callData->argc);
ArrayData::realloc(this, ArrayData::Sparse, 0, argCount, true);
- context->engine->requireArgumentsAccessors(numAccessors);
- mappedArguments.ensureIndex(engine(), numAccessors);
+ context()->d()->engine->requireArgumentsAccessors(numAccessors);
+ mappedArguments().ensureIndex(engine(), numAccessors);
for (uint i = 0; i < (uint)numAccessors; ++i) {
- mappedArguments[i] = context->callData->args[i];
- arraySet(i, context->engine->argumentsAccessors[i], Attr_Accessor);
+ mappedArguments()[i] = context()->d()->callData->args[i];
+ arraySet(i, context()->d()->engine->argumentsAccessors[i], Attr_Accessor);
}
- arrayPut(numAccessors, context->callData->args + numAccessors, argCount - numAccessors);
+ arrayPut(numAccessors, context()->d()->callData->args + numAccessors, argCount - numAccessors);
for (uint i = numAccessors; i < argCount; ++i)
setArrayAttributes(i, Attr_Data);
- fullyCreated = true;
+ d()->fullyCreated = true;
}
bool ArgumentsObject::defineOwnProperty(ExecutionContext *ctx, uint index, const Property &desc, PropertyAttributes attrs)
@@ -110,26 +105,26 @@ bool ArgumentsObject::defineOwnProperty(ExecutionContext *ctx, uint index, const
fullyCreate();
Scope scope(ctx);
- Property *pd = arrayData->getProperty(index);
+ Property *pd = arrayData()->getProperty(index);
Property map;
PropertyAttributes mapAttrs;
bool isMapped = false;
- uint numAccessors = qMin((int)context->function->formalParameterCount(), context->realArgumentCount);
+ uint numAccessors = qMin((int)context()->d()->function->formalParameterCount(), context()->d()->realArgumentCount);
if (pd && index < (uint)numAccessors)
- isMapped = arrayData->attributes(index).isAccessor() && pd->getter() == context->engine->argumentsAccessors[index].getter();
+ isMapped = arrayData()->attributes(index).isAccessor() && pd->getter() == context()->d()->engine->argumentsAccessors[index].getter();
if (isMapped) {
- mapAttrs = arrayData->attributes(index);
+ mapAttrs = arrayData()->attributes(index);
map.copy(*pd, mapAttrs);
setArrayAttributes(index, Attr_Data);
- pd = arrayData->getProperty(index);
- pd->value = mappedArguments[index];
+ pd = arrayData()->getProperty(index);
+ pd->value = mappedArguments()[index];
}
- bool strict = ctx->strictMode;
- ctx->strictMode = false;
+ bool strict = ctx->d()->strictMode;
+ ctx->d()->strictMode = false;
bool result = Object::defineOwnProperty2(ctx, index, desc, attrs);
- ctx->strictMode = strict;
+ ctx->d()->strictMode = strict;
if (isMapped && attrs.isData()) {
ScopedCallData callData(scope, 1);
@@ -139,12 +134,12 @@ bool ArgumentsObject::defineOwnProperty(ExecutionContext *ctx, uint index, const
if (attrs.isWritable()) {
setArrayAttributes(index, mapAttrs);
- pd = arrayData->getProperty(index);
+ pd = arrayData()->getProperty(index);
pd->copy(map, mapAttrs);
}
}
- if (ctx->strictMode && !result)
+ if (ctx->d()->strictMode && !result)
return ctx->throwTypeError();
return result;
}
@@ -152,13 +147,13 @@ bool ArgumentsObject::defineOwnProperty(ExecutionContext *ctx, uint index, const
ReturnedValue ArgumentsObject::getIndexed(Managed *m, uint index, bool *hasProperty)
{
ArgumentsObject *args = static_cast<ArgumentsObject *>(m);
- if (args->fullyCreated)
+ if (args->fullyCreated())
return Object::getIndexed(m, index, hasProperty);
- if (index < static_cast<uint>(args->context->callData->argc)) {
+ if (index < static_cast<uint>(args->context()->d()->callData->argc)) {
if (hasProperty)
*hasProperty = true;
- return args->context->callData->args[index].asReturnedValue();
+ return args->context()->d()->callData->args[index].asReturnedValue();
}
if (hasProperty)
*hasProperty = false;
@@ -168,21 +163,21 @@ ReturnedValue ArgumentsObject::getIndexed(Managed *m, uint index, bool *hasPrope
void ArgumentsObject::putIndexed(Managed *m, uint index, const ValueRef value)
{
ArgumentsObject *args = static_cast<ArgumentsObject *>(m);
- if (!args->fullyCreated && index >= static_cast<uint>(args->context->callData->argc))
+ if (!args->fullyCreated() && index >= static_cast<uint>(args->context()->d()->callData->argc))
args->fullyCreate();
- if (args->fullyCreated) {
+ if (args->fullyCreated()) {
Object::putIndexed(m, index, value);
return;
}
- args->context->callData->args[index] = value;
+ args->context()->d()->callData->args[index] = value;
}
bool ArgumentsObject::deleteIndexedProperty(Managed *m, uint index)
{
ArgumentsObject *args = static_cast<ArgumentsObject *>(m);
- if (!args->fullyCreated)
+ if (!args->fullyCreated())
args->fullyCreate();
return Object::deleteIndexedProperty(m, index);
}
@@ -190,11 +185,11 @@ bool ArgumentsObject::deleteIndexedProperty(Managed *m, uint index)
PropertyAttributes ArgumentsObject::queryIndexed(const Managed *m, uint index)
{
const ArgumentsObject *args = static_cast<const ArgumentsObject *>(m);
- if (args->fullyCreated)
+ if (args->fullyCreated())
return Object::queryIndexed(m, index);
- uint numAccessors = qMin((int)args->context->function->formalParameterCount(), args->context->realArgumentCount);
- uint argCount = qMin(args->context->realArgumentCount, args->context->callData->argc);
+ uint numAccessors = qMin((int)args->context()->d()->function->formalParameterCount(), args->context()->d()->realArgumentCount);
+ uint argCount = qMin(args->context()->d()->realArgumentCount, args->context()->d()->callData->argc);
if (index >= argCount)
return PropertyAttributes();
if (index >= numAccessors)
@@ -213,8 +208,8 @@ ReturnedValue ArgumentsGetterFunction::call(Managed *getter, CallData *callData)
if (!o)
return v4->currentContext()->throwTypeError();
- Q_ASSERT(g->index < static_cast<unsigned>(o->context->callData->argc));
- return o->context->argument(g->index);
+ Q_ASSERT(g->index() < static_cast<unsigned>(o->context()->d()->callData->argc));
+ return o->context()->argument(g->index());
}
DEFINE_OBJECT_VTABLE(ArgumentsSetterFunction);
@@ -228,17 +223,17 @@ ReturnedValue ArgumentsSetterFunction::call(Managed *setter, CallData *callData)
if (!o)
return v4->currentContext()->throwTypeError();
- Q_ASSERT(s->index < static_cast<unsigned>(o->context->callData->argc));
- o->context->callData->args[s->index] = callData->argc ? callData->args[0].asReturnedValue() : Encode::undefined();
+ Q_ASSERT(s->index() < static_cast<unsigned>(o->context()->d()->callData->argc));
+ o->context()->d()->callData->args[s->index()] = callData->argc ? callData->args[0].asReturnedValue() : Encode::undefined();
return Encode::undefined();
}
void ArgumentsObject::markObjects(Managed *that, ExecutionEngine *e)
{
ArgumentsObject *o = static_cast<ArgumentsObject *>(that);
- if (o->context)
- o->context->mark(e);
- o->mappedArguments.mark(e);
+ if (o->context())
+ o->context()->mark(e);
+ o->mappedArguments().mark(e);
Object::markObjects(that, e);
}
diff --git a/src/qml/jsruntime/qv4argumentsobject_p.h b/src/qml/jsruntime/qv4argumentsobject_p.h
index 80c2a70501..59ab9f020e 100644
--- a/src/qml/jsruntime/qv4argumentsobject_p.h
+++ b/src/qml/jsruntime/qv4argumentsobject_p.h
@@ -50,43 +50,58 @@ namespace QV4 {
struct ArgumentsGetterFunction: FunctionObject
{
- V4_OBJECT
- uint index;
+ struct Data : FunctionObject::Data {
+ Data(ExecutionContext *scope, uint index)
+ : FunctionObject::Data(scope)
+ , index(index)
+ {
+ setVTable(staticVTable());
+ }
+ uint index;
+ };
+ V4_OBJECT(FunctionObject)
- ArgumentsGetterFunction(ExecutionContext *scope, uint index)
- : FunctionObject(scope), index(index) {
- setVTable(staticVTable());
- }
+ uint index() const { return d()->index; }
static ReturnedValue call(Managed *that, CallData *d);
};
struct ArgumentsSetterFunction: FunctionObject
{
- V4_OBJECT
- uint index;
+ struct Data : FunctionObject::Data {
+ Data(ExecutionContext *scope, uint index)
+ : FunctionObject::Data(scope)
+ , index(index)
+ {
+ setVTable(staticVTable());
+ }
+ uint index;
+ };
+ V4_OBJECT(FunctionObject)
- ArgumentsSetterFunction(ExecutionContext *scope, uint index)
- : FunctionObject(scope), index(index) {
- setVTable(staticVTable());
- }
+ uint index() const { return d()->index; }
static ReturnedValue call(Managed *that, CallData *callData);
};
struct ArgumentsObject: Object {
- V4_OBJECT
+ struct Data : Object::Data {
+ Data(CallContext *context);
+ CallContext *context;
+ bool fullyCreated;
+ Members mappedArguments;
+ };
+ V4_OBJECT(Object)
Q_MANAGED_TYPE(ArgumentsObject)
- CallContext *context;
- bool fullyCreated;
- Members mappedArguments;
- ArgumentsObject(CallContext *context);
- ~ArgumentsObject() {}
+
+ CallContext *context() const { return d()->context; }
+ bool fullyCreated() const { return d()->fullyCreated; }
+ Members &mappedArguments() { return d()->mappedArguments; }
static bool isNonStrictArgumentsObject(Managed *m) {
- return m->internalClass->vtable->type == Type_ArgumentsObject &&
- !static_cast<ArgumentsObject *>(m)->context->strictMode;
+ return m->internalClass()->vtable->type == Type_ArgumentsObject &&
+ !static_cast<ArgumentsObject *>(m)->context()->d()->strictMode;
}
enum {
@@ -100,7 +115,6 @@ struct ArgumentsObject: Object {
static bool deleteIndexedProperty(Managed *m, uint index);
static PropertyAttributes queryIndexed(const Managed *m, uint index);
static void markObjects(Managed *that, ExecutionEngine *e);
- static void destroy(Managed *);
void fullyCreate();
};
diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp
index ed2122fb89..f56c31b177 100644
--- a/src/qml/jsruntime/qv4arraydata.cpp
+++ b/src/qml/jsruntime/qv4arraydata.cpp
@@ -45,9 +45,25 @@
using namespace QV4;
+const QV4::ManagedVTable QV4::ArrayData::static_vtbl = {
+ 0,
+ QV4::ArrayData::IsExecutionContext,
+ QV4::ArrayData::IsString,
+ QV4::ArrayData::IsObject,
+ QV4::ArrayData::IsFunctionObject,
+ QV4::ArrayData::IsErrorObject,
+ QV4::ArrayData::IsArrayData,
+ 0,
+ QV4::ArrayData::MyType,
+ "ArrayData",
+ Q_VTABLE_FUNCTION(QV4::ArrayData, destroy),
+ 0,
+ isEqualTo
+};
+
const ArrayVTable SimpleArrayData::static_vtbl =
{
- DEFINE_MANAGED_VTABLE_INT(SimpleArrayData),
+ DEFINE_MANAGED_VTABLE_INT(SimpleArrayData, 0),
SimpleArrayData::Simple,
SimpleArrayData::reallocate,
SimpleArrayData::get,
@@ -64,7 +80,7 @@ const ArrayVTable SimpleArrayData::static_vtbl =
const ArrayVTable SparseArrayData::static_vtbl =
{
- DEFINE_MANAGED_VTABLE_INT(SparseArrayData),
+ DEFINE_MANAGED_VTABLE_INT(SparseArrayData, 0),
ArrayData::Sparse,
SparseArrayData::reallocate,
SparseArrayData::get,
@@ -82,7 +98,7 @@ const ArrayVTable SparseArrayData::static_vtbl =
void ArrayData::realloc(Object *o, Type newType, uint offset, uint alloc, bool enforceAttributes)
{
- ArrayData *d = o->arrayData;
+ ArrayData *d = o->arrayData();
uint oldAlloc = 0;
uint toCopy = 0;
@@ -90,19 +106,19 @@ void ArrayData::realloc(Object *o, Type newType, uint offset, uint alloc, bool e
alloc = 8;
if (d) {
- bool hasAttrs = d->attrs;
+ bool hasAttrs = d->attrs();
enforceAttributes |= hasAttrs;
- if (!offset && alloc <= d->alloc && newType == d->type && hasAttrs == enforceAttributes)
+ if (!offset && alloc <= d->alloc() && newType == d->type() && hasAttrs == enforceAttributes)
return;
- oldAlloc = d->alloc;
- if (d->type < Sparse) {
- offset = qMax(offset, static_cast<SimpleArrayData *>(d)->offset);
- toCopy = static_cast<SimpleArrayData *>(d)->len;
+ oldAlloc = d->alloc();
+ if (d->type() < Sparse) {
+ offset = qMax(offset, static_cast<SimpleArrayData *>(d)->offset());
+ toCopy = static_cast<SimpleArrayData *>(d)->len();
} else {
Q_ASSERT(!offset);
- toCopy = d->alloc;
+ toCopy = d->alloc();
newType = Sparse;
}
}
@@ -115,69 +131,69 @@ void ArrayData::realloc(Object *o, Type newType, uint offset, uint alloc, bool e
size += alloc*sizeof(PropertyAttributes);
if (newType < Sparse) {
- size += sizeof(SimpleArrayData);
+ size += sizeof(SimpleArrayData::Data);
SimpleArrayData *newData = static_cast<SimpleArrayData *>(o->engine()->memoryManager->allocManaged(size));
- new (newData) SimpleArrayData(o->engine());
- newData->alloc = alloc - offset;
- newData->type = newType;
- newData->data = reinterpret_cast<Value *>(newData + 1) + offset;
- newData->attrs = enforceAttributes ? reinterpret_cast<PropertyAttributes *>(newData->data + alloc) + offset : 0;
- newData->offset = offset;
- newData->len = d ? static_cast<SimpleArrayData *>(d)->len : 0;
- o->arrayData = newData;
+ new (newData->d()) SimpleArrayData::Data(o->engine());
+ newData->setAlloc(alloc - offset);
+ newData->setType(newType);
+ newData->setArrayData(reinterpret_cast<Value *>(newData->d() + 1) + offset);
+ newData->setAttrs(enforceAttributes ? reinterpret_cast<PropertyAttributes *>(newData->arrayData() + alloc) + offset : 0);
+ newData->offset() = offset;
+ newData->len() = d ? static_cast<SimpleArrayData *>(d)->len() : 0;
+ o->setArrayData(newData);
} else {
- size += sizeof(SparseArrayData);
+ size += sizeof(SparseArrayData::Data);
SparseArrayData *newData = static_cast<SparseArrayData *>(o->engine()->memoryManager->allocManaged(size));
- new (newData) SparseArrayData(o->engine());
- newData->alloc = alloc;
- newData->type = newType;
- newData->data = reinterpret_cast<Value *>(newData + 1);
- newData->attrs = enforceAttributes ? reinterpret_cast<PropertyAttributes *>(newData->data + alloc) : 0;
- o->arrayData = newData;
+ new (newData->d()) SparseArrayData::Data(o->engine());
+ newData->setAlloc(alloc);
+ newData->setType(newType);
+ newData->setArrayData(reinterpret_cast<Value *>(newData->d() + 1));
+ newData->setAttrs(enforceAttributes ? reinterpret_cast<PropertyAttributes *>(newData->arrayData() + alloc) : 0);
+ o->setArrayData(newData);
}
if (d) {
- memcpy(o->arrayData->data, d->data, sizeof(Value)*toCopy);
+ memcpy(o->arrayData()->arrayData(), d->arrayData(), sizeof(Value)*toCopy);
if (enforceAttributes) {
- if (d->attrs)
- memcpy(o->arrayData->attrs, d->attrs, sizeof(PropertyAttributes)*toCopy);
+ if (d->attrs())
+ memcpy(o->arrayData()->attrs(), d->attrs(), sizeof(PropertyAttributes)*toCopy);
else
for (uint i = 0; i < toCopy; ++i)
- o->arrayData->attrs[i] = Attr_Data;
+ o->arrayData()->attrs()[i] = Attr_Data;
}
}
if (newType != Sparse)
return;
- SparseArrayData *newData = static_cast<SparseArrayData *>(o->arrayData);
- if (d && d->type == Sparse) {
+ SparseArrayData *newData = static_cast<SparseArrayData *>(o->arrayData());
+ if (d && d->type() == Sparse) {
SparseArrayData *old = static_cast<SparseArrayData *>(d);
- newData->sparse = old->sparse;
- old->sparse = 0;
- newData->freeList = old->freeList;
+ newData->setSparse(old->sparse());
+ old->setSparse(0);
+ newData->freeList() = old->freeList();
} else {
- newData->sparse = new SparseArray;
- uint *lastFree = &newData->freeList;
+ newData->setSparse(new SparseArray);
+ uint *lastFree = &newData->freeList();
for (uint i = 0; i < toCopy; ++i) {
- if (!newData->data[i].isEmpty()) {
- SparseArrayNode *n = newData->sparse->insert(i);
+ if (!newData->arrayData()[i].isEmpty()) {
+ SparseArrayNode *n = newData->sparse()->insert(i);
n->value = i;
} else {
*lastFree = i;
- newData->data[i].tag = Value::Empty_Type;
- lastFree = &newData->data[i].uint_32;
+ newData->arrayData()[i].tag = Value::Empty_Type;
+ lastFree = &newData->arrayData()[i].uint_32;
}
}
}
- uint *lastFree = &newData->freeList;
- for (uint i = toCopy; i < newData->alloc; ++i) {
+ uint *lastFree = &newData->freeList();
+ for (uint i = toCopy; i < newData->alloc(); ++i) {
*lastFree = i;
- newData->data[i].tag = Value::Empty_Type;
- lastFree = &newData->data[i].uint_32;
+ newData->arrayData()[i].tag = Value::Empty_Type;
+ lastFree = &newData->arrayData()[i].uint_32;
}
- *lastFree = newData->alloc;
+ *lastFree = newData->alloc();
// ### Could explicitly free the old data
}
@@ -185,248 +201,244 @@ void ArrayData::realloc(Object *o, Type newType, uint offset, uint alloc, bool e
void SimpleArrayData::getHeadRoom(Object *o)
{
- SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData);
+ SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData());
Q_ASSERT(dd);
- Q_ASSERT(!dd->offset);
- uint offset = qMax(dd->len >> 2, (uint)16);
+ Q_ASSERT(!dd->offset());
+ uint offset = qMax(dd->len() >> 2, (uint)16);
realloc(o, Simple, offset, 0, false);
}
ArrayData *SimpleArrayData::reallocate(Object *o, uint n, bool enforceAttributes)
{
realloc(o, Simple, 0, n, enforceAttributes);
- return o->arrayData;
+ return o->arrayData();
}
void ArrayData::ensureAttributes(Object *o)
{
- if (o->arrayData && o->arrayData->attrs)
+ if (o->arrayData() && o->arrayData()->attrs())
return;
ArrayData::realloc(o, Simple, 0, 0, true);
}
-void SimpleArrayData::destroy(Managed *)
-{
-}
-
void SimpleArrayData::markObjects(Managed *d, ExecutionEngine *e)
{
SimpleArrayData *dd = static_cast<SimpleArrayData *>(d);
- uint l = dd->len;
+ uint l = dd->len();
for (uint i = 0; i < l; ++i)
- dd->data[i].mark(e);
+ dd->arrayData()[i].mark(e);
}
ReturnedValue SimpleArrayData::get(const ArrayData *d, uint index)
{
const SimpleArrayData *dd = static_cast<const SimpleArrayData *>(d);
- if (index >= dd->len)
+ if (index >= dd->len())
return Primitive::emptyValue().asReturnedValue();
- return dd->data[index].asReturnedValue();
+ return dd->arrayData()[index].asReturnedValue();
}
bool SimpleArrayData::put(Object *o, uint index, ValueRef value)
{
- SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData);
- Q_ASSERT(index >= dd->len || !dd->attrs || !dd->attrs[index].isAccessor());
+ SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData());
+ Q_ASSERT(index >= dd->len() || !dd->attrs() || !dd->attrs()[index].isAccessor());
// ### honour attributes
- dd->data[index] = value;
- if (index >= dd->len) {
- if (dd->attrs)
- dd->attrs[index] = Attr_Data;
- dd->len = index + 1;
+ dd->arrayData()[index] = value;
+ if (index >= dd->len()) {
+ if (dd->attrs())
+ dd->attrs()[index] = Attr_Data;
+ dd->len() = index + 1;
}
return true;
}
bool SimpleArrayData::del(Object *o, uint index)
{
- SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData);
- if (index >= dd->len)
+ SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData());
+ if (index >= dd->len())
return true;
- if (!dd->attrs || dd->attrs[index].isConfigurable()) {
- dd->data[index] = Primitive::emptyValue();
- if (dd->attrs)
- dd->attrs[index] = Attr_Data;
+ if (!dd->attrs() || dd->attrs()[index].isConfigurable()) {
+ dd->arrayData()[index] = Primitive::emptyValue();
+ if (dd->attrs())
+ dd->attrs()[index] = Attr_Data;
return true;
}
- if (dd->data[index].isEmpty())
+ if (dd->arrayData()[index].isEmpty())
return true;
return false;
}
void SimpleArrayData::setAttribute(Object *o, uint index, PropertyAttributes attrs)
{
- o->arrayData->attrs[index] = attrs;
+ o->arrayData()->attrs()[index] = attrs;
}
PropertyAttributes SimpleArrayData::attribute(const ArrayData *d, uint index)
{
- return d->attrs[index];
+ return d->attrs()[index];
}
void SimpleArrayData::push_front(Object *o, Value *values, uint n)
{
- SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData);
- Q_ASSERT(!dd->attrs);
+ SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData());
+ Q_ASSERT(!dd->attrs());
for (int i = n - 1; i >= 0; --i) {
- if (!dd->offset) {
+ if (!dd->offset()) {
getHeadRoom(o);
- dd = static_cast<SimpleArrayData *>(o->arrayData);
+ dd = static_cast<SimpleArrayData *>(o->arrayData());
}
- --dd->offset;
- --dd->data;
- ++dd->len;
- ++dd->alloc;
- *dd->data = values[i].asReturnedValue();
+ --dd->offset();
+ --dd->arrayData();
+ ++dd->len();
+ ++dd->alloc();
+ *dd->arrayData() = values[i].asReturnedValue();
}
}
ReturnedValue SimpleArrayData::pop_front(Object *o)
{
- SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData);
- Q_ASSERT(!dd->attrs);
- if (!dd->len)
+ SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData());
+ Q_ASSERT(!dd->attrs());
+ if (!dd->len())
return Encode::undefined();
- ReturnedValue v = dd->data[0].isEmpty() ? Encode::undefined() : dd->data[0].asReturnedValue();
- ++dd->offset;
- ++dd->data;
- --dd->len;
- --dd->alloc;
+ ReturnedValue v = dd->arrayData()[0].isEmpty() ? Encode::undefined() : dd->arrayData()[0].asReturnedValue();
+ ++dd->offset();
+ ++dd->arrayData();
+ --dd->len();
+ --dd->alloc();
return v;
}
uint SimpleArrayData::truncate(Object *o, uint newLen)
{
- SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData);
- if (dd->len < newLen)
+ SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData());
+ if (dd->len() < newLen)
return newLen;
- if (dd->attrs) {
- Value *it = dd->data + dd->len;
- const Value *begin = dd->data + newLen;
+ if (dd->attrs()) {
+ Value *it = dd->arrayData() + dd->len();
+ const Value *begin = dd->arrayData() + newLen;
while (--it >= begin) {
- if (!it->isEmpty() && !dd->attrs[it - dd->data].isConfigurable()) {
- newLen = it - dd->data + 1;
+ if (!it->isEmpty() && !dd->attrs()[it - dd->arrayData()].isConfigurable()) {
+ newLen = it - dd->arrayData() + 1;
break;
}
*it = Primitive::emptyValue();
}
}
- dd->len = newLen;
+ dd->len() = newLen;
return newLen;
}
uint SimpleArrayData::length(const ArrayData *d)
{
- return static_cast<const SimpleArrayData *>(d)->len;
+ return static_cast<const SimpleArrayData *>(d)->len();
}
bool SimpleArrayData::putArray(Object *o, uint index, Value *values, uint n)
{
- SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData);
- if (index + n > dd->alloc) {
+ SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData());
+ if (index + n > dd->alloc()) {
reallocate(o, index + n + 1, false);
- dd = static_cast<SimpleArrayData *>(o->arrayData);
+ dd = static_cast<SimpleArrayData *>(o->arrayData());
}
- for (uint i = dd->len; i < index; ++i)
- dd->data[i] = Primitive::emptyValue();
+ for (uint i = dd->len(); i < index; ++i)
+ dd->arrayData()[i] = Primitive::emptyValue();
for (uint i = 0; i < n; ++i)
- dd->data[index + i] = values[i];
- dd->len = qMax(dd->len, index + n);
+ dd->arrayData()[index + i] = values[i];
+ dd->len() = qMax(dd->len(), index + n);
return true;
}
void SparseArrayData::free(ArrayData *d, uint idx)
{
- Q_ASSERT(d && d->type == ArrayData::Sparse);
+ Q_ASSERT(d && d->type() == ArrayData::Sparse);
SparseArrayData *dd = static_cast<SparseArrayData *>(d);
- Value *v = dd->data + idx;
- if (dd->attrs && dd->attrs[idx].isAccessor()) {
+ Value *v = dd->arrayData() + idx;
+ if (dd->attrs() && dd->attrs()[idx].isAccessor()) {
// double slot, free both. Order is important, so we have a double slot for allocation again afterwards.
v[1].tag = Value::Empty_Type;
- v[1].uint_32 = dd->freeList;
+ v[1].uint_32 = dd->freeList();
v[0].tag = Value::Empty_Type;
v[0].uint_32 = idx + 1;
} else {
v->tag = Value::Empty_Type;
- v->uint_32 = dd->freeList;
+ v->uint_32 = dd->freeList();
}
- dd->freeList = idx;
- if (dd->attrs)
- dd->attrs[idx].clear();
+ dd->freeList() = idx;
+ if (dd->attrs())
+ dd->attrs()[idx].clear();
}
void SparseArrayData::destroy(Managed *d)
{
SparseArrayData *dd = static_cast<SparseArrayData *>(d);
- delete dd->sparse;
+ delete dd->sparse();
}
void SparseArrayData::markObjects(Managed *d, ExecutionEngine *e)
{
SparseArrayData *dd = static_cast<SparseArrayData *>(d);
- uint l = dd->alloc;
+ uint l = dd->alloc();
for (uint i = 0; i < l; ++i)
- dd->data[i].mark(e);
+ dd->arrayData()[i].mark(e);
}
ArrayData *SparseArrayData::reallocate(Object *o, uint n, bool enforceAttributes)
{
realloc(o, Sparse, 0, n, enforceAttributes);
- return o->arrayData;
+ return o->arrayData();
}
// double slots are required for accessor properties
uint SparseArrayData::allocate(Object *o, bool doubleSlot)
{
- Q_ASSERT(o->arrayData->type == ArrayData::Sparse);
- SparseArrayData *dd = static_cast<SparseArrayData *>(o->arrayData);
+ Q_ASSERT(o->arrayData()->type() == ArrayData::Sparse);
+ SparseArrayData *dd = static_cast<SparseArrayData *>(o->arrayData());
if (doubleSlot) {
- uint *last = &dd->freeList;
+ uint *last = &dd->freeList();
while (1) {
- if (*last + 1 >= dd->alloc) {
- reallocate(o, o->arrayData->alloc + 2, true);
- dd = static_cast<SparseArrayData *>(o->arrayData);
- last = &dd->freeList;
+ if (*last + 1 >= dd->alloc()) {
+ reallocate(o, o->arrayData()->alloc() + 2, true);
+ dd = static_cast<SparseArrayData *>(o->arrayData());
+ last = &dd->freeList();
}
- if (dd->data[*last].uint_32 == (*last + 1)) {
+ if (dd->arrayData()[*last].uint_32 == (*last + 1)) {
// found two slots in a row
uint idx = *last;
- *last = dd->data[*last + 1].uint_32;
- o->arrayData->attrs[idx] = Attr_Accessor;
+ *last = dd->arrayData()[*last + 1].uint_32;
+ o->arrayData()->attrs()[idx] = Attr_Accessor;
return idx;
}
- last = &dd->data[*last].uint_32;
+ last = &dd->arrayData()[*last].uint_32;
}
} else {
- if (dd->alloc == dd->freeList) {
- reallocate(o, o->arrayData->alloc + 2, false);
- dd = static_cast<SparseArrayData *>(o->arrayData);
+ if (dd->alloc() == dd->freeList()) {
+ reallocate(o, o->arrayData()->alloc() + 2, false);
+ dd = static_cast<SparseArrayData *>(o->arrayData());
}
- uint idx = dd->freeList;
- dd->freeList = dd->data[idx].uint_32;
- if (dd->attrs)
- dd->attrs[idx] = Attr_Data;
+ uint idx = dd->freeList();
+ dd->freeList() = dd->arrayData()[idx].uint_32;
+ if (dd->attrs())
+ dd->attrs()[idx] = Attr_Data;
return idx;
}
}
ReturnedValue SparseArrayData::get(const ArrayData *d, uint index)
{
- SparseArrayNode *n = static_cast<const SparseArrayData *>(d)->sparse->findNode(index);
+ SparseArrayNode *n = static_cast<const SparseArrayData *>(d)->sparse()->findNode(index);
if (!n)
return Primitive::emptyValue().asReturnedValue();
- return d->data[n->value].asReturnedValue();
+ return d->arrayData()[n->value].asReturnedValue();
}
bool SparseArrayData::put(Object *o, uint index, ValueRef value)
@@ -434,93 +446,93 @@ bool SparseArrayData::put(Object *o, uint index, ValueRef value)
if (value->isEmpty())
return true;
- SparseArrayNode *n = static_cast<SparseArrayData *>(o->arrayData)->sparse->insert(index);
- Q_ASSERT(n->value == UINT_MAX || !o->arrayData->attrs || !o->arrayData->attrs[n->value].isAccessor());
+ SparseArrayNode *n = static_cast<SparseArrayData *>(o->arrayData())->sparse()->insert(index);
+ Q_ASSERT(n->value == UINT_MAX || !o->arrayData()->attrs() || !o->arrayData()->attrs()[n->value].isAccessor());
if (n->value == UINT_MAX)
n->value = allocate(o);
- o->arrayData->data[n->value] = value;
- if (o->arrayData->attrs)
- o->arrayData->attrs[n->value] = Attr_Data;
+ o->arrayData()->arrayData()[n->value] = value;
+ if (o->arrayData()->attrs())
+ o->arrayData()->attrs()[n->value] = Attr_Data;
return true;
}
bool SparseArrayData::del(Object *o, uint index)
{
- SparseArrayData *dd = static_cast<SparseArrayData *>(o->arrayData);
- SparseArrayNode *n = dd->sparse->findNode(index);
+ SparseArrayData *dd = static_cast<SparseArrayData *>(o->arrayData());
+ SparseArrayNode *n = dd->sparse()->findNode(index);
if (!n)
return true;
uint pidx = n->value;
- Q_ASSERT(!dd->data[pidx].isEmpty());
+ Q_ASSERT(!dd->arrayData()[pidx].isEmpty());
bool isAccessor = false;
- if (dd->attrs) {
- if (!dd->attrs[pidx].isConfigurable())
+ if (dd->attrs()) {
+ if (!dd->attrs()[pidx].isConfigurable())
return false;
- isAccessor = dd->attrs[pidx].isAccessor();
- dd->attrs[pidx] = Attr_Data;
+ isAccessor = dd->attrs()[pidx].isAccessor();
+ dd->attrs()[pidx] = Attr_Data;
}
if (isAccessor) {
// free up both indices
- dd->data[pidx + 1].tag = Value::Undefined_Type;
- dd->data[pidx + 1].uint_32 = static_cast<SparseArrayData *>(dd)->freeList;
- dd->data[pidx].tag = Value::Undefined_Type;
- dd->data[pidx].uint_32 = pidx + 1;
+ dd->arrayData()[pidx + 1].tag = Value::Undefined_Type;
+ dd->arrayData()[pidx + 1].uint_32 = static_cast<SparseArrayData *>(dd)->freeList();
+ dd->arrayData()[pidx].tag = Value::Undefined_Type;
+ dd->arrayData()[pidx].uint_32 = pidx + 1;
} else {
- dd->data[pidx].tag = Value::Undefined_Type;
- dd->data[pidx].uint_32 = static_cast<SparseArrayData *>(dd)->freeList;
+ dd->arrayData()[pidx].tag = Value::Undefined_Type;
+ dd->arrayData()[pidx].uint_32 = static_cast<SparseArrayData *>(dd)->freeList();
}
- dd->freeList = pidx;
- dd->sparse->erase(n);
+ dd->freeList() = pidx;
+ dd->sparse()->erase(n);
return true;
}
void SparseArrayData::setAttribute(Object *o, uint index, PropertyAttributes attrs)
{
- SparseArrayData *d = static_cast<SparseArrayData *>(o->arrayData);
- SparseArrayNode *n = d->sparse->insert(index);
+ SparseArrayData *d = static_cast<SparseArrayData *>(o->arrayData());
+ SparseArrayNode *n = d->sparse()->insert(index);
if (n->value == UINT_MAX) {
n->value = allocate(o, attrs.isAccessor());
- d = static_cast<SparseArrayData *>(o->arrayData);
+ d = static_cast<SparseArrayData *>(o->arrayData());
}
- else if (attrs.isAccessor() != d->attrs[n->value].isAccessor()) {
+ else if (attrs.isAccessor() != d->attrs()[n->value].isAccessor()) {
// need to convert the slot
free(d, n->value);
n->value = allocate(o, attrs.isAccessor());
}
- o->arrayData->attrs[n->value] = attrs;
+ o->arrayData()->attrs()[n->value] = attrs;
}
PropertyAttributes SparseArrayData::attribute(const ArrayData *d, uint index)
{
- SparseArrayNode *n = static_cast<const SparseArrayData *>(d)->sparse->insert(index);
+ SparseArrayNode *n = static_cast<const SparseArrayData *>(d)->sparse()->insert(index);
if (!n)
return PropertyAttributes();
- return d->attrs[n->value];
+ return d->attrs()[n->value];
}
void SparseArrayData::push_front(Object *o, Value *values, uint n)
{
- Q_ASSERT(!o->arrayData->attrs);
+ Q_ASSERT(!o->arrayData()->attrs());
for (int i = n - 1; i >= 0; --i) {
uint idx = allocate(o);
- o->arrayData->data[idx] = values[i];
- static_cast<SparseArrayData *>(o->arrayData)->sparse->push_front(idx);
+ o->arrayData()->arrayData()[idx] = values[i];
+ static_cast<SparseArrayData *>(o->arrayData())->sparse()->push_front(idx);
}
}
ReturnedValue SparseArrayData::pop_front(Object *o)
{
- Q_ASSERT(!o->arrayData->attrs);
- uint idx = static_cast<SparseArrayData *>(o->arrayData)->sparse->pop_front();
+ Q_ASSERT(!o->arrayData()->attrs());
+ uint idx = static_cast<SparseArrayData *>(o->arrayData())->sparse()->pop_front();
ReturnedValue v;
if (idx != UINT_MAX) {
- v = o->arrayData->data[idx].asReturnedValue();
- free(o->arrayData, idx);
+ v = o->arrayData()->arrayData()[idx].asReturnedValue();
+ free(o->arrayData(), idx);
} else {
v = Encode::undefined();
}
@@ -529,13 +541,13 @@ ReturnedValue SparseArrayData::pop_front(Object *o)
uint SparseArrayData::truncate(Object *o, uint newLen)
{
- SparseArrayData *d = static_cast<SparseArrayData *>(o->arrayData);
- SparseArrayNode *begin = d->sparse->lowerBound(newLen);
- if (begin != d->sparse->end()) {
- SparseArrayNode *it = d->sparse->end()->previousNode();
+ SparseArrayData *d = static_cast<SparseArrayData *>(o->arrayData());
+ SparseArrayNode *begin = d->sparse()->lowerBound(newLen);
+ if (begin != d->sparse()->end()) {
+ SparseArrayNode *it = d->sparse()->end()->previousNode();
while (1) {
- if (d->attrs) {
- if (!d->attrs[it->value].isConfigurable()) {
+ if (d->attrs()) {
+ if (!d->attrs()[it->value].isConfigurable()) {
newLen = it->key() + 1;
break;
}
@@ -543,7 +555,7 @@ uint SparseArrayData::truncate(Object *o, uint newLen)
free(d, it->value);
bool brk = (it == begin);
SparseArrayNode *prev = it->previousNode();
- static_cast<SparseArrayData *>(d)->sparse->erase(it);
+ static_cast<SparseArrayData *>(d)->sparse()->erase(it);
if (brk)
break;
it = prev;
@@ -555,9 +567,9 @@ uint SparseArrayData::truncate(Object *o, uint newLen)
uint SparseArrayData::length(const ArrayData *d)
{
const SparseArrayData *dd = static_cast<const SparseArrayData *>(d);
- if (!dd->sparse)
+ if (!dd->sparse())
return 0;
- SparseArrayNode *n = dd->sparse->end();
+ SparseArrayNode *n = dd->sparse()->end();
n = n->previousNode();
return n ? n->key() + 1 : 0;
}
@@ -572,12 +584,12 @@ bool SparseArrayData::putArray(Object *o, uint index, Value *values, uint n)
uint ArrayData::append(Object *obj, const ArrayObject *otherObj, uint n)
{
- Q_ASSERT(!obj->arrayData->hasAttributes());
+ Q_ASSERT(!obj->arrayData()->hasAttributes());
if (!n)
return obj->getLength();
- const ArrayData *other = otherObj->arrayData;
+ const ArrayData *other = otherObj->arrayData();
if (other->isSparse())
obj->initSparseArray();
@@ -587,21 +599,21 @@ uint ArrayData::append(Object *obj, const ArrayObject *otherObj, uint n)
uint oldSize = obj->getLength();
if (other->isSparse()) {
- if (otherObj->hasAccessorProperty && other->hasAttributes()) {
+ if (otherObj->hasAccessorProperty() && other->hasAttributes()) {
Scope scope(obj->engine());
ScopedValue v(scope);
- for (const SparseArrayNode *it = static_cast<const SparseArrayData *>(other)->sparse->begin();
- it != static_cast<const SparseArrayData *>(other)->sparse->end(); it = it->nextNode()) {
- v = otherObj->getValue(reinterpret_cast<Property *>(other->data + it->value), other->attrs[it->value]);
+ for (const SparseArrayNode *it = static_cast<const SparseArrayData *>(other)->sparse()->begin();
+ it != static_cast<const SparseArrayData *>(other)->sparse()->end(); it = it->nextNode()) {
+ v = otherObj->getValue(reinterpret_cast<Property *>(other->arrayData() + it->value), other->attrs()[it->value]);
obj->arraySet(oldSize + it->key(), v);
}
} else {
- for (const SparseArrayNode *it = static_cast<const SparseArrayData *>(other)->sparse->begin();
- it != static_cast<const SparseArrayData *>(other)->sparse->end(); it = it->nextNode())
- obj->arraySet(oldSize + it->key(), ValueRef(other->data[it->value]));
+ for (const SparseArrayNode *it = static_cast<const SparseArrayData *>(other)->sparse()->begin();
+ it != static_cast<const SparseArrayData *>(other)->sparse()->end(); it = it->nextNode())
+ obj->arraySet(oldSize + it->key(), ValueRef(other->arrayData()[it->value]));
}
} else {
- obj->arrayPut(oldSize, other->data, n);
+ obj->arrayPut(oldSize, other->arrayData(), n);
}
return oldSize + n;
@@ -609,42 +621,42 @@ uint ArrayData::append(Object *obj, const ArrayObject *otherObj, uint n)
Property *ArrayData::insert(Object *o, uint index, bool isAccessor)
{
- if (!isAccessor && o->arrayData->type != ArrayData::Sparse) {
- SimpleArrayData *d = static_cast<SimpleArrayData *>(o->arrayData);
- if (index < 0x1000 || index < d->len + (d->len >> 2)) {
- if (index >= o->arrayData->alloc) {
+ if (!isAccessor && o->arrayData()->type() != ArrayData::Sparse) {
+ SimpleArrayData *d = static_cast<SimpleArrayData *>(o->arrayData());
+ if (index < 0x1000 || index < d->len() + (d->len() >> 2)) {
+ if (index >= o->arrayData()->alloc()) {
o->arrayReserve(index + 1);
- d = static_cast<SimpleArrayData *>(o->arrayData);
+ d = static_cast<SimpleArrayData *>(o->arrayData());
}
- if (index >= d->len) {
+ if (index >= d->len()) {
// mark possible hole in the array
- for (uint i = d->len; i < index; ++i)
- d->data[i] = Primitive::emptyValue();
- d->len = index + 1;
+ for (uint i = d->len(); i < index; ++i)
+ d->arrayData()[i] = Primitive::emptyValue();
+ d->len() = index + 1;
}
- return reinterpret_cast<Property *>(o->arrayData->data + index);
+ return reinterpret_cast<Property *>(o->arrayData()->arrayData() + index);
}
}
o->initSparseArray();
- SparseArrayNode *n = static_cast<SparseArrayData *>(o->arrayData)->sparse->insert(index);
+ SparseArrayNode *n = static_cast<SparseArrayData *>(o->arrayData())->sparse()->insert(index);
if (n->value == UINT_MAX)
n->value = SparseArrayData::allocate(o, isAccessor);
- return reinterpret_cast<Property *>(o->arrayData->data + n->value);
+ return reinterpret_cast<Property *>(o->arrayData()->arrayData() + n->value);
}
class ArrayElementLessThan
{
public:
- inline ArrayElementLessThan(ExecutionContext *context, ObjectRef thisObject, const ValueRef comparefn)
+ inline ArrayElementLessThan(ExecutionContext *context, Object *thisObject, const ValueRef comparefn)
: m_context(context), thisObject(thisObject), m_comparefn(comparefn) {}
bool operator()(const Value &v1, const Value &v2) const;
private:
ExecutionContext *m_context;
- ObjectRef thisObject;
+ Object *thisObject;
const ValueRef m_comparefn;
};
@@ -674,12 +686,12 @@ bool ArrayElementLessThan::operator()(const Value &v1, const Value &v2) const
return p1s->toQString() < p2s->toQString();
}
-void ArrayData::sort(ExecutionContext *context, ObjectRef thisObject, const ValueRef comparefn, uint len)
+void ArrayData::sort(ExecutionContext *context, Object *thisObject, const ValueRef comparefn, uint len)
{
if (!len)
return;
- if (!thisObject->arrayData->length())
+ if (!thisObject->arrayData()->length())
return;
if (!(comparefn->isUndefined() || comparefn->asObject())) {
@@ -690,50 +702,50 @@ void ArrayData::sort(ExecutionContext *context, ObjectRef thisObject, const Valu
// The spec says the sorting goes through a series of get,put and delete operations.
// this implies that the attributes don't get sorted around.
- if (thisObject->arrayData->type == ArrayData::Sparse) {
+ if (thisObject->arrayData()->type() == ArrayData::Sparse) {
// since we sort anyway, we can simply iterate over the entries in the sparse
// array and append them one by one to a regular one.
- SparseArrayData *sparse = static_cast<SparseArrayData *>(thisObject->arrayData);
+ SparseArrayData *sparse = static_cast<SparseArrayData *>(thisObject->arrayData());
- if (!sparse->sparse->nEntries())
+ if (!sparse->sparse()->nEntries())
return;
- thisObject->arrayData = 0;
- ArrayData::realloc(thisObject, ArrayData::Simple, 0, sparse->sparse->nEntries(), sparse->attrs ? true : false);
- SimpleArrayData *d = static_cast<SimpleArrayData *>(thisObject->arrayData);
+ thisObject->setArrayData(0);
+ ArrayData::realloc(thisObject, ArrayData::Simple, 0, sparse->sparse()->nEntries(), sparse->attrs() ? true : false);
+ SimpleArrayData *d = static_cast<SimpleArrayData *>(thisObject->arrayData());
- SparseArrayNode *n = sparse->sparse->begin();
+ SparseArrayNode *n = sparse->sparse()->begin();
uint i = 0;
- if (sparse->attrs) {
- while (n != sparse->sparse->end()) {
+ if (sparse->attrs()) {
+ while (n != sparse->sparse()->end()) {
if (n->value >= len)
break;
- PropertyAttributes a = sparse->attrs ? sparse->attrs[n->value] : Attr_Data;
- d->data[i] = thisObject->getValue(reinterpret_cast<Property *>(sparse->data + n->value), a);
- d->attrs[i] = a.isAccessor() ? Attr_Data : a;
+ PropertyAttributes a = sparse->attrs() ? sparse->attrs()[n->value] : Attr_Data;
+ d->arrayData()[i] = thisObject->getValue(reinterpret_cast<Property *>(sparse->arrayData() + n->value), a);
+ d->attrs()[i] = a.isAccessor() ? Attr_Data : a;
n = n->nextNode();
++i;
}
} else {
- while (n != sparse->sparse->end()) {
+ while (n != sparse->sparse()->end()) {
if (n->value >= len)
break;
- d->data[i] = sparse->data[n->value];
+ d->arrayData()[i] = sparse->arrayData()[n->value];
n = n->nextNode();
++i;
}
}
- d->len = i;
+ d->len() = i;
if (len > i)
len = i;
- if (n != sparse->sparse->end()) {
+ if (n != sparse->sparse()->end()) {
// have some entries outside the sort range that we need to ignore when sorting
thisObject->initSparseArray();
- while (n != sparse->sparse->end()) {
- PropertyAttributes a = sparse->attrs ? sparse->attrs[n->value] : Attr_Data;
- thisObject->arraySet(n->value, *reinterpret_cast<Property *>(sparse->data + n->value), a);
+ while (n != sparse->sparse()->end()) {
+ PropertyAttributes a = sparse->attrs() ? sparse->attrs()[n->value] : Attr_Data;
+ thisObject->arraySet(n->value, *reinterpret_cast<Property *>(sparse->arrayData() + n->value), a);
n = n->nextNode();
}
@@ -741,19 +753,19 @@ void ArrayData::sort(ExecutionContext *context, ObjectRef thisObject, const Valu
}
// ### explicitly delete sparse
} else {
- SimpleArrayData *d = static_cast<SimpleArrayData *>(thisObject->arrayData);
- if (len > d->len)
- len = d->len;
+ SimpleArrayData *d = static_cast<SimpleArrayData *>(thisObject->arrayData());
+ if (len > d->len())
+ len = d->len();
// sort empty values to the end
for (uint i = 0; i < len; i++) {
- if (thisObject->arrayData->data[i].isEmpty()) {
+ if (thisObject->arrayData()->arrayData()[i].isEmpty()) {
while (--len > i)
- if (!thisObject->arrayData->data[len].isEmpty())
+ if (!thisObject->arrayData()->arrayData()[len].isEmpty())
break;
- Q_ASSERT(!thisObject->arrayData->attrs || !thisObject->arrayData->attrs[len].isAccessor());
- thisObject->arrayData->data[i] = thisObject->arrayData->data[len];
- thisObject->arrayData->data[len] = Primitive::emptyValue();
+ Q_ASSERT(!thisObject->arrayData()->attrs() || !thisObject->arrayData()->attrs()[len].isAccessor());
+ thisObject->arrayData()->arrayData()[i] = thisObject->arrayData()->arrayData()[len];
+ thisObject->arrayData()->arrayData()[len] = Primitive::emptyValue();
}
}
@@ -764,7 +776,7 @@ void ArrayData::sort(ExecutionContext *context, ObjectRef thisObject, const Valu
ArrayElementLessThan lessThan(context, thisObject, comparefn);
- Value *begin = thisObject->arrayData->data;
+ Value *begin = thisObject->arrayData()->arrayData();
std::sort(begin, begin + len, lessThan);
#ifdef CHECK_SPARSE_ARRAYS
diff --git a/src/qml/jsruntime/qv4arraydata_p.h b/src/qml/jsruntime/qv4arraydata_p.h
index 50b7b8a947..aab9157ced 100644
--- a/src/qml/jsruntime/qv4arraydata_p.h
+++ b/src/qml/jsruntime/qv4arraydata_p.h
@@ -57,6 +57,10 @@ namespace QV4 {
static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl.managedVTable; } \
template <typename T> \
QV4::Returned<T> *asReturned() { return QV4::Returned<T>::create(this); } \
+ V4_MANAGED_SIZE_TEST \
+ const Data *d() const { return &static_cast<const Data &>(Managed::data); } \
+ Data *d() { return &static_cast<Data &>(Managed::data); }
+
struct ArrayData;
@@ -80,11 +84,6 @@ struct ArrayVTable
struct Q_QML_EXPORT ArrayData : public Managed
{
- ArrayData(InternalClass *ic)
- : Managed(ic)
- {
- }
-
enum Type {
Simple = 0,
Complex = 1,
@@ -92,13 +91,30 @@ struct Q_QML_EXPORT ArrayData : public Managed
Custom = 3
};
- uint alloc;
- Type type;
- PropertyAttributes *attrs;
- Value *data;
-
- const ArrayVTable *vtable() const { return reinterpret_cast<const ArrayVTable *>(internalClass->vtable); }
- bool isSparse() const { return this && type == Sparse; }
+ struct Data : public Managed::Data {
+ Data(InternalClass *ic)
+ : Managed::Data(ic)
+ {}
+ uint alloc;
+ Type type;
+ PropertyAttributes *attrs;
+ Value *arrayData;
+ };
+ V4_MANAGED(Managed)
+
+ uint alloc() const { return d()->alloc; }
+ uint &alloc() { return d()->alloc; }
+ void setAlloc(uint a) { d()->alloc = a; }
+ Type type() const { return d()->type; }
+ void setType(Type t) { d()->type = t; }
+ PropertyAttributes *attrs() const { return d()->attrs; }
+ void setAttrs(PropertyAttributes *a) { d()->attrs = a; }
+ Value *arrayData() const { return d()->arrayData; }
+ Value *&arrayData() { return d()->arrayData; }
+ void setArrayData(Value *v) { d()->arrayData = v; }
+
+ const ArrayVTable *vtable() const { return reinterpret_cast<const ArrayVTable *>(internalClass()->vtable); }
+ bool isSparse() const { return this && type() == Sparse; }
uint length() const {
if (!this)
@@ -107,11 +123,11 @@ struct Q_QML_EXPORT ArrayData : public Managed
}
bool hasAttributes() const {
- return this && attrs;
+ return this && attrs();
}
PropertyAttributes attributes(int i) const {
Q_ASSERT(this);
- return attrs ? vtable()->attribute(this, i) : Attr_Data;
+ return attrs() ? vtable()->attribute(this, i) : Attr_Data;
}
bool isEmpty(uint i) const {
@@ -130,26 +146,31 @@ struct Q_QML_EXPORT ArrayData : public Managed
static void ensureAttributes(Object *o);
static void realloc(Object *o, Type newType, uint offset, uint alloc, bool enforceAttributes);
- static void sort(ExecutionContext *context, ObjectRef thisObject, const ValueRef comparefn, uint dataLen);
+ static void sort(ExecutionContext *context, Object *thisObject, const ValueRef comparefn, uint dataLen);
static uint append(Object *obj, const ArrayObject *otherObj, uint n);
static Property *insert(Object *o, uint index, bool isAccessor = false);
};
struct Q_QML_EXPORT SimpleArrayData : public ArrayData
{
- V4_ARRAYDATA
- SimpleArrayData(ExecutionEngine *engine)
- : ArrayData(engine->simpleArrayDataClass)
- {}
+ struct Data : public ArrayData::Data {
+ Data(ExecutionEngine *engine)
+ : ArrayData::Data(engine->simpleArrayDataClass)
+ {}
+ uint len;
+ uint offset;
+ };
+ V4_ARRAYDATA
- uint len;
- uint offset;
+ uint &len() { return d()->len; }
+ uint len() const { return d()->len; }
+ uint &offset() { return d()->offset; }
+ uint offset() const { return d()->offset; }
static void getHeadRoom(Object *o);
static ArrayData *reallocate(Object *o, uint n, bool enforceAttributes);
- static void destroy(Managed *d);
static void markObjects(Managed *d, ExecutionEngine *e);
static ReturnedValue get(const ArrayData *d, uint index);
@@ -166,14 +187,20 @@ struct Q_QML_EXPORT SimpleArrayData : public ArrayData
struct Q_QML_EXPORT SparseArrayData : public ArrayData
{
- V4_ARRAYDATA
+ struct Data : public ArrayData::Data {
+ Data(ExecutionEngine *engine)
+ : ArrayData::Data(engine->emptyClass)
+ { setVTable(staticVTable()); }
- SparseArrayData(ExecutionEngine *engine)
- : ArrayData(engine->emptyClass)
- { setVTable(staticVTable()); }
+ uint freeList;
+ SparseArray *sparse;
+ };
+ V4_ARRAYDATA
- uint freeList;
- SparseArray *sparse;
+ uint &freeList() { return d()->freeList; }
+ uint freeList() const { return d()->freeList; }
+ SparseArray *sparse() const { return d()->sparse; }
+ void setSparse(SparseArray *s) { d()->sparse = s; }
static uint allocate(Object *o, bool doubleSlot = false);
static void free(ArrayData *d, uint idx);
@@ -199,16 +226,16 @@ inline Property *ArrayData::getProperty(uint index) const
{
if (!this)
return 0;
- if (type != Sparse) {
+ if (type() != Sparse) {
const SimpleArrayData *that = static_cast<const SimpleArrayData *>(this);
- if (index >= that->len || data[index].isEmpty())
+ if (index >= that->len() || arrayData()[index].isEmpty())
return 0;
- return reinterpret_cast<Property *>(data + index);
+ return reinterpret_cast<Property *>(arrayData() + index);
} else {
- SparseArrayNode *n = static_cast<const SparseArrayData *>(this)->sparse->findNode(index);
+ SparseArrayNode *n = static_cast<const SparseArrayData *>(this)->sparse()->findNode(index);
if (!n)
return 0;
- return reinterpret_cast<Property *>(data + n->value);
+ return reinterpret_cast<Property *>(arrayData() + n->value);
}
}
diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp
index fbd757a829..abe8a44065 100644
--- a/src/qml/jsruntime/qv4arrayobject.cpp
+++ b/src/qml/jsruntime/qv4arrayobject.cpp
@@ -48,8 +48,8 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(ArrayCtor);
-ArrayCtor::ArrayCtor(ExecutionContext *scope)
- : FunctionObject(scope, QStringLiteral("Array"))
+ArrayCtor::Data::Data(ExecutionContext *scope)
+ : FunctionObject::Data(scope, QStringLiteral("Array"))
{
setVTable(staticVTable());
}
@@ -84,12 +84,7 @@ ReturnedValue ArrayCtor::call(Managed *that, CallData *callData)
return construct(that, callData);
}
-ArrayPrototype::ArrayPrototype(InternalClass *ic)
- : ArrayObject(ic)
-{
-}
-
-void ArrayPrototype::init(ExecutionEngine *engine, ObjectRef ctor)
+void ArrayPrototype::init(ExecutionEngine *engine, Object *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
@@ -122,21 +117,21 @@ void ArrayPrototype::init(ExecutionEngine *engine, ObjectRef ctor)
ReturnedValue ArrayPrototype::method_isArray(CallContext *ctx)
{
- bool isArray = ctx->callData->argc && ctx->callData->args[0].asArrayObject();
+ bool isArray = ctx->d()->callData->argc && ctx->d()->callData->args[0].asArrayObject();
return Encode(isArray);
}
ReturnedValue ArrayPrototype::method_toString(CallContext *ctx)
{
Scope scope(ctx);
- ScopedObject o(scope, ctx->callData->thisObject, ScopedObject::Convert);
- if (ctx->engine->hasException)
+ ScopedObject o(scope, ctx->d()->callData->thisObject, ScopedObject::Convert);
+ if (ctx->d()->engine->hasException)
return Encode::undefined();
- ScopedString s(scope, ctx->engine->newString(QStringLiteral("join")));
- ScopedFunctionObject f(scope, o->get(s));
+ ScopedString s(scope, ctx->d()->engine->newString(QStringLiteral("join")));
+ ScopedFunctionObject f(scope, o->get(s.getPointer()));
if (!!f) {
ScopedCallData d(scope, 0);
- d->thisObject = ctx->callData->thisObject;
+ d->thisObject = ctx->d()->callData->thisObject;
return f->call(d);
}
return ObjectPrototype::method_toString(ctx);
@@ -150,9 +145,9 @@ ReturnedValue ArrayPrototype::method_toLocaleString(CallContext *ctx)
ReturnedValue ArrayPrototype::method_concat(CallContext *ctx)
{
Scope scope(ctx);
- ScopedObject result(scope, ctx->engine->newArrayObject());
+ ScopedObject result(scope, ctx->d()->engine->newArrayObject());
- ScopedObject thisObject(scope, ctx->callData->thisObject.toObject(ctx));
+ ScopedObject thisObject(scope, ctx->d()->callData->thisObject.toObject(ctx));
if (!thisObject)
return Encode::undefined();
ScopedArrayObject instance(scope, thisObject);
@@ -165,9 +160,9 @@ ReturnedValue ArrayPrototype::method_concat(CallContext *ctx)
ScopedArrayObject elt(scope);
ScopedObject eltAsObj(scope);
ScopedValue entry(scope);
- for (int i = 0; i < ctx->callData->argc; ++i) {
- eltAsObj = ctx->callData->args[i];
- elt = ctx->callData->args[i];
+ for (int i = 0; i < ctx->d()->callData->argc; ++i) {
+ eltAsObj = ctx->d()->callData->args[i];
+ elt = ctx->d()->callData->args[i];
if (elt) {
uint n = elt->getLength();
uint newLen = ArrayData::append(result.getPointer(), elt.getPointer(), n);
@@ -179,7 +174,7 @@ ReturnedValue ArrayPrototype::method_concat(CallContext *ctx)
result->putIndexed(startIndex + i, entry);
}
} else {
- result->arraySet(result->getLength(), ValueRef(ctx->callData->args[i]));
+ result->arraySet(result->getLength(), ValueRef(ctx->d()->callData->args[i]));
}
}
@@ -197,12 +192,12 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx)
else
r4 = arg->toQString();
- ScopedObject self(scope, ctx->callData->thisObject);
- ScopedValue length(scope, self->get(ctx->engine->id_length));
+ ScopedObject self(scope, ctx->d()->callData->thisObject);
+ ScopedValue length(scope, self->get(ctx->d()->engine->id_length));
const quint32 r2 = length->isUndefined() ? 0 : length->toUInt32();
if (!r2)
- return ctx->engine->newString(QString())->asReturnedValue();
+ return ctx->d()->engine->newString(QString())->asReturnedValue();
QString R;
@@ -223,8 +218,8 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx)
//
// crazy!
//
- ScopedString name(scope, ctx->engine->newString(QStringLiteral("0")));
- ScopedValue r6(scope, self->get(name));
+ ScopedString name(scope, ctx->d()->engine->newString(QStringLiteral("0")));
+ ScopedValue r6(scope, self->get(name.getPointer()));
if (!r6->isNullOrUndefined())
R = r6->toString(ctx)->toQString();
@@ -233,7 +228,7 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx)
R += r4;
name = Primitive::fromDouble(k).toString(ctx);
- r12 = self->get(name);
+ r12 = self->get(name.getPointer());
if (scope.hasException())
return Encode::undefined();
@@ -242,20 +237,20 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx)
}
}
- return ctx->engine->newString(R)->asReturnedValue();
+ return ctx->d()->engine->newString(R)->asReturnedValue();
}
ReturnedValue ArrayPrototype::method_pop(CallContext *ctx)
{
Scope scope(ctx);
- ScopedObject instance(scope, ctx->callData->thisObject.toObject(ctx));
+ ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(ctx));
if (!instance)
return Encode::undefined();
uint len = instance->getLength();
if (!len) {
if (!instance->isArrayObject())
- instance->put(ctx->engine->id_length, ScopedValue(scope, Primitive::fromInt32(0)));
+ instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromInt32(0)));
return Encode::undefined();
}
@@ -269,14 +264,14 @@ ReturnedValue ArrayPrototype::method_pop(CallContext *ctx)
if (instance->isArrayObject())
instance->setArrayLength(len - 1);
else
- instance->put(ctx->engine->id_length, ScopedValue(scope, Primitive::fromDouble(len - 1)));
+ instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromDouble(len - 1)));
return result.asReturnedValue();
}
ReturnedValue ArrayPrototype::method_push(CallContext *ctx)
{
Scope scope(ctx);
- ScopedObject instance(scope, ctx->callData->thisObject.toObject(ctx));
+ ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(ctx));
if (!instance)
return Encode::undefined();
@@ -284,38 +279,38 @@ ReturnedValue ArrayPrototype::method_push(CallContext *ctx)
uint len = instance->getLength();
- if (len + ctx->callData->argc < len) {
+ if (len + ctx->d()->callData->argc < len) {
// ughh...
double l = len;
ScopedString s(scope);
- for (int i = 0; i < ctx->callData->argc; ++i) {
+ for (int i = 0; i < ctx->d()->callData->argc; ++i) {
s = Primitive::fromDouble(l + i).toString(ctx);
- instance->put(s, ctx->callData->args[i]);
+ instance->put(s.getPointer(), ctx->d()->callData->args[i]);
}
- double newLen = l + ctx->callData->argc;
+ double newLen = l + ctx->d()->callData->argc;
if (!instance->isArrayObject())
- instance->put(ctx->engine->id_length, ScopedValue(scope, Primitive::fromDouble(newLen)));
+ instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromDouble(newLen)));
else {
- ScopedString str(scope, ctx->engine->newString(QStringLiteral("Array.prototype.push: Overflow")));
+ ScopedString str(scope, ctx->d()->engine->newString(QStringLiteral("Array.prototype.push: Overflow")));
return ctx->throwRangeError(str);
}
return Encode(newLen);
}
- if (!ctx->callData->argc) {
+ if (!ctx->d()->callData->argc) {
;
- } else if (!instance->protoHasArray() && instance->arrayData->length() <= len && instance->arrayType() == ArrayData::Simple) {
- instance->arrayData->vtable()->putArray(instance.getPointer(), len, ctx->callData->args, ctx->callData->argc);
- len = instance->arrayData->length();
+ } else if (!instance->protoHasArray() && instance->arrayData()->length() <= len && instance->arrayType() == ArrayData::Simple) {
+ instance->arrayData()->vtable()->putArray(instance.getPointer(), len, ctx->d()->callData->args, ctx->d()->callData->argc);
+ len = instance->arrayData()->length();
} else {
- for (int i = 0; i < ctx->callData->argc; ++i)
- instance->putIndexed(len + i, ctx->callData->args[i]);
- len += ctx->callData->argc;
+ for (int i = 0; i < ctx->d()->callData->argc; ++i)
+ instance->putIndexed(len + i, ctx->d()->callData->args[i]);
+ len += ctx->d()->callData->argc;
}
if (instance->isArrayObject())
instance->setArrayLengthUnchecked(len);
else
- instance->put(ctx->engine->id_length, ScopedValue(scope, Primitive::fromDouble(len)));
+ instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromDouble(len)));
return Encode(len);
}
@@ -323,7 +318,7 @@ ReturnedValue ArrayPrototype::method_push(CallContext *ctx)
ReturnedValue ArrayPrototype::method_reverse(CallContext *ctx)
{
Scope scope(ctx);
- ScopedObject instance(scope, ctx->callData->thisObject.toObject(ctx));
+ ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(ctx));
if (!instance)
return Encode::undefined();
uint length = instance->getLength();
@@ -355,7 +350,7 @@ ReturnedValue ArrayPrototype::method_reverse(CallContext *ctx)
ReturnedValue ArrayPrototype::method_shift(CallContext *ctx)
{
Scope scope(ctx);
- ScopedObject instance(scope, ctx->callData->thisObject.toObject(ctx));
+ ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(ctx));
if (!instance)
return Encode::undefined();
@@ -365,14 +360,14 @@ ReturnedValue ArrayPrototype::method_shift(CallContext *ctx)
if (!len) {
if (!instance->isArrayObject())
- instance->put(ctx->engine->id_length, ScopedValue(scope, Primitive::fromInt32(0)));
+ instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromInt32(0)));
return Encode::undefined();
}
ScopedValue result(scope);
- if (!instance->protoHasArray() && !instance->arrayData->hasAttributes() && instance->arrayData->length() <= len && instance->arrayData->type != ArrayData::Custom) {
- result = instance->arrayData->vtable()->pop_front(instance.getPointer());
+ if (!instance->protoHasArray() && !instance->arrayData()->hasAttributes() && instance->arrayData()->length() <= len && instance->arrayData()->type() != ArrayData::Custom) {
+ result = instance->arrayData()->vtable()->pop_front(instance.getPointer());
} else {
result = instance->getIndexed(0);
if (scope.hasException())
@@ -399,18 +394,18 @@ ReturnedValue ArrayPrototype::method_shift(CallContext *ctx)
if (instance->isArrayObject())
instance->setArrayLengthUnchecked(len - 1);
else
- instance->put(ctx->engine->id_length, ScopedValue(scope, Primitive::fromDouble(len - 1)));
+ instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromDouble(len - 1)));
return result.asReturnedValue();
}
ReturnedValue ArrayPrototype::method_slice(CallContext *ctx)
{
Scope scope(ctx);
- ScopedObject o(scope, ctx->callData->thisObject.toObject(ctx));
+ ScopedObject o(scope, ctx->d()->callData->thisObject.toObject(ctx));
if (!o)
return Encode::undefined();
- Scoped<ArrayObject> result(scope, ctx->engine->newArrayObject());
+ Scoped<ArrayObject> result(scope, ctx->d()->engine->newArrayObject());
uint len = o->getLength();
double s = ScopedValue(scope, ctx->argument(0))->toInteger();
uint start;
@@ -421,8 +416,8 @@ ReturnedValue ArrayPrototype::method_slice(CallContext *ctx)
else
start = (uint) s;
uint end = len;
- if (ctx->callData->argc > 1 && !ctx->callData->args[1].isUndefined()) {
- double e = ctx->callData->args[1].toInteger();
+ if (ctx->d()->callData->argc > 1 && !ctx->d()->callData->args[1].isUndefined()) {
+ double e = ctx->d()->callData->args[1].toInteger();
if (e < 0)
end = (uint)qMax(len + e, 0.);
else if (e > len)
@@ -448,7 +443,7 @@ ReturnedValue ArrayPrototype::method_slice(CallContext *ctx)
ReturnedValue ArrayPrototype::method_sort(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Object> instance(scope, ctx->callData->thisObject.toObject(ctx));
+ Scoped<Object> instance(scope, ctx->d()->callData->thisObject.toObject(ctx));
if (!instance)
return Encode::undefined();
@@ -456,18 +451,18 @@ ReturnedValue ArrayPrototype::method_sort(CallContext *ctx)
ScopedValue comparefn(scope, ctx->argument(0));
ArrayData::sort(ctx, instance, comparefn, len);
- return ctx->callData->thisObject.asReturnedValue();
+ return ctx->d()->callData->thisObject.asReturnedValue();
}
ReturnedValue ArrayPrototype::method_splice(CallContext *ctx)
{
Scope scope(ctx);
- ScopedObject instance(scope, ctx->callData->thisObject.toObject(ctx));
+ ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(ctx));
if (!instance)
return Encode::undefined();
uint len = instance->getLength();
- Scoped<ArrayObject> newArray(scope, ctx->engine->newArrayObject());
+ Scoped<ArrayObject> newArray(scope, ctx->d()->engine->newArrayObject());
double rs = ScopedValue(scope, ctx->argument(0))->toInteger();
uint start;
@@ -490,7 +485,7 @@ ReturnedValue ArrayPrototype::method_splice(CallContext *ctx)
}
newArray->setArrayLengthUnchecked(deleteCount);
- uint itemCount = ctx->callData->argc < 2 ? 0 : ctx->callData->argc - 2;
+ uint itemCount = ctx->d()->callData->argc < 2 ? 0 : ctx->d()->callData->argc - 2;
if (itemCount < deleteCount) {
for (uint k = start; k < len - deleteCount; ++k) {
@@ -528,13 +523,13 @@ ReturnedValue ArrayPrototype::method_splice(CallContext *ctx)
}
for (uint i = 0; i < itemCount; ++i) {
- instance->putIndexed(start + i, ctx->callData->args[i + 2]);
+ instance->putIndexed(start + i, ctx->d()->callData->args[i + 2]);
if (scope.hasException())
return Encode::undefined();
}
- ctx->strictMode = true;
- instance->put(ctx->engine->id_length, ScopedValue(scope, Primitive::fromDouble(len - deleteCount + itemCount)));
+ ctx->d()->strictMode = true;
+ instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromDouble(len - deleteCount + itemCount)));
return newArray.asReturnedValue();
}
@@ -542,7 +537,7 @@ ReturnedValue ArrayPrototype::method_splice(CallContext *ctx)
ReturnedValue ArrayPrototype::method_unshift(CallContext *ctx)
{
Scope scope(ctx);
- ScopedObject instance(scope, ctx->callData->thisObject.toObject(ctx));
+ ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(ctx));
if (!instance)
return Encode::undefined();
@@ -550,27 +545,27 @@ ReturnedValue ArrayPrototype::method_unshift(CallContext *ctx)
uint len = instance->getLength();
- if (!instance->protoHasArray() && !instance->arrayData->hasAttributes() && instance->arrayData->length() <= len && instance->arrayData->type != ArrayData::Custom) {
- instance->arrayData->vtable()->push_front(instance.getPointer(), ctx->callData->args, ctx->callData->argc);
+ if (!instance->protoHasArray() && !instance->arrayData()->hasAttributes() && instance->arrayData()->length() <= len && instance->arrayData()->type() != ArrayData::Custom) {
+ instance->arrayData()->vtable()->push_front(instance.getPointer(), ctx->d()->callData->args, ctx->d()->callData->argc);
} else {
ScopedValue v(scope);
for (uint k = len; k > 0; --k) {
bool exists;
v = instance->getIndexed(k - 1, &exists);
if (exists)
- instance->putIndexed(k + ctx->callData->argc - 1, v);
+ instance->putIndexed(k + ctx->d()->callData->argc - 1, v);
else
- instance->deleteIndexedProperty(k + ctx->callData->argc - 1);
+ instance->deleteIndexedProperty(k + ctx->d()->callData->argc - 1);
}
- for (int i = 0; i < ctx->callData->argc; ++i)
- instance->putIndexed(i, ctx->callData->args[i]);
+ for (int i = 0; i < ctx->d()->callData->argc; ++i)
+ instance->putIndexed(i, ctx->d()->callData->args[i]);
}
- uint newLen = len + ctx->callData->argc;
+ uint newLen = len + ctx->d()->callData->argc;
if (instance->isArrayObject())
instance->setArrayLengthUnchecked(newLen);
else
- instance->put(ctx->engine->id_length, ScopedValue(scope, Primitive::fromDouble(newLen)));
+ instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromDouble(newLen)));
return Encode(newLen);
}
@@ -579,18 +574,18 @@ ReturnedValue ArrayPrototype::method_indexOf(CallContext *ctx)
{
Scope scope(ctx);
- ScopedObject instance(scope, ctx->callData->thisObject.toObject(ctx));
+ ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(ctx));
if (!instance)
return Encode::undefined();
uint len = instance->getLength();
if (!len)
return Encode(-1);
- ScopedValue searchValue(scope, ctx->callData->argument(0));
+ ScopedValue searchValue(scope, ctx->d()->callData->argument(0));
uint fromIndex = 0;
- if (ctx->callData->argc >= 2) {
- double f = ctx->callData->args[1].toInteger();
+ if (ctx->d()->callData->argc >= 2) {
+ double f = ctx->d()->callData->args[1].toInteger();
if (scope.hasException())
return Encode::undefined();
if (f >= len)
@@ -613,7 +608,7 @@ ReturnedValue ArrayPrototype::method_indexOf(CallContext *ctx)
ScopedValue value(scope);
- if (instance->hasAccessorProperty || (instance->arrayType() >= ArrayData::Sparse) || instance->protoHasArray()) {
+ if (instance->hasAccessorProperty() || (instance->arrayType() >= ArrayData::Sparse) || instance->protoHasArray()) {
// lets be safe and slow
for (uint i = fromIndex; i < len; ++i) {
bool exists;
@@ -623,13 +618,13 @@ ReturnedValue ArrayPrototype::method_indexOf(CallContext *ctx)
if (exists && RuntimeHelpers::strictEqual(value, searchValue))
return Encode(i);
}
- } else if (!instance->arrayData) {
+ } else if (!instance->arrayData()) {
return Encode(-1);
} else {
Q_ASSERT(instance->arrayType() == ArrayData::Simple || instance->arrayType() == ArrayData::Complex);
- if (len > instance->arrayData->length())
- len = instance->arrayData->length();
- Value *val = instance->arrayData->data;
+ if (len > instance->arrayData()->length())
+ len = instance->arrayData()->length();
+ Value *val = instance->arrayData()->arrayData();
Value *end = val + len;
val += fromIndex;
while (val < end) {
@@ -638,7 +633,7 @@ ReturnedValue ArrayPrototype::method_indexOf(CallContext *ctx)
if (scope.hasException())
return Encode::undefined();
if (RuntimeHelpers::strictEqual(value, searchValue))
- return Encode((uint)(val - instance->arrayData->data));
+ return Encode((uint)(val - instance->arrayData()->arrayData()));
}
++val;
}
@@ -650,7 +645,7 @@ ReturnedValue ArrayPrototype::method_lastIndexOf(CallContext *ctx)
{
Scope scope(ctx);
- ScopedObject instance(scope, ctx->callData->thisObject.toObject(ctx));
+ ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(ctx));
if (!instance)
return Encode::undefined();
uint len = instance->getLength();
@@ -660,13 +655,13 @@ ReturnedValue ArrayPrototype::method_lastIndexOf(CallContext *ctx)
ScopedValue searchValue(scope);
uint fromIndex = len;
- if (ctx->callData->argc >= 1)
+ if (ctx->d()->callData->argc >= 1)
searchValue = ctx->argument(0);
else
searchValue = Primitive::undefinedValue();
- if (ctx->callData->argc >= 2) {
- double f = ctx->callData->args[1].toInteger();
+ if (ctx->d()->callData->argc >= 2) {
+ double f = ctx->d()->callData->args[1].toInteger();
if (scope.hasException())
return Encode::undefined();
if (f > 0)
@@ -695,7 +690,7 @@ ReturnedValue ArrayPrototype::method_lastIndexOf(CallContext *ctx)
ReturnedValue ArrayPrototype::method_every(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Object> instance(scope, ctx->callData->thisObject.toObject(ctx));
+ Scoped<Object> instance(scope, ctx->d()->callData->thisObject.toObject(ctx));
if (!instance)
return Encode::undefined();
@@ -729,7 +724,7 @@ ReturnedValue ArrayPrototype::method_every(CallContext *ctx)
ReturnedValue ArrayPrototype::method_some(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Object> instance(scope, ctx->callData->thisObject.toObject(ctx));
+ Scoped<Object> instance(scope, ctx->d()->callData->thisObject.toObject(ctx));
if (!instance)
return Encode::undefined();
@@ -763,7 +758,7 @@ ReturnedValue ArrayPrototype::method_some(CallContext *ctx)
ReturnedValue ArrayPrototype::method_forEach(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Object> instance(scope, ctx->callData->thisObject.toObject(ctx));
+ Scoped<Object> instance(scope, ctx->d()->callData->thisObject.toObject(ctx));
if (!instance)
return Encode::undefined();
@@ -794,7 +789,7 @@ ReturnedValue ArrayPrototype::method_forEach(CallContext *ctx)
ReturnedValue ArrayPrototype::method_map(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Object> instance(scope, ctx->callData->thisObject.toObject(ctx));
+ Scoped<Object> instance(scope, ctx->d()->callData->thisObject.toObject(ctx));
if (!instance)
return Encode::undefined();
@@ -804,7 +799,7 @@ ReturnedValue ArrayPrototype::method_map(CallContext *ctx)
if (!callback)
return ctx->throwTypeError();
- Scoped<ArrayObject> a(scope, ctx->engine->newArrayObject());
+ Scoped<ArrayObject> a(scope, ctx->d()->engine->newArrayObject());
a->arrayReserve(len);
a->setArrayLengthUnchecked(len);
@@ -831,7 +826,7 @@ ReturnedValue ArrayPrototype::method_map(CallContext *ctx)
ReturnedValue ArrayPrototype::method_filter(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Object> instance(scope, ctx->callData->thisObject.toObject(ctx));
+ Scoped<Object> instance(scope, ctx->d()->callData->thisObject.toObject(ctx));
if (!instance)
return Encode::undefined();
@@ -841,7 +836,7 @@ ReturnedValue ArrayPrototype::method_filter(CallContext *ctx)
if (!callback)
return ctx->throwTypeError();
- Scoped<ArrayObject> a(scope, ctx->engine->newArrayObject());
+ Scoped<ArrayObject> a(scope, ctx->d()->engine->newArrayObject());
a->arrayReserve(len);
ScopedValue selected(scope);
@@ -872,7 +867,7 @@ ReturnedValue ArrayPrototype::method_filter(CallContext *ctx)
ReturnedValue ArrayPrototype::method_reduce(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Object> instance(scope, ctx->callData->thisObject.toObject(ctx));
+ Scoped<Object> instance(scope, ctx->d()->callData->thisObject.toObject(ctx));
if (!instance)
return Encode::undefined();
@@ -886,7 +881,7 @@ ReturnedValue ArrayPrototype::method_reduce(CallContext *ctx)
ScopedValue acc(scope);
ScopedValue v(scope);
- if (ctx->callData->argc > 1) {
+ if (ctx->d()->callData->argc > 1) {
acc = ctx->argument(1);
} else {
bool kPresent = false;
@@ -922,7 +917,7 @@ ReturnedValue ArrayPrototype::method_reduce(CallContext *ctx)
ReturnedValue ArrayPrototype::method_reduceRight(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Object> instance(scope, ctx->callData->thisObject.toObject(ctx));
+ Scoped<Object> instance(scope, ctx->d()->callData->thisObject.toObject(ctx));
if (!instance)
return Encode::undefined();
@@ -933,7 +928,7 @@ ReturnedValue ArrayPrototype::method_reduceRight(CallContext *ctx)
return ctx->throwTypeError();
if (len == 0) {
- if (ctx->callData->argc == 1)
+ if (ctx->d()->callData->argc == 1)
return ctx->throwTypeError();
return ctx->argument(1);
}
@@ -941,7 +936,7 @@ ReturnedValue ArrayPrototype::method_reduceRight(CallContext *ctx)
uint k = len;
ScopedValue acc(scope);
ScopedValue v(scope);
- if (ctx->callData->argc > 1) {
+ if (ctx->d()->callData->argc > 1) {
acc = ctx->argument(1);
} else {
bool kPresent = false;
diff --git a/src/qml/jsruntime/qv4arrayobject_p.h b/src/qml/jsruntime/qv4arrayobject_p.h
index e7f8ba711f..dccda2896e 100644
--- a/src/qml/jsruntime/qv4arrayobject_p.h
+++ b/src/qml/jsruntime/qv4arrayobject_p.h
@@ -51,8 +51,11 @@ namespace QV4 {
struct ArrayCtor: FunctionObject
{
- V4_OBJECT
- ArrayCtor(ExecutionContext *scope);
+ struct Data : FunctionObject::Data {
+ Data(ExecutionContext *scope);
+ };
+
+ V4_OBJECT(FunctionObject)
static ReturnedValue construct(Managed *m, CallData *callData);
static ReturnedValue call(Managed *that, CallData *callData);
@@ -60,9 +63,7 @@ struct ArrayCtor: FunctionObject
struct ArrayPrototype: ArrayObject
{
- ArrayPrototype(InternalClass *ic);
-
- void init(ExecutionEngine *engine, ObjectRef ctor);
+ void init(ExecutionEngine *engine, Object *ctor);
static ReturnedValue method_isArray(CallContext *ctx);
static ReturnedValue method_toString(CallContext *ctx);
diff --git a/src/qml/jsruntime/qv4booleanobject.cpp b/src/qml/jsruntime/qv4booleanobject.cpp
index 662ec64efb..38a0f7f549 100644
--- a/src/qml/jsruntime/qv4booleanobject.cpp
+++ b/src/qml/jsruntime/qv4booleanobject.cpp
@@ -46,8 +46,8 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(BooleanCtor);
DEFINE_OBJECT_VTABLE(BooleanObject);
-BooleanCtor::BooleanCtor(ExecutionContext *scope)
- : FunctionObject(scope, QStringLiteral("Boolean"))
+BooleanCtor::Data::Data(ExecutionContext *scope)
+ : FunctionObject::Data(scope, QStringLiteral("Boolean"))
{
setVTable(staticVTable());
}
@@ -66,7 +66,7 @@ ReturnedValue BooleanCtor::call(Managed *, CallData *callData)
return Encode(value);
}
-void BooleanPrototype::init(ExecutionEngine *engine, ObjectRef ctor)
+void BooleanPrototype::init(ExecutionEngine *engine, Object *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
@@ -80,28 +80,28 @@ void BooleanPrototype::init(ExecutionEngine *engine, ObjectRef ctor)
ReturnedValue BooleanPrototype::method_toString(CallContext *ctx)
{
bool result;
- if (ctx->callData->thisObject.isBoolean()) {
- result = ctx->callData->thisObject.booleanValue();
+ if (ctx->d()->callData->thisObject.isBoolean()) {
+ result = ctx->d()->callData->thisObject.booleanValue();
} else {
Scope scope(ctx);
- Scoped<BooleanObject> thisObject(scope, ctx->callData->thisObject);
+ Scoped<BooleanObject> thisObject(scope, ctx->d()->callData->thisObject);
if (!thisObject)
return ctx->throwTypeError();
- result = thisObject->value.booleanValue();
+ result = thisObject->value().booleanValue();
}
- return Encode(ctx->engine->newString(QLatin1String(result ? "true" : "false")));
+ return Encode(ctx->d()->engine->newString(QLatin1String(result ? "true" : "false")));
}
ReturnedValue BooleanPrototype::method_valueOf(CallContext *ctx)
{
- if (ctx->callData->thisObject.isBoolean())
- return ctx->callData->thisObject.asReturnedValue();
+ if (ctx->d()->callData->thisObject.isBoolean())
+ return ctx->d()->callData->thisObject.asReturnedValue();
Scope scope(ctx);
- Scoped<BooleanObject> thisObject(scope, ctx->callData->thisObject);
+ Scoped<BooleanObject> thisObject(scope, ctx->d()->callData->thisObject);
if (!thisObject)
return ctx->throwTypeError();
- return thisObject->value.asReturnedValue();
+ return thisObject->value().asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4booleanobject_p.h b/src/qml/jsruntime/qv4booleanobject_p.h
index 617f7f6b01..35cfd5729e 100644
--- a/src/qml/jsruntime/qv4booleanobject_p.h
+++ b/src/qml/jsruntime/qv4booleanobject_p.h
@@ -51,8 +51,11 @@ namespace QV4 {
struct BooleanCtor: FunctionObject
{
- V4_OBJECT
- BooleanCtor(ExecutionContext *scope);
+ struct Data : FunctionObject::Data {
+ Data(ExecutionContext *scope);
+ };
+
+ V4_OBJECT(FunctionObject)
static ReturnedValue construct(Managed *, CallData *callData);
static ReturnedValue call(Managed *that, CallData *callData);
@@ -60,8 +63,7 @@ struct BooleanCtor: FunctionObject
struct BooleanPrototype: BooleanObject
{
- BooleanPrototype(InternalClass *ic): BooleanObject(ic) {}
- void init(ExecutionEngine *engine, ObjectRef ctor);
+ void init(ExecutionEngine *engine, Object *ctor);
static ReturnedValue method_toString(CallContext *ctx);
static ReturnedValue method_valueOf(CallContext *ctx);
diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp
index b43b4893a3..62d5859e87 100644
--- a/src/qml/jsruntime/qv4context.cpp
+++ b/src/qml/jsruntime/qv4context.cpp
@@ -52,27 +52,30 @@
using namespace QV4;
DEFINE_MANAGED_VTABLE(ExecutionContext);
+DEFINE_MANAGED_VTABLE(CallContext);
+DEFINE_MANAGED_VTABLE(WithContext);
+DEFINE_MANAGED_VTABLE(GlobalContext);
-CallContext *ExecutionContext::newCallContext(FunctionObject *function, CallData *callData)
+HeapObject *ExecutionContext::newCallContext(FunctionObject *function, CallData *callData)
{
- Q_ASSERT(function->function);
+ Q_ASSERT(function->function());
- CallContext *c = static_cast<CallContext *>(engine->memoryManager->allocManaged(requiredMemoryForExecutionContect(function, callData->argc)));
- new (c) CallContext(engine, Type_CallContext);
+ CallContext::Data *c = reinterpret_cast<CallContext::Data *>(d()->engine->memoryManager->allocManaged(requiredMemoryForExecutionContect(function, callData->argc)));
+ new (c) CallContext::Data(d()->engine, Type_CallContext);
c->function = function;
c->realArgumentCount = callData->argc;
- c->strictMode = function->strictMode;
- c->outer = function->scope;
+ c->strictMode = function->strictMode();
+ c->outer = function->scope();
c->activation = 0;
- c->compilationUnit = function->function->compilationUnit;
+ c->compilationUnit = function->function()->compilationUnit;
c->lookups = c->compilationUnit->runtimeLookups;
c->locals = (Value *)((quintptr(c + 1) + 7) & ~7);
- const CompiledData::Function *compiledFunction = function->function->compiledFunction;
+ const CompiledData::Function *compiledFunction = function->function()->compiledFunction;
int nLocals = compiledFunction->nLocals;
if (nLocals)
std::fill(c->locals, c->locals + nLocals, Primitive::undefinedValue());
@@ -86,43 +89,41 @@ CallContext *ExecutionContext::newCallContext(FunctionObject *function, CallData
return c;
}
-WithContext *ExecutionContext::newWithContext(ObjectRef with)
+WithContext *ExecutionContext::newWithContext(Object *with)
{
- WithContext *w = new (engine->memoryManager) WithContext(engine, with);
- return w;
+ return d()->engine->memoryManager->alloc<WithContext>(d()->engine, with);
}
-CatchContext *ExecutionContext::newCatchContext(const StringRef exceptionVarName, const ValueRef exceptionValue)
+CatchContext *ExecutionContext::newCatchContext(String *exceptionVarName, const ValueRef exceptionValue)
{
- CatchContext *c = new (engine->memoryManager) CatchContext(engine, exceptionVarName, exceptionValue);
- return c;
+ return d()->engine->memoryManager->alloc<CatchContext>(d()->engine, exceptionVarName, exceptionValue);
}
-CallContext *ExecutionContext::newQmlContext(FunctionObject *f, ObjectRef qml)
+CallContext *ExecutionContext::newQmlContext(FunctionObject *f, Object *qml)
{
- CallContext *c = static_cast<CallContext *>(engine->memoryManager->allocManaged(requiredMemoryForExecutionContect(f, 0)));
- new (c) CallContext(engine, qml, f);
+ CallContext *c = reinterpret_cast<CallContext*>(d()->engine->memoryManager->allocManaged(requiredMemoryForExecutionContect(f, 0)));
+ new (c->d()) CallContext::Data(d()->engine, qml, f);
return c;
}
-void ExecutionContext::createMutableBinding(const StringRef name, bool deletable)
+void ExecutionContext::createMutableBinding(String *name, bool deletable)
{
Scope scope(this);
// find the right context to create the binding on
- ScopedObject activation(scope, engine->globalObject);
+ ScopedObject activation(scope, d()->engine->globalObject);
ExecutionContext *ctx = this;
while (ctx) {
- if (ctx->type >= Type_CallContext) {
+ if (ctx->d()->type >= Type_CallContext) {
CallContext *c = static_cast<CallContext *>(ctx);
- if (!c->activation)
- c->activation = engine->newObject()->getPointer();
- activation = c->activation;
+ if (!c->d()->activation)
+ c->d()->activation = d()->engine->newObject()->getPointer();
+ activation = c->d()->activation;
break;
}
- ctx = ctx->outer;
+ ctx = ctx->d()->outer;
}
if (activation->hasProperty(name))
@@ -134,38 +135,38 @@ void ExecutionContext::createMutableBinding(const StringRef name, bool deletable
}
-GlobalContext::GlobalContext(ExecutionEngine *eng)
- : ExecutionContext(eng, Type_GlobalContext)
+GlobalContext::Data::Data(ExecutionEngine *eng)
+ : ExecutionContext::Data(eng, Type_GlobalContext)
{
global = eng->globalObject;
}
-WithContext::WithContext(ExecutionEngine *engine, ObjectRef with)
- : ExecutionContext(engine, Type_WithContext)
+WithContext::Data::Data(ExecutionEngine *engine, Object *with)
+ : ExecutionContext::Data(engine, Type_WithContext)
{
- callData = parent->callData;
+ callData = parent->d()->callData;
outer = parent;
- lookups = parent->lookups;
- compilationUnit = parent->compilationUnit;
+ lookups = parent->d()->lookups;
+ compilationUnit = parent->d()->compilationUnit;
- withObject = with.getPointer();
+ withObject = with;
}
-CatchContext::CatchContext(ExecutionEngine *engine, const StringRef exceptionVarName, const ValueRef exceptionValue)
- : ExecutionContext(engine, Type_CatchContext)
+CatchContext::Data::Data(ExecutionEngine *engine, String *exceptionVarName, const ValueRef exceptionValue)
+ : ExecutionContext::Data(engine, Type_CatchContext)
{
- strictMode = parent->strictMode;
- callData = parent->callData;
+ strictMode = parent->d()->strictMode;
+ callData = parent->d()->callData;
outer = parent;
- lookups = parent->lookups;
- compilationUnit = parent->compilationUnit;
+ lookups = parent->d()->lookups;
+ compilationUnit = parent->d()->compilationUnit;
this->exceptionVarName = exceptionVarName;
this->exceptionValue = exceptionValue;
}
-CallContext::CallContext(ExecutionEngine *engine, ObjectRef qml, FunctionObject *function)
- : ExecutionContext(engine, Type_QmlContext)
+CallContext::Data::Data(ExecutionEngine *engine, Object *qml, FunctionObject *function)
+ : ExecutionContext::Data(engine, Type_QmlContext)
{
this->function = function;
callData = reinterpret_cast<CallData *>(this + 1);
@@ -174,12 +175,12 @@ CallContext::CallContext(ExecutionEngine *engine, ObjectRef qml, FunctionObject
callData->thisObject = Primitive::undefinedValue();
strictMode = true;
- outer = function->scope;
+ outer = function->scope();
- activation = qml.getPointer();
+ activation = qml;
- if (function->function) {
- compilationUnit = function->function->compilationUnit;
+ if (function->function()) {
+ compilationUnit = function->function()->compilationUnit;
lookups = compilationUnit->runtimeLookups;
}
@@ -190,170 +191,170 @@ CallContext::CallContext(ExecutionEngine *engine, ObjectRef qml, FunctionObject
String * const *CallContext::formals() const
{
- return (function && function->function) ? function->function->internalClass->nameMap.constData() : 0;
+ return (d()->function && d()->function->function()) ? d()->function->function()->internalClass->nameMap.constData() : 0;
}
unsigned int CallContext::formalCount() const
{
- return function ? function->formalParameterCount() : 0;
+ return d()->function ? d()->function->formalParameterCount() : 0;
}
String * const *CallContext::variables() const
{
- return (function && function->function) ? function->function->internalClass->nameMap.constData() + function->function->compiledFunction->nFormals : 0;
+ return (d()->function && d()->function->function()) ? d()->function->function()->internalClass->nameMap.constData() + d()->function->function()->compiledFunction->nFormals : 0;
}
unsigned int CallContext::variableCount() const
{
- return function ? function->varCount() : 0;
+ return d()->function ? d()->function->varCount() : 0;
}
-bool ExecutionContext::deleteProperty(const StringRef name)
+bool ExecutionContext::deleteProperty(String *name)
{
Scope scope(this);
bool hasWith = false;
- for (ExecutionContext *ctx = this; ctx; ctx = ctx->outer) {
- if (ctx->type == Type_WithContext) {
+ for (ExecutionContext *ctx = this; ctx; ctx = ctx->d()->outer) {
+ if (ctx->d()->type == Type_WithContext) {
hasWith = true;
WithContext *w = static_cast<WithContext *>(ctx);
- if (w->withObject->hasProperty(name))
- return w->withObject->deleteProperty(name);
- } else if (ctx->type == Type_CatchContext) {
+ if (w->d()->withObject->hasProperty(name))
+ return w->d()->withObject->deleteProperty(name);
+ } else if (ctx->d()->type == Type_CatchContext) {
CatchContext *c = static_cast<CatchContext *>(ctx);
- if (c->exceptionVarName->isEqualTo(name))
+ if (c->d()->exceptionVarName->isEqualTo(name))
return false;
- } else if (ctx->type >= Type_CallContext) {
+ } else if (ctx->d()->type >= Type_CallContext) {
CallContext *c = static_cast<CallContext *>(ctx);
- FunctionObject *f = c->function;
- if (f->needsActivation || hasWith) {
- uint index = f->function->internalClass->find(name);
+ FunctionObject *f = c->d()->function;
+ if (f->needsActivation() || hasWith) {
+ uint index = f->function()->internalClass->find(name);
if (index < UINT_MAX)
// ### throw in strict mode?
return false;
}
- if (c->activation && c->activation->hasProperty(name))
- return c->activation->deleteProperty(name);
- } else if (ctx->type == Type_GlobalContext) {
+ if (c->d()->activation && c->d()->activation->hasProperty(name))
+ return c->d()->activation->deleteProperty(name);
+ } else if (ctx->d()->type == Type_GlobalContext) {
GlobalContext *g = static_cast<GlobalContext *>(ctx);
- if (g->global->hasProperty(name))
- return g->global->deleteProperty(name);
+ if (g->d()->global->hasProperty(name))
+ return g->d()->global->deleteProperty(name);
}
}
- if (strictMode)
+ if (d()->strictMode)
throwSyntaxError(QStringLiteral("Can't delete property %1").arg(name->toQString()));
return true;
}
bool CallContext::needsOwnArguments() const
{
- return function->needsActivation || callData->argc < static_cast<int>(function->formalParameterCount());
+ return d()->function->needsActivation() || d()->callData->argc < static_cast<int>(d()->function->formalParameterCount());
}
void ExecutionContext::markObjects(Managed *m, ExecutionEngine *engine)
{
ExecutionContext *ctx = static_cast<ExecutionContext *>(m);
- if (ctx->outer)
- ctx->outer->mark(engine);
+ if (ctx->d()->outer)
+ ctx->d()->outer->mark(engine);
// ### shouldn't need these 3 lines
- ctx->callData->thisObject.mark(engine);
- for (int arg = 0; arg < ctx->callData->argc; ++arg)
- ctx->callData->args[arg].mark(engine);
+ ctx->d()->callData->thisObject.mark(engine);
+ for (int arg = 0; arg < ctx->d()->callData->argc; ++arg)
+ ctx->d()->callData->args[arg].mark(engine);
- if (ctx->type >= Type_CallContext) {
+ if (ctx->d()->type >= Type_CallContext) {
QV4::CallContext *c = static_cast<CallContext *>(ctx);
- for (unsigned local = 0, lastLocal = c->function->varCount(); local < lastLocal; ++local)
- c->locals[local].mark(engine);
- if (c->activation)
- c->activation->mark(engine);
- c->function->mark(engine);
- } else if (ctx->type == Type_WithContext) {
+ for (unsigned local = 0, lastLocal = c->d()->function->varCount(); local < lastLocal; ++local)
+ c->d()->locals[local].mark(engine);
+ if (c->d()->activation)
+ c->d()->activation->mark(engine);
+ c->d()->function->mark(engine);
+ } else if (ctx->d()->type == Type_WithContext) {
WithContext *w = static_cast<WithContext *>(ctx);
- w->withObject->mark(engine);
- } else if (ctx->type == Type_CatchContext) {
+ w->d()->withObject->mark(engine);
+ } else if (ctx->d()->type == Type_CatchContext) {
CatchContext *c = static_cast<CatchContext *>(ctx);
- c->exceptionVarName->mark(engine);
- c->exceptionValue.mark(engine);
- } else if (ctx->type == Type_GlobalContext) {
+ c->d()->exceptionVarName->mark(engine);
+ c->d()->exceptionValue.mark(engine);
+ } else if (ctx->d()->type == Type_GlobalContext) {
GlobalContext *g = static_cast<GlobalContext *>(ctx);
- g->global->mark(engine);
+ g->d()->global->mark(engine);
}
}
-void ExecutionContext::setProperty(const StringRef name, const ValueRef value)
+void ExecutionContext::setProperty(String *name, const ValueRef value)
{
Scope scope(this);
- for (ExecutionContext *ctx = this; ctx; ctx = ctx->outer) {
- if (ctx->type == Type_WithContext) {
- ScopedObject w(scope, static_cast<WithContext *>(ctx)->withObject);
+ for (ExecutionContext *ctx = this; ctx; ctx = ctx->d()->outer) {
+ if (ctx->d()->type == Type_WithContext) {
+ ScopedObject w(scope, static_cast<WithContext *>(ctx)->d()->withObject);
if (w->hasProperty(name)) {
w->put(name, value);
return;
}
- } else if (ctx->type == Type_CatchContext && static_cast<CatchContext *>(ctx)->exceptionVarName->isEqualTo(name)) {
- static_cast<CatchContext *>(ctx)->exceptionValue = *value;
+ } else if (ctx->d()->type == Type_CatchContext && static_cast<CatchContext *>(ctx)->d()->exceptionVarName->isEqualTo(name)) {
+ static_cast<CatchContext *>(ctx)->d()->exceptionValue = *value;
return;
} else {
ScopedObject activation(scope, (Object *)0);
- if (ctx->type >= Type_CallContext) {
+ if (ctx->d()->type >= Type_CallContext) {
CallContext *c = static_cast<CallContext *>(ctx);
- if (c->function->function) {
- uint index = c->function->function->internalClass->find(name);
+ if (c->d()->function->function()) {
+ uint index = c->d()->function->function()->internalClass->find(name);
if (index < UINT_MAX) {
- if (index < c->function->formalParameterCount()) {
- c->callData->args[c->function->formalParameterCount() - index - 1] = *value;
+ if (index < c->d()->function->formalParameterCount()) {
+ c->d()->callData->args[c->d()->function->formalParameterCount() - index - 1] = *value;
} else {
- index -= c->function->formalParameterCount();
- c->locals[index] = *value;
+ index -= c->d()->function->formalParameterCount();
+ c->d()->locals[index] = *value;
}
return;
}
}
- activation = c->activation;
- } else if (ctx->type == Type_GlobalContext) {
- activation = static_cast<GlobalContext *>(ctx)->global;
+ activation = c->d()->activation;
+ } else if (ctx->d()->type == Type_GlobalContext) {
+ activation = static_cast<GlobalContext *>(ctx)->d()->global;
}
if (activation) {
- if (ctx->type == Type_QmlContext) {
+ if (ctx->d()->type == Type_QmlContext) {
activation->put(name, value);
return;
} else {
- uint member = activation->internalClass->find(name);
+ uint member = activation->internalClass()->find(name);
if (member < UINT_MAX) {
- activation->putValue(activation->propertyAt(member), activation->internalClass->propertyData[member], value);
+ activation->putValue(activation->propertyAt(member), activation->internalClass()->propertyData[member], value);
return;
}
}
}
}
}
- if (strictMode || name->equals(engine->id_this)) {
- ScopedValue n(scope, name.asReturnedValue());
+ if (d()->strictMode || name->equals(d()->engine->id_this.getPointer())) {
+ ScopedValue n(scope, name->asReturnedValue());
throwReferenceError(n);
return;
}
- engine->globalObject->put(name, value);
+ d()->engine->globalObject->put(name, value);
}
-ReturnedValue ExecutionContext::getProperty(const StringRef name)
+ReturnedValue ExecutionContext::getProperty(String *name)
{
Scope scope(this);
ScopedValue v(scope);
name->makeIdentifier();
- if (name->equals(engine->id_this))
- return callData->thisObject.asReturnedValue();
+ if (name->equals(d()->engine->id_this.getPointer()))
+ return d()->callData->thisObject.asReturnedValue();
bool hasWith = false;
bool hasCatchScope = false;
- for (ExecutionContext *ctx = this; ctx; ctx = ctx->outer) {
- if (ctx->type == Type_WithContext) {
- ScopedObject w(scope, static_cast<WithContext *>(ctx)->withObject);
+ for (ExecutionContext *ctx = this; ctx; ctx = ctx->d()->outer) {
+ if (ctx->d()->type == Type_WithContext) {
+ ScopedObject w(scope, static_cast<WithContext *>(ctx)->d()->withObject);
hasWith = true;
bool hasProperty = false;
v = w->get(name, &hasProperty);
@@ -363,62 +364,62 @@ ReturnedValue ExecutionContext::getProperty(const StringRef name)
continue;
}
- else if (ctx->type == Type_CatchContext) {
+ else if (ctx->d()->type == Type_CatchContext) {
hasCatchScope = true;
CatchContext *c = static_cast<CatchContext *>(ctx);
- if (c->exceptionVarName->isEqualTo(name))
- return c->exceptionValue.asReturnedValue();
+ if (c->d()->exceptionVarName->isEqualTo(name))
+ return c->d()->exceptionValue.asReturnedValue();
}
- else if (ctx->type >= Type_CallContext) {
+ else if (ctx->d()->type >= Type_CallContext) {
QV4::CallContext *c = static_cast<CallContext *>(ctx);
- ScopedFunctionObject f(scope, c->function);
- if (f->function && (f->needsActivation || hasWith || hasCatchScope)) {
- uint index = f->function->internalClass->find(name);
+ ScopedFunctionObject f(scope, c->d()->function);
+ if (f->function() && (f->needsActivation() || hasWith || hasCatchScope)) {
+ uint index = f->function()->internalClass->find(name);
if (index < UINT_MAX) {
- if (index < c->function->formalParameterCount())
- return c->callData->args[c->function->formalParameterCount() - index - 1].asReturnedValue();
- return c->locals[index - c->function->formalParameterCount()].asReturnedValue();
+ if (index < c->d()->function->formalParameterCount())
+ return c->d()->callData->args[c->d()->function->formalParameterCount() - index - 1].asReturnedValue();
+ return c->d()->locals[index - c->d()->function->formalParameterCount()].asReturnedValue();
}
}
- if (c->activation) {
+ if (c->d()->activation) {
bool hasProperty = false;
- v = c->activation->get(name, &hasProperty);
+ v = c->d()->activation->get(name, &hasProperty);
if (hasProperty)
return v.asReturnedValue();
}
- if (f->function && f->function->isNamedExpression()
- && name->equals(f->function->name()))
+ if (f->function() && f->function()->isNamedExpression()
+ && name->equals(f->function()->name()))
return f.asReturnedValue();
}
- else if (ctx->type == Type_GlobalContext) {
+ else if (ctx->d()->type == Type_GlobalContext) {
GlobalContext *g = static_cast<GlobalContext *>(ctx);
bool hasProperty = false;
- v = g->global->get(name, &hasProperty);
+ v = g->d()->global->get(name, &hasProperty);
if (hasProperty)
return v.asReturnedValue();
}
}
- ScopedValue n(scope, name.asReturnedValue());
+ ScopedValue n(scope, name);
return throwReferenceError(n);
}
-ReturnedValue ExecutionContext::getPropertyAndBase(const StringRef name, ObjectRef base)
+ReturnedValue ExecutionContext::getPropertyAndBase(String *name, Object *&base)
{
Scope scope(this);
ScopedValue v(scope);
base = (Object *)0;
name->makeIdentifier();
- if (name->equals(engine->id_this))
- return callData->thisObject.asReturnedValue();
+ if (name->equals(d()->engine->id_this.getPointer()))
+ return d()->callData->thisObject.asReturnedValue();
bool hasWith = false;
bool hasCatchScope = false;
- for (ExecutionContext *ctx = this; ctx; ctx = ctx->outer) {
- if (ctx->type == Type_WithContext) {
- Object *w = static_cast<WithContext *>(ctx)->withObject;
+ for (ExecutionContext *ctx = this; ctx; ctx = ctx->d()->outer) {
+ if (ctx->d()->type == Type_WithContext) {
+ Object *w = static_cast<WithContext *>(ctx)->d()->withObject;
hasWith = true;
bool hasProperty = false;
v = w->get(name, &hasProperty);
@@ -429,103 +430,103 @@ ReturnedValue ExecutionContext::getPropertyAndBase(const StringRef name, ObjectR
continue;
}
- else if (ctx->type == Type_CatchContext) {
+ else if (ctx->d()->type == Type_CatchContext) {
hasCatchScope = true;
CatchContext *c = static_cast<CatchContext *>(ctx);
- if (c->exceptionVarName->isEqualTo(name))
- return c->exceptionValue.asReturnedValue();
+ if (c->d()->exceptionVarName->isEqualTo(name))
+ return c->d()->exceptionValue.asReturnedValue();
}
- else if (ctx->type >= Type_CallContext) {
+ else if (ctx->d()->type >= Type_CallContext) {
QV4::CallContext *c = static_cast<CallContext *>(ctx);
- FunctionObject *f = c->function;
- if (f->function && (f->needsActivation || hasWith || hasCatchScope)) {
- uint index = f->function->internalClass->find(name);
+ FunctionObject *f = c->d()->function;
+ if (f->function() && (f->needsActivation() || hasWith || hasCatchScope)) {
+ uint index = f->function()->internalClass->find(name);
if (index < UINT_MAX) {
- if (index < c->function->formalParameterCount())
- return c->callData->args[c->function->formalParameterCount() - index - 1].asReturnedValue();
- return c->locals[index - c->function->formalParameterCount()].asReturnedValue();
+ if (index < c->d()->function->formalParameterCount())
+ return c->d()->callData->args[c->d()->function->formalParameterCount() - index - 1].asReturnedValue();
+ return c->d()->locals[index - c->d()->function->formalParameterCount()].asReturnedValue();
}
}
- if (c->activation) {
+ if (c->d()->activation) {
bool hasProperty = false;
- v = c->activation->get(name, &hasProperty);
+ v = c->d()->activation->get(name, &hasProperty);
if (hasProperty) {
- if (ctx->type == Type_QmlContext)
- base = c->activation;
+ if (ctx->d()->type == Type_QmlContext)
+ base = c->d()->activation;
return v.asReturnedValue();
}
}
- if (f->function && f->function->isNamedExpression()
- && name->equals(f->function->name()))
- return c->function->asReturnedValue();
+ if (f->function() && f->function()->isNamedExpression()
+ && name->equals(f->function()->name()))
+ return c->d()->function->asReturnedValue();
}
- else if (ctx->type == Type_GlobalContext) {
+ else if (ctx->d()->type == Type_GlobalContext) {
GlobalContext *g = static_cast<GlobalContext *>(ctx);
bool hasProperty = false;
- v = g->global->get(name, &hasProperty);
+ v = g->d()->global->get(name, &hasProperty);
if (hasProperty)
return v.asReturnedValue();
}
}
- ScopedValue n(scope, name.asReturnedValue());
+ ScopedValue n(scope, name);
return throwReferenceError(n);
}
ReturnedValue ExecutionContext::throwError(const ValueRef value)
{
- return engine->throwException(value);
+ return d()->engine->throwException(value);
}
ReturnedValue ExecutionContext::throwError(const QString &message)
{
Scope scope(this);
- ScopedValue v(scope, engine->newString(message));
- v = engine->newErrorObject(v);
+ ScopedValue v(scope, d()->engine->newString(message));
+ v = d()->engine->newErrorObject(v);
return throwError(v);
}
ReturnedValue ExecutionContext::throwSyntaxError(const QString &message, const QString &fileName, int line, int column)
{
Scope scope(this);
- Scoped<Object> error(scope, engine->newSyntaxErrorObject(message, fileName, line, column));
+ Scoped<Object> error(scope, d()->engine->newSyntaxErrorObject(message, fileName, line, column));
return throwError(error);
}
ReturnedValue ExecutionContext::throwSyntaxError(const QString &message)
{
Scope scope(this);
- Scoped<Object> error(scope, engine->newSyntaxErrorObject(message));
+ Scoped<Object> error(scope, d()->engine->newSyntaxErrorObject(message));
return throwError(error);
}
ReturnedValue ExecutionContext::throwTypeError()
{
Scope scope(this);
- Scoped<Object> error(scope, engine->newTypeErrorObject(QStringLiteral("Type error")));
+ Scoped<Object> error(scope, d()->engine->newTypeErrorObject(QStringLiteral("Type error")));
return throwError(error);
}
ReturnedValue ExecutionContext::throwTypeError(const QString &message)
{
Scope scope(this);
- Scoped<Object> error(scope, engine->newTypeErrorObject(message));
+ Scoped<Object> error(scope, d()->engine->newTypeErrorObject(message));
return throwError(error);
}
ReturnedValue ExecutionContext::throwUnimplemented(const QString &message)
{
Scope scope(this);
- ScopedValue v(scope, engine->newString(QStringLiteral("Unimplemented ") + message));
- v = engine->newErrorObject(v);
+ ScopedValue v(scope, d()->engine->newString(QStringLiteral("Unimplemented ") + message));
+ v = d()->engine->newErrorObject(v);
return throwError(v);
}
ReturnedValue ExecutionContext::catchException(StackTrace *trace)
{
- return engine->catchException(this, trace);
+ return d()->engine->catchException(this, trace);
}
ReturnedValue ExecutionContext::throwReferenceError(const ValueRef value)
@@ -533,7 +534,7 @@ ReturnedValue ExecutionContext::throwReferenceError(const ValueRef value)
Scope scope(this);
Scoped<String> s(scope, value->toString(this));
QString msg = s->toQString() + QStringLiteral(" is not defined");
- Scoped<Object> error(scope, engine->newReferenceErrorObject(msg));
+ Scoped<Object> error(scope, d()->engine->newReferenceErrorObject(msg));
return throwError(error);
}
@@ -541,7 +542,7 @@ ReturnedValue ExecutionContext::throwReferenceError(const QString &message, cons
{
Scope scope(this);
QString msg = message;
- Scoped<Object> error(scope, engine->newReferenceErrorObject(msg, fileName, line, column));
+ Scoped<Object> error(scope, d()->engine->newReferenceErrorObject(msg, fileName, line, column));
return throwError(error);
}
@@ -550,20 +551,20 @@ ReturnedValue ExecutionContext::throwRangeError(const ValueRef value)
Scope scope(this);
ScopedString s(scope, value->toString(this));
QString msg = s->toQString() + QStringLiteral(" out of range");
- ScopedObject error(scope, engine->newRangeErrorObject(msg));
+ ScopedObject error(scope, d()->engine->newRangeErrorObject(msg));
return throwError(error);
}
ReturnedValue ExecutionContext::throwRangeError(const QString &message)
{
Scope scope(this);
- ScopedObject error(scope, engine->newRangeErrorObject(message));
+ ScopedObject error(scope, d()->engine->newRangeErrorObject(message));
return throwError(error);
}
ReturnedValue ExecutionContext::throwURIError(const ValueRef msg)
{
Scope scope(this);
- ScopedObject error(scope, engine->newURIErrorObject(msg));
+ ScopedObject error(scope, d()->engine->newURIErrorObject(msg));
return throwError(error);
}
diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h
index a07cbf2da5..7e67028364 100644
--- a/src/qml/jsruntime/qv4context_p.h
+++ b/src/qml/jsruntime/qv4context_p.h
@@ -69,8 +69,6 @@ struct WithContext;
struct Q_QML_EXPORT ExecutionContext : public Managed
{
- V4_MANAGED
- Q_MANAGED_TYPE(ExecutionContext)
enum {
IsExecutionContext = true
};
@@ -83,48 +81,66 @@ struct Q_QML_EXPORT ExecutionContext : public Managed
Type_CallContext = 0x5,
Type_QmlContext = 0x6
};
-
- ExecutionContext(ExecutionEngine *engine, ContextType t)
- : Managed(engine->executionContextClass)
- {
- this->type = t;
- strictMode = false;
- this->engine = engine;
- this->parent = engine->currentContext();
- outer = 0;
- lookups = 0;
- compilationUnit = 0;
- currentEvalCode = 0;
- lineNumber = -1;
- engine->current = this;
- }
-
- ContextType type;
- bool strictMode;
-
- CallData *callData;
-
- ExecutionEngine *engine;
- ExecutionContext *parent;
- ExecutionContext *outer;
- Lookup *lookups;
- CompiledData::CompilationUnit *compilationUnit;
-
struct EvalCode
{
Function *function;
EvalCode *next;
};
- EvalCode *currentEvalCode;
- int lineNumber;
+ struct Data : Managed::Data {
+ Data(ExecutionEngine *engine, ContextType t)
+ : Managed::Data(engine->executionContextClass)
+ , type(t)
+ , strictMode(false)
+ , engine(engine)
+ , parent(engine->currentContext())
+ , outer(0)
+ , lookups(0)
+ , compilationUnit(0)
+ , currentEvalCode(0)
+ , lineNumber(-1)
+ {
+ engine->current = reinterpret_cast<ExecutionContext *>(this);
+ }
+ ContextType type;
+ bool strictMode;
+
+ CallData *callData;
+
+ ExecutionEngine *engine;
+ ExecutionContext *parent;
+ ExecutionContext *outer;
+ Lookup *lookups;
+ CompiledData::CompilationUnit *compilationUnit;
+ EvalCode *currentEvalCode;
+
+ int lineNumber;
- CallContext *newCallContext(FunctionObject *f, CallData *callData);
- WithContext *newWithContext(ObjectRef with);
- CatchContext *newCatchContext(const StringRef exceptionVarName, const ValueRef exceptionValue);
- CallContext *newQmlContext(FunctionObject *f, ObjectRef qml);
+ };
+ V4_MANAGED(Managed)
+ Q_MANAGED_TYPE(ExecutionContext)
- void createMutableBinding(const StringRef name, bool deletable);
+ ExecutionContext(ExecutionEngine *engine, ContextType t)
+ : Managed(engine->executionContextClass)
+ {
+ d()->type = t;
+ d()->strictMode = false;
+ d()->engine = engine;
+ d()->parent = engine->currentContext();
+ d()->outer = 0;
+ d()->lookups = 0;
+ d()->compilationUnit = 0;
+ d()->currentEvalCode = 0;
+ d()->lineNumber = -1;
+ engine->current = this;
+ }
+
+ HeapObject *newCallContext(FunctionObject *f, CallData *callData);
+ WithContext *newWithContext(Object *with);
+ CatchContext *newCatchContext(String *exceptionVarName, const ValueRef exceptionValue);
+ CallContext *newQmlContext(FunctionObject *f, Object *qml);
+
+ void createMutableBinding(String *name, bool deletable);
ReturnedValue throwError(const QV4::ValueRef value);
ReturnedValue throwError(const QString &message);
@@ -139,10 +155,10 @@ struct Q_QML_EXPORT ExecutionContext : public Managed
ReturnedValue throwURIError(const ValueRef msg);
ReturnedValue throwUnimplemented(const QString &message);
- void setProperty(const StringRef name, const ValueRef value);
- ReturnedValue getProperty(const StringRef name);
- ReturnedValue getPropertyAndBase(const StringRef name, ObjectRef base);
- bool deleteProperty(const StringRef name);
+ void setProperty(String *name, const ValueRef value);
+ ReturnedValue getProperty(String *name);
+ ReturnedValue getPropertyAndBase(String *name, Object *&base);
+ bool deleteProperty(String *name);
// Can only be called from within catch(...), rethrows if no JS exception.
ReturnedValue catchException(StackTrace *trace = 0);
@@ -155,19 +171,22 @@ struct Q_QML_EXPORT ExecutionContext : public Managed
struct CallContext : public ExecutionContext
{
- CallContext(ExecutionEngine *engine, ContextType t = Type_SimpleCallContext)
- : ExecutionContext(engine, t)
- {
- function = 0;
- locals = 0;
- activation = 0;
- }
- CallContext(ExecutionEngine *engine, ObjectRef qml, QV4::FunctionObject *function);
-
- FunctionObject *function;
- int realArgumentCount;
- Value *locals;
- Object *activation;
+ struct Data : ExecutionContext::Data {
+ Data(ExecutionEngine *engine, ContextType t = Type_SimpleCallContext)
+ : ExecutionContext::Data(engine, t)
+ {
+ function = 0;
+ locals = 0;
+ activation = 0;
+ }
+ Data(ExecutionEngine *engine, Object *qml, QV4::FunctionObject *function);
+
+ FunctionObject *function;
+ int realArgumentCount;
+ Value *locals;
+ Object *activation;
+ };
+ V4_MANAGED(ExecutionContext)
// formals are in reverse order
String * const *formals() const;
@@ -180,52 +199,60 @@ struct CallContext : public ExecutionContext
};
inline ReturnedValue CallContext::argument(int i) {
- return i < callData->argc ? callData->args[i].asReturnedValue() : Primitive::undefinedValue().asReturnedValue();
+ return i < d()->callData->argc ? d()->callData->args[i].asReturnedValue() : Primitive::undefinedValue().asReturnedValue();
}
struct GlobalContext : public ExecutionContext
{
- GlobalContext(ExecutionEngine *engine);
+ struct Data : ExecutionContext::Data {
+ Data(ExecutionEngine *engine);
+ Object *global;
+ };
+ V4_MANAGED(ExecutionContext)
- Object *global;
};
struct CatchContext : public ExecutionContext
{
- CatchContext(ExecutionEngine *engine, const StringRef exceptionVarName, const ValueRef exceptionValue);
-
- StringValue exceptionVarName;
- Value exceptionValue;
+ struct Data : ExecutionContext::Data {
+ Data(ExecutionEngine *engine, String *exceptionVarName, const ValueRef exceptionValue);
+ StringValue exceptionVarName;
+ Value exceptionValue;
+ };
+ V4_MANAGED(ExecutionContext)
};
struct WithContext : public ExecutionContext
{
- WithContext(ExecutionEngine *engine, ObjectRef with);
- Object *withObject;
+ struct Data : ExecutionContext::Data {
+ Data(ExecutionEngine *engine, Object *with);
+ Object *withObject;
+ };
+ V4_MANAGED(ExecutionContext)
};
inline CallContext *ExecutionContext::asCallContext()
{
- return type >= Type_SimpleCallContext ? static_cast<CallContext *>(this) : 0;
+ return d()->type >= Type_SimpleCallContext ? static_cast<CallContext *>(this) : 0;
}
inline const CallContext *ExecutionContext::asCallContext() const
{
- return type >= Type_SimpleCallContext ? static_cast<const CallContext *>(this) : 0;
+ return d()->type >= Type_SimpleCallContext ? static_cast<const CallContext *>(this) : 0;
}
inline void ExecutionEngine::pushContext(CallContext *context)
{
- context->parent = current;
+ context->d()->parent = current;
current = context;
- current->currentEvalCode = 0;
+ current->d()->currentEvalCode = 0;
}
inline ExecutionContext *ExecutionEngine::popContext()
{
- Q_ASSERT(current->parent);
- current = current->parent;
+ Q_ASSERT(current->d()->parent);
+ current = current->d()->parent;
return current;
}
@@ -235,7 +262,7 @@ struct ExecutionContextSaver
ExecutionContext *savedContext;
ExecutionContextSaver(ExecutionContext *context)
- : engine(context->engine)
+ : engine(context->d()->engine)
, savedContext(context)
{
}
@@ -246,7 +273,7 @@ struct ExecutionContextSaver
};
inline Scope::Scope(ExecutionContext *ctx)
- : engine(ctx->engine)
+ : engine(ctx->d()->engine)
#ifndef QT_NO_DEBUG
, size(0)
#endif
@@ -256,7 +283,7 @@ inline Scope::Scope(ExecutionContext *ctx)
/* Function *f, int argc */
#define requiredMemoryForExecutionContect(f, argc) \
- ((sizeof(CallContext) + 7) & ~7) + sizeof(Value) * (f->varCount() + qMax((uint)argc, f->formalParameterCount())) + sizeof(CallData)
+ ((sizeof(CallContext::Data) + 7) & ~7) + sizeof(Value) * (f->varCount() + qMax((uint)argc, f->formalParameterCount())) + sizeof(CallData)
} // namespace QV4
diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp
index ceef88455b..b7fac9432f 100644
--- a/src/qml/jsruntime/qv4dateobject.cpp
+++ b/src/qml/jsruntime/qv4dateobject.cpp
@@ -643,8 +643,8 @@ static double getLocalTZA()
DEFINE_OBJECT_VTABLE(DateObject);
-DateObject::DateObject(ExecutionEngine *engine, const QDateTime &date)
- : Object(engine->dateClass)
+DateObject::Data::Data(ExecutionEngine *engine, const QDateTime &date)
+ : Object::Data(engine->dateClass)
{
setVTable(staticVTable());
value.setDouble(date.isValid() ? date.toMSecsSinceEpoch() : qSNaN());
@@ -652,13 +652,13 @@ DateObject::DateObject(ExecutionEngine *engine, const QDateTime &date)
QDateTime DateObject::toQDateTime() const
{
- return ToDateTime(value.asDouble(), Qt::LocalTime);
+ return ToDateTime(date().asDouble(), Qt::LocalTime);
}
DEFINE_OBJECT_VTABLE(DateCtor);
-DateCtor::DateCtor(ExecutionContext *scope)
- : FunctionObject(scope, QStringLiteral("Date"))
+DateCtor::Data::Data(ExecutionContext *scope)
+ : FunctionObject::Data(scope, QStringLiteral("Date"))
{
setVTable(staticVTable());
}
@@ -674,7 +674,7 @@ ReturnedValue DateCtor::construct(Managed *m, CallData *callData)
Scope scope(m->engine());
ScopedValue arg(scope, callData->args[0]);
if (DateObject *d = arg->asDateObject())
- arg = d->value;
+ arg = d->date();
else
arg = RuntimeHelpers::toPrimitive(arg, PREFERREDTYPE_HINT);
@@ -707,7 +707,7 @@ ReturnedValue DateCtor::call(Managed *m, CallData *)
return m->engine()->newString(ToString(t))->asReturnedValue();
}
-void DatePrototype::init(ExecutionEngine *engine, ObjectRef ctor)
+void DatePrototype::init(ExecutionEngine *engine, Object *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
@@ -770,8 +770,8 @@ void DatePrototype::init(ExecutionEngine *engine, ObjectRef ctor)
double DatePrototype::getThisDate(ExecutionContext *ctx)
{
- if (DateObject *thisObject = ctx->callData->thisObject.asDateObject())
- return thisObject->value.asDouble();
+ if (DateObject *thisObject = ctx->d()->callData->thisObject.asDateObject())
+ return thisObject->date().asDouble();
else {
ctx->throwTypeError();
return 0;
@@ -780,22 +780,22 @@ double DatePrototype::getThisDate(ExecutionContext *ctx)
ReturnedValue DatePrototype::method_parse(CallContext *ctx)
{
- if (!ctx->callData->argc)
+ if (!ctx->d()->callData->argc)
return Encode(qSNaN());
- return Encode(ParseString(ctx->callData->args[0].toString(ctx)->toQString()));
+ return Encode(ParseString(ctx->d()->callData->args[0].toString(ctx)->toQString()));
}
ReturnedValue DatePrototype::method_UTC(CallContext *ctx)
{
- const int numArgs = ctx->callData->argc;
+ const int numArgs = ctx->d()->callData->argc;
if (numArgs >= 2) {
- double year = ctx->callData->args[0].toNumber();
- double month = ctx->callData->args[1].toNumber();
- double day = numArgs >= 3 ? ctx->callData->args[2].toNumber() : 1;
- double hours = numArgs >= 4 ? ctx->callData->args[3].toNumber() : 0;
- double mins = numArgs >= 5 ? ctx->callData->args[4].toNumber() : 0;
- double secs = numArgs >= 6 ? ctx->callData->args[5].toNumber() : 0;
- double ms = numArgs >= 7 ? ctx->callData->args[6].toNumber() : 0;
+ double year = ctx->d()->callData->args[0].toNumber();
+ double month = ctx->d()->callData->args[1].toNumber();
+ double day = numArgs >= 3 ? ctx->d()->callData->args[2].toNumber() : 1;
+ double hours = numArgs >= 4 ? ctx->d()->callData->args[3].toNumber() : 0;
+ double mins = numArgs >= 5 ? ctx->d()->callData->args[4].toNumber() : 0;
+ double secs = numArgs >= 6 ? ctx->d()->callData->args[5].toNumber() : 0;
+ double ms = numArgs >= 7 ? ctx->d()->callData->args[6].toNumber() : 0;
if (year >= 0 && year <= 99)
year += 1900;
double t = MakeDate(MakeDay(year, month, day),
@@ -815,37 +815,37 @@ ReturnedValue DatePrototype::method_now(CallContext *ctx)
ReturnedValue DatePrototype::method_toString(CallContext *ctx)
{
double t = getThisDate(ctx);
- return ctx->engine->newString(ToString(t))->asReturnedValue();
+ return ctx->d()->engine->newString(ToString(t))->asReturnedValue();
}
ReturnedValue DatePrototype::method_toDateString(CallContext *ctx)
{
double t = getThisDate(ctx);
- return ctx->engine->newString(ToDateString(t))->asReturnedValue();
+ return ctx->d()->engine->newString(ToDateString(t))->asReturnedValue();
}
ReturnedValue DatePrototype::method_toTimeString(CallContext *ctx)
{
double t = getThisDate(ctx);
- return ctx->engine->newString(ToTimeString(t))->asReturnedValue();
+ return ctx->d()->engine->newString(ToTimeString(t))->asReturnedValue();
}
ReturnedValue DatePrototype::method_toLocaleString(CallContext *ctx)
{
double t = getThisDate(ctx);
- return ctx->engine->newString(ToLocaleString(t))->asReturnedValue();
+ return ctx->d()->engine->newString(ToLocaleString(t))->asReturnedValue();
}
ReturnedValue DatePrototype::method_toLocaleDateString(CallContext *ctx)
{
double t = getThisDate(ctx);
- return ctx->engine->newString(ToLocaleDateString(t))->asReturnedValue();
+ return ctx->d()->engine->newString(ToLocaleDateString(t))->asReturnedValue();
}
ReturnedValue DatePrototype::method_toLocaleTimeString(CallContext *ctx)
{
double t = getThisDate(ctx);
- return ctx->engine->newString(ToLocaleTimeString(t))->asReturnedValue();
+ return ctx->d()->engine->newString(ToLocaleTimeString(t))->asReturnedValue();
}
ReturnedValue DatePrototype::method_valueOf(CallContext *ctx)
@@ -1007,196 +1007,196 @@ ReturnedValue DatePrototype::method_getTimezoneOffset(CallContext *ctx)
ReturnedValue DatePrototype::method_setTime(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<DateObject> self(scope, ctx->callData->thisObject);
+ Scoped<DateObject> self(scope, ctx->d()->callData->thisObject);
if (!self)
return ctx->throwTypeError();
- double t = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN();
- self->value.setDouble(TimeClip(t));
- return self->value.asReturnedValue();
+ double t = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN();
+ self->date().setDouble(TimeClip(t));
+ return self->date().asReturnedValue();
}
ReturnedValue DatePrototype::method_setMilliseconds(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<DateObject> self(scope, ctx->callData->thisObject);
+ Scoped<DateObject> self(scope, ctx->d()->callData->thisObject);
if (!self)
return ctx->throwTypeError();
- double t = LocalTime(self->value.asDouble());
- double ms = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN();
- self->value.setDouble(TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms)))));
- return self->value.asReturnedValue();
+ double t = LocalTime(self->date().asDouble());
+ double ms = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN();
+ self->date().setDouble(TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms)))));
+ return self->date().asReturnedValue();
}
ReturnedValue DatePrototype::method_setUTCMilliseconds(CallContext *ctx)
{
- DateObject *self = ctx->callData->thisObject.asDateObject();
+ DateObject *self = ctx->d()->callData->thisObject.asDateObject();
if (!self)
return ctx->throwTypeError();
- double t = self->value.asDouble();
- double ms = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN();
- self->value.setDouble(TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms)))));
- return self->value.asReturnedValue();
+ double t = self->date().asDouble();
+ double ms = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN();
+ self->date().setDouble(TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms)))));
+ return self->date().asReturnedValue();
}
ReturnedValue DatePrototype::method_setSeconds(CallContext *ctx)
{
- DateObject *self = ctx->callData->thisObject.asDateObject();
+ DateObject *self = ctx->d()->callData->thisObject.asDateObject();
if (!self)
return ctx->throwTypeError();
- double t = LocalTime(self->value.asDouble());
- double sec = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN();
- double ms = (ctx->callData->argc < 2) ? msFromTime(t) : ctx->callData->args[1].toNumber();
+ double t = LocalTime(self->date().asDouble());
+ double sec = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN();
+ double ms = (ctx->d()->callData->argc < 2) ? msFromTime(t) : ctx->d()->callData->args[1].toNumber();
t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), sec, ms))));
- self->value.setDouble(t);
- return self->value.asReturnedValue();
+ self->date().setDouble(t);
+ return self->date().asReturnedValue();
}
ReturnedValue DatePrototype::method_setUTCSeconds(CallContext *ctx)
{
- DateObject *self = ctx->callData->thisObject.asDateObject();
+ DateObject *self = ctx->d()->callData->thisObject.asDateObject();
if (!self)
return ctx->throwTypeError();
- double t = self->value.asDouble();
- double sec = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN();
- double ms = (ctx->callData->argc < 2) ? msFromTime(t) : ctx->callData->args[1].toNumber();
+ double t = self->date().asDouble();
+ double sec = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN();
+ double ms = (ctx->d()->callData->argc < 2) ? msFromTime(t) : ctx->d()->callData->args[1].toNumber();
t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), sec, ms))));
- self->value.setDouble(t);
- return self->value.asReturnedValue();
+ self->date().setDouble(t);
+ return self->date().asReturnedValue();
}
ReturnedValue DatePrototype::method_setMinutes(CallContext *ctx)
{
- DateObject *self = ctx->callData->thisObject.asDateObject();
+ DateObject *self = ctx->d()->callData->thisObject.asDateObject();
if (!self)
return ctx->throwTypeError();
- double t = LocalTime(self->value.asDouble());
- double min = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN();
- double sec = (ctx->callData->argc < 2) ? SecFromTime(t) : ctx->callData->args[1].toNumber();
- double ms = (ctx->callData->argc < 3) ? msFromTime(t) : ctx->callData->args[2].toNumber();
+ double t = LocalTime(self->date().asDouble());
+ double min = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN();
+ double sec = (ctx->d()->callData->argc < 2) ? SecFromTime(t) : ctx->d()->callData->args[1].toNumber();
+ double ms = (ctx->d()->callData->argc < 3) ? msFromTime(t) : ctx->d()->callData->args[2].toNumber();
t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), min, sec, ms))));
- self->value.setDouble(t);
- return self->value.asReturnedValue();
+ self->date().setDouble(t);
+ return self->date().asReturnedValue();
}
ReturnedValue DatePrototype::method_setUTCMinutes(CallContext *ctx)
{
- DateObject *self = ctx->callData->thisObject.asDateObject();
+ DateObject *self = ctx->d()->callData->thisObject.asDateObject();
if (!self)
return ctx->throwTypeError();
- double t = self->value.asDouble();
- double min = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN();
- double sec = (ctx->callData->argc < 2) ? SecFromTime(t) : ctx->callData->args[1].toNumber();
- double ms = (ctx->callData->argc < 3) ? msFromTime(t) : ctx->callData->args[2].toNumber();
+ double t = self->date().asDouble();
+ double min = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN();
+ double sec = (ctx->d()->callData->argc < 2) ? SecFromTime(t) : ctx->d()->callData->args[1].toNumber();
+ double ms = (ctx->d()->callData->argc < 3) ? msFromTime(t) : ctx->d()->callData->args[2].toNumber();
t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), min, sec, ms))));
- self->value.setDouble(t);
- return self->value.asReturnedValue();
+ self->date().setDouble(t);
+ return self->date().asReturnedValue();
}
ReturnedValue DatePrototype::method_setHours(CallContext *ctx)
{
- DateObject *self = ctx->callData->thisObject.asDateObject();
+ DateObject *self = ctx->d()->callData->thisObject.asDateObject();
if (!self)
return ctx->throwTypeError();
- double t = LocalTime(self->value.asDouble());
- double hour = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN();
- double min = (ctx->callData->argc < 2) ? MinFromTime(t) : ctx->callData->args[1].toNumber();
- double sec = (ctx->callData->argc < 3) ? SecFromTime(t) : ctx->callData->args[2].toNumber();
- double ms = (ctx->callData->argc < 4) ? msFromTime(t) : ctx->callData->args[3].toNumber();
+ double t = LocalTime(self->date().asDouble());
+ double hour = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN();
+ double min = (ctx->d()->callData->argc < 2) ? MinFromTime(t) : ctx->d()->callData->args[1].toNumber();
+ double sec = (ctx->d()->callData->argc < 3) ? SecFromTime(t) : ctx->d()->callData->args[2].toNumber();
+ double ms = (ctx->d()->callData->argc < 4) ? msFromTime(t) : ctx->d()->callData->args[3].toNumber();
t = TimeClip(UTC(MakeDate(Day(t), MakeTime(hour, min, sec, ms))));
- self->value.setDouble(t);
- return self->value.asReturnedValue();
+ self->date().setDouble(t);
+ return self->date().asReturnedValue();
}
ReturnedValue DatePrototype::method_setUTCHours(CallContext *ctx)
{
- DateObject *self = ctx->callData->thisObject.asDateObject();
+ DateObject *self = ctx->d()->callData->thisObject.asDateObject();
if (!self)
return ctx->throwTypeError();
- double t = self->value.asDouble();
- double hour = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN();
- double min = (ctx->callData->argc < 2) ? MinFromTime(t) : ctx->callData->args[1].toNumber();
- double sec = (ctx->callData->argc < 3) ? SecFromTime(t) : ctx->callData->args[2].toNumber();
- double ms = (ctx->callData->argc < 4) ? msFromTime(t) : ctx->callData->args[3].toNumber();
+ double t = self->date().asDouble();
+ double hour = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN();
+ double min = (ctx->d()->callData->argc < 2) ? MinFromTime(t) : ctx->d()->callData->args[1].toNumber();
+ double sec = (ctx->d()->callData->argc < 3) ? SecFromTime(t) : ctx->d()->callData->args[2].toNumber();
+ double ms = (ctx->d()->callData->argc < 4) ? msFromTime(t) : ctx->d()->callData->args[3].toNumber();
t = TimeClip(UTC(MakeDate(Day(t), MakeTime(hour, min, sec, ms))));
- self->value.setDouble(t);
- return self->value.asReturnedValue();
+ self->date().setDouble(t);
+ return self->date().asReturnedValue();
}
ReturnedValue DatePrototype::method_setDate(CallContext *ctx)
{
- DateObject *self = ctx->callData->thisObject.asDateObject();
+ DateObject *self = ctx->d()->callData->thisObject.asDateObject();
if (!self)
return ctx->throwTypeError();
- double t = LocalTime(self->value.asDouble());
- double date = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN();
+ double t = LocalTime(self->date().asDouble());
+ double date = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN();
t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), date), TimeWithinDay(t))));
- self->value.setDouble(t);
- return self->value.asReturnedValue();
+ self->date().setDouble(t);
+ return self->date().asReturnedValue();
}
ReturnedValue DatePrototype::method_setUTCDate(CallContext *ctx)
{
- DateObject *self = ctx->callData->thisObject.asDateObject();
+ DateObject *self = ctx->d()->callData->thisObject.asDateObject();
if (!self)
return ctx->throwTypeError();
- double t = self->value.asDouble();
- double date = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN();
+ double t = self->date().asDouble();
+ double date = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN();
t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), date), TimeWithinDay(t))));
- self->value.setDouble(t);
- return self->value.asReturnedValue();
+ self->date().setDouble(t);
+ return self->date().asReturnedValue();
}
ReturnedValue DatePrototype::method_setMonth(CallContext *ctx)
{
- DateObject *self = ctx->callData->thisObject.asDateObject();
+ DateObject *self = ctx->d()->callData->thisObject.asDateObject();
if (!self)
return ctx->throwTypeError();
- double t = LocalTime(self->value.asDouble());
- double month = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN();
- double date = (ctx->callData->argc < 2) ? DateFromTime(t) : ctx->callData->args[1].toNumber();
+ double t = LocalTime(self->date().asDouble());
+ double month = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN();
+ double date = (ctx->d()->callData->argc < 2) ? DateFromTime(t) : ctx->d()->callData->args[1].toNumber();
t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), month, date), TimeWithinDay(t))));
- self->value.setDouble(t);
- return self->value.asReturnedValue();
+ self->date().setDouble(t);
+ return self->date().asReturnedValue();
}
ReturnedValue DatePrototype::method_setUTCMonth(CallContext *ctx)
{
- DateObject *self = ctx->callData->thisObject.asDateObject();
+ DateObject *self = ctx->d()->callData->thisObject.asDateObject();
if (!self)
return ctx->throwTypeError();
- double t = self->value.asDouble();
- double month = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN();
- double date = (ctx->callData->argc < 2) ? DateFromTime(t) : ctx->callData->args[1].toNumber();
+ double t = self->date().asDouble();
+ double month = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN();
+ double date = (ctx->d()->callData->argc < 2) ? DateFromTime(t) : ctx->d()->callData->args[1].toNumber();
t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), month, date), TimeWithinDay(t))));
- self->value.setDouble(t);
- return self->value.asReturnedValue();
+ self->date().setDouble(t);
+ return self->date().asReturnedValue();
}
ReturnedValue DatePrototype::method_setYear(CallContext *ctx)
{
- DateObject *self = ctx->callData->thisObject.asDateObject();
+ DateObject *self = ctx->d()->callData->thisObject.asDateObject();
if (!self)
return ctx->throwTypeError();
- double t = self->value.asDouble();
+ double t = self->date().asDouble();
if (std::isnan(t))
t = 0;
else
t = LocalTime(t);
- double year = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN();
+ double year = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN();
double r;
if (std::isnan(year)) {
r = qSNaN();
@@ -1207,50 +1207,50 @@ ReturnedValue DatePrototype::method_setYear(CallContext *ctx)
r = UTC(MakeDate(r, TimeWithinDay(t)));
r = TimeClip(r);
}
- self->value.setDouble(r);
- return self->value.asReturnedValue();
+ self->date().setDouble(r);
+ return self->date().asReturnedValue();
}
ReturnedValue DatePrototype::method_setUTCFullYear(CallContext *ctx)
{
- DateObject *self = ctx->callData->thisObject.asDateObject();
+ DateObject *self = ctx->d()->callData->thisObject.asDateObject();
if (!self)
return ctx->throwTypeError();
- double t = self->value.asDouble();
- double year = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN();
- double month = (ctx->callData->argc < 2) ? MonthFromTime(t) : ctx->callData->args[1].toNumber();
- double date = (ctx->callData->argc < 3) ? DateFromTime(t) : ctx->callData->args[2].toNumber();
+ double t = self->date().asDouble();
+ double year = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN();
+ double month = (ctx->d()->callData->argc < 2) ? MonthFromTime(t) : ctx->d()->callData->args[1].toNumber();
+ double date = (ctx->d()->callData->argc < 3) ? DateFromTime(t) : ctx->d()->callData->args[2].toNumber();
t = TimeClip(UTC(MakeDate(MakeDay(year, month, date), TimeWithinDay(t))));
- self->value.setDouble(t);
- return self->value.asReturnedValue();
+ self->date().setDouble(t);
+ return self->date().asReturnedValue();
}
ReturnedValue DatePrototype::method_setFullYear(CallContext *ctx)
{
- DateObject *self = ctx->callData->thisObject.asDateObject();
+ DateObject *self = ctx->d()->callData->thisObject.asDateObject();
if (!self)
return ctx->throwTypeError();
- double t = LocalTime(self->value.asDouble());
+ double t = LocalTime(self->date().asDouble());
if (std::isnan(t))
t = 0;
- double year = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN();
- double month = (ctx->callData->argc < 2) ? MonthFromTime(t) : ctx->callData->args[1].toNumber();
- double date = (ctx->callData->argc < 3) ? DateFromTime(t) : ctx->callData->args[2].toNumber();
+ double year = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN();
+ double month = (ctx->d()->callData->argc < 2) ? MonthFromTime(t) : ctx->d()->callData->args[1].toNumber();
+ double date = (ctx->d()->callData->argc < 3) ? DateFromTime(t) : ctx->d()->callData->args[2].toNumber();
t = TimeClip(UTC(MakeDate(MakeDay(year, month, date), TimeWithinDay(t))));
- self->value.setDouble(t);
- return self->value.asReturnedValue();
+ self->date().setDouble(t);
+ return self->date().asReturnedValue();
}
ReturnedValue DatePrototype::method_toUTCString(CallContext *ctx)
{
- DateObject *self = ctx->callData->thisObject.asDateObject();
+ DateObject *self = ctx->d()->callData->thisObject.asDateObject();
if (!self)
return ctx->throwTypeError();
- double t = self->value.asDouble();
- return ctx->engine->newString(ToUTCString(t))->asReturnedValue();
+ double t = self->date().asDouble();
+ return ctx->d()->engine->newString(ToUTCString(t))->asReturnedValue();
}
static void addZeroPrefixedInt(QString &str, int num, int nDigits)
@@ -1268,19 +1268,19 @@ static void addZeroPrefixedInt(QString &str, int num, int nDigits)
ReturnedValue DatePrototype::method_toISOString(CallContext *ctx)
{
- DateObject *self = ctx->callData->thisObject.asDateObject();
+ DateObject *self = ctx->d()->callData->thisObject.asDateObject();
if (!self)
return ctx->throwTypeError();
- double t = self->value.asDouble();
+ double t = self->date().asDouble();
if (!std::isfinite(t))
- return ctx->throwRangeError(ctx->callData->thisObject);
+ return ctx->throwRangeError(ctx->d()->callData->thisObject);
QString result;
int year = (int)YearFromTime(t);
if (year < 0 || year > 9999) {
if (qAbs(year) >= 1000000)
- return ctx->engine->newString(QStringLiteral("Invalid Date"))->asReturnedValue();
+ return ctx->d()->engine->newString(QStringLiteral("Invalid Date"))->asReturnedValue();
result += year < 0 ? QLatin1Char('-') : QLatin1Char('+');
year = qAbs(year);
addZeroPrefixedInt(result, year, 6);
@@ -1301,27 +1301,27 @@ ReturnedValue DatePrototype::method_toISOString(CallContext *ctx)
addZeroPrefixedInt(result, msFromTime(t), 3);
result += QLatin1Char('Z');
- return ctx->engine->newString(result)->asReturnedValue();
+ return ctx->d()->engine->newString(result)->asReturnedValue();
}
ReturnedValue DatePrototype::method_toJSON(CallContext *ctx)
{
Scope scope(ctx);
- ScopedValue O(scope, RuntimeHelpers::toObject(ctx, ValueRef(&ctx->callData->thisObject)));
+ ScopedValue O(scope, RuntimeHelpers::toObject(ctx, ValueRef(&ctx->d()->callData->thisObject)));
ScopedValue tv(scope, RuntimeHelpers::toPrimitive(O, NUMBER_HINT));
if (tv->isNumber() && !std::isfinite(tv->toNumber()))
return Encode::null();
- ScopedString s(scope, ctx->engine->newString(QStringLiteral("toISOString")));
- ScopedValue v(scope, O->objectValue()->get(s));
+ ScopedString s(scope, ctx->d()->engine->newString(QStringLiteral("toISOString")));
+ ScopedValue v(scope, O->objectValue()->get(s.getPointer()));
FunctionObject *toIso = v->asFunctionObject();
if (!toIso)
return ctx->throwTypeError();
ScopedCallData callData(scope, 0);
- callData->thisObject = ctx->callData->thisObject;
+ callData->thisObject = ctx->d()->callData->thisObject;
return toIso->call(callData);
}
diff --git a/src/qml/jsruntime/qv4dateobject_p.h b/src/qml/jsruntime/qv4dateobject_p.h
index c52e8c3ee1..6df4da45c9 100644
--- a/src/qml/jsruntime/qv4dateobject_p.h
+++ b/src/qml/jsruntime/qv4dateobject_p.h
@@ -52,27 +52,38 @@ class QDateTime;
namespace QV4 {
struct DateObject: Object {
- V4_OBJECT
+ struct Data : Object::Data {
+ Data(ExecutionEngine *engine, const ValueRef date)
+ : Object::Data(engine->dateClass)
+ {
+ value = date;
+ }
+ Data(ExecutionEngine *engine, const QDateTime &date);
+ Data(InternalClass *ic)
+ : Object::Data(ic)
+ {
+ Q_ASSERT(internalClass->vtable == staticVTable());
+ value = Primitive::fromDouble(qSNaN());
+ }
+ Value value;
+ };
+ V4_OBJECT(Object)
Q_MANAGED_TYPE(DateObject)
- Value value;
- DateObject(ExecutionEngine *engine, const ValueRef date): Object(engine->dateClass) {
- value = date;
- }
- DateObject(ExecutionEngine *engine, const QDateTime &value);
- QDateTime toQDateTime() const;
-protected:
- DateObject(InternalClass *ic): Object(ic) {
- Q_ASSERT(internalClass->vtable == staticVTable());
- value = Primitive::fromDouble(qSNaN());
- }
+ Value date() const { return d()->value; }
+ Value &date() { return d()->value; }
+ void setDate(const ValueRef date) { d()->value = date; }
+
+ QDateTime toQDateTime() const;
};
struct DateCtor: FunctionObject
{
- V4_OBJECT
- DateCtor(ExecutionContext *scope);
+ struct Data : FunctionObject::Data {
+ Data(ExecutionContext *scope);
+ };
+ V4_OBJECT(FunctionObject)
static ReturnedValue construct(Managed *, CallData *callData);
static ReturnedValue call(Managed *that, CallData *);
@@ -80,8 +91,7 @@ struct DateCtor: FunctionObject
struct DatePrototype: DateObject
{
- DatePrototype(InternalClass *ic): DateObject(ic) {}
- void init(ExecutionEngine *engine, ObjectRef ctor);
+ void init(ExecutionEngine *engine, Object *ctor);
static double getThisDate(ExecutionContext *ctx);
diff --git a/src/qml/jsruntime/qv4debugging.cpp b/src/qml/jsruntime/qv4debugging.cpp
index 06c6dbb4d9..04422b9f5e 100644
--- a/src/qml/jsruntime/qv4debugging.cpp
+++ b/src/qml/jsruntime/qv4debugging.cpp
@@ -210,7 +210,7 @@ Debugger::ExecutionState Debugger::currentExecutionState() const
{
ExecutionState state;
state.fileName = getFunction()->sourceFile();
- state.lineNumber = engine()->currentContext()->lineNumber;
+ state.lineNumber = engine()->currentContext()->d()->lineNumber;
return state;
}
@@ -224,12 +224,12 @@ static inline CallContext *findContext(ExecutionContext *ctxt, int frame)
{
while (ctxt) {
CallContext *cCtxt = ctxt->asCallContext();
- if (cCtxt && cCtxt->function) {
+ if (cCtxt && cCtxt->d()->function) {
if (frame < 1)
return cCtxt;
--frame;
}
- ctxt = ctxt->parent;
+ ctxt = ctxt->d()->parent;
}
return 0;
@@ -238,7 +238,7 @@ static inline CallContext *findContext(ExecutionContext *ctxt, int frame)
static inline CallContext *findScope(ExecutionContext *ctxt, int scope)
{
for (; scope > 0 && ctxt; --scope)
- ctxt = ctxt->outer;
+ ctxt = ctxt->d()->outer;
return ctxt ? ctxt->asCallContext() : 0;
}
@@ -327,7 +327,7 @@ void Debugger::collectLocalsInContext(Collector *collector, int frameNr, int sco
QString qName;
if (String *name = ctxt->variables()[i])
qName = name->toQString();
- v = ctxt->locals[i];
+ v = ctxt->d()->locals[i];
collector->collect(qName, v);
}
}
@@ -367,16 +367,16 @@ bool Debugger::collectThisInContext(Debugger::Collector *collector, int frame)
ExecutionContext *ctxt = findContext(engine->currentContext(), frameNr);
while (ctxt) {
if (CallContext *cCtxt = ctxt->asCallContext())
- if (cCtxt->activation)
+ if (cCtxt->d()->activation)
break;
- ctxt = ctxt->outer;
+ ctxt = ctxt->d()->outer;
}
if (!ctxt)
return false;
Scope scope(engine);
- ScopedObject o(scope, ctxt->asCallContext()->activation);
+ ScopedObject o(scope, ctxt->asCallContext()->d()->activation);
collector->collect(o);
return true;
}
@@ -434,12 +434,12 @@ QVector<ExecutionContext::ContextType> Debugger::getScopeTypes(int frame) const
return types;
CallContext *sctxt = findContext(m_engine->currentContext(), frame);
- if (!sctxt || sctxt->type < ExecutionContext::Type_SimpleCallContext)
+ if (!sctxt || sctxt->d()->type < ExecutionContext::Type_SimpleCallContext)
return types;
CallContext *ctxt = static_cast<CallContext *>(sctxt);
- for (ExecutionContext *it = ctxt; it; it = it->outer)
- types.append(it->type);
+ for (ExecutionContext *it = ctxt; it; it = it->d()->outer)
+ types.append(it->d()->type);
return types;
}
@@ -450,7 +450,7 @@ void Debugger::maybeBreakAtInstruction()
return;
QMutexLocker locker(&m_lock);
- int lineNumber = engine()->currentContext()->lineNumber;
+ int lineNumber = engine()->currentContext()->d()->lineNumber;
if (m_gatherSources) {
m_gatherSources->run();
@@ -495,7 +495,7 @@ void Debugger::leavingFunction(const ReturnedValue &retVal)
QMutexLocker locker(&m_lock);
if (m_stepping != NotStepping && m_currentContext == m_engine->currentContext()) {
- m_currentContext = m_engine->currentContext()->parent;
+ m_currentContext = m_engine->currentContext()->d()->parent;
m_stepping = StepOver;
m_returnedValue = retVal;
}
@@ -517,10 +517,10 @@ Function *Debugger::getFunction() const
{
ExecutionContext *context = m_engine->currentContext();
if (CallContext *callCtx = context->asCallContext())
- return callCtx->function->function;
+ return callCtx->d()->function->function();
else {
- Q_ASSERT(context->type == QV4::ExecutionContext::Type_GlobalContext);
- return context->engine->globalCode;
+ Q_ASSERT(context->d()->type == QV4::ExecutionContext::Type_GlobalContext);
+ return context->d()->engine->globalCode;
}
}
@@ -726,7 +726,7 @@ void Debugger::Collector::collect(const QString &name, const ScopedValue &value)
}
}
-void Debugger::Collector::collect(const ObjectRef object)
+void Debugger::Collector::collect(Object *object)
{
bool property = true;
qSwap(property, m_isProperty);
diff --git a/src/qml/jsruntime/qv4debugging_p.h b/src/qml/jsruntime/qv4debugging_p.h
index 47a7d77b28..f834b8d15f 100644
--- a/src/qml/jsruntime/qv4debugging_p.h
+++ b/src/qml/jsruntime/qv4debugging_p.h
@@ -105,7 +105,7 @@ public:
virtual ~Collector();
void collect(const QString &name, const ScopedValue &value);
- void collect(const ObjectRef object);
+ void collect(Object *object);
protected:
virtual void addUndefined(const QString &name) = 0;
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 72be889e72..7be518916d 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -71,6 +71,7 @@
#include "qv4memberdata_p.h"
#include <QtCore/QTextStream>
+#include <QDateTime>
#ifdef V4_ENABLE_JIT
#include "qv4isel_masm_p.h"
@@ -258,13 +259,13 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
memberDataClass = InternalClass::create(this, MemberData::staticVTable(), 0);
- ObjectPrototype *objectPrototype = new (memoryManager) ObjectPrototype(InternalClass::create(this, ObjectPrototype::staticVTable(), 0));
+ ScopedObject objectPrototype(scope, memoryManager->alloc<ObjectPrototype>(InternalClass::create(this, ObjectPrototype::staticVTable(), 0)));
objectClass = InternalClass::create(this, Object::staticVTable(), objectPrototype);
Q_ASSERT(objectClass->vtable == Object::staticVTable());
arrayClass = InternalClass::create(this, ArrayObject::staticVTable(), objectPrototype);
arrayClass = arrayClass->addMember(id_length, Attr_NotConfigurable|Attr_NotEnumerable);
- ArrayPrototype *arrayPrototype = new (memoryManager) ArrayPrototype(arrayClass);
+ ScopedObject arrayPrototype(scope, memoryManager->alloc<ArrayPrototype>(arrayClass));
arrayClass = arrayClass->changePrototype(arrayPrototype);
simpleArrayDataClass = InternalClass::create(this, SimpleArrayData::staticVTable(), 0);
@@ -279,100 +280,100 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
initRootContext();
- StringPrototype *stringPrototype = new (memoryManager) StringPrototype(InternalClass::create(this, StringPrototype::staticVTable(), objectPrototype));
+ ScopedObject stringPrototype(scope, memoryManager->alloc<StringPrototype>(InternalClass::create(this, StringPrototype::staticVTable(), objectPrototype)));
stringObjectClass = InternalClass::create(this, String::staticVTable(), stringPrototype);
- NumberPrototype *numberPrototype = new (memoryManager) NumberPrototype(InternalClass::create(this, NumberPrototype::staticVTable(), objectPrototype));
+ ScopedObject numberPrototype(scope, memoryManager->alloc<NumberPrototype>(InternalClass::create(this, NumberPrototype::staticVTable(), objectPrototype)));
numberClass = InternalClass::create(this, NumberObject::staticVTable(), numberPrototype);
- BooleanPrototype *booleanPrototype = new (memoryManager) BooleanPrototype(InternalClass::create(this, BooleanPrototype::staticVTable(), objectPrototype));
+ ScopedObject booleanPrototype(scope, memoryManager->alloc<BooleanPrototype>(InternalClass::create(this, BooleanPrototype::staticVTable(), objectPrototype)));
booleanClass = InternalClass::create(this, BooleanObject::staticVTable(), booleanPrototype);
- DatePrototype *datePrototype = new (memoryManager) DatePrototype(InternalClass::create(this, DatePrototype::staticVTable(), objectPrototype));
+ ScopedObject datePrototype(scope, memoryManager->alloc<DatePrototype>(InternalClass::create(this, DatePrototype::staticVTable(), objectPrototype)));
dateClass = InternalClass::create(this, DateObject::staticVTable(), datePrototype);
InternalClass *functionProtoClass = InternalClass::create(this, FunctionObject::staticVTable(), objectPrototype);
uint index;
functionProtoClass = functionProtoClass->addMember(id_prototype, Attr_NotEnumerable, &index);
Q_ASSERT(index == FunctionObject::Index_Prototype);
- FunctionPrototype *functionPrototype = new (memoryManager) FunctionPrototype(functionProtoClass);
+ ScopedObject functionPrototype(scope, memoryManager->alloc<FunctionPrototype>(functionProtoClass));
functionClass = InternalClass::create(this, FunctionObject::staticVTable(), functionPrototype);
functionClass = functionClass->addMember(id_prototype, Attr_NotEnumerable|Attr_NotConfigurable, &index);
Q_ASSERT(index == FunctionObject::Index_Prototype);
protoClass = objectClass->addMember(id_constructor, Attr_NotEnumerable, &index);
Q_ASSERT(index == FunctionObject::Index_ProtoConstructor);
- RegExpPrototype *regExpPrototype = new (memoryManager) RegExpPrototype(InternalClass::create(this, RegExpPrototype::staticVTable(), objectPrototype));
- regExpClass = InternalClass::create(this, RegExpObject::staticVTable(), regExpPrototype);
+ Scoped<RegExpPrototype> regExpPrototype(scope, memoryManager->alloc<RegExpPrototype>(InternalClass::create(this, RegExpPrototype::staticVTable(), objectPrototype)));
+ regExpClass = InternalClass::create(this, RegExpObject::staticVTable(), regExpPrototype.getPointer());
regExpExecArrayClass = arrayClass->addMember(id_index, Attr_Data, &index);
Q_ASSERT(index == RegExpObject::Index_ArrayIndex);
regExpExecArrayClass = regExpExecArrayClass->addMember(id_input, Attr_Data, &index);
Q_ASSERT(index == RegExpObject::Index_ArrayInput);
- ErrorPrototype *errorPrototype = new (memoryManager) ErrorPrototype(InternalClass::create(this, ErrorObject::staticVTable(), objectPrototype));
+ ScopedObject errorPrototype(scope, memoryManager->alloc<ErrorPrototype>(InternalClass::create(this, ErrorObject::staticVTable(), objectPrototype)));
errorClass = InternalClass::create(this, ErrorObject::staticVTable(), errorPrototype);
- EvalErrorPrototype *evalErrorPrototype = new (memoryManager) EvalErrorPrototype(errorClass);
+ ScopedObject evalErrorPrototype(scope, memoryManager->alloc<EvalErrorPrototype>(errorClass));
evalErrorClass = InternalClass::create(this, EvalErrorObject::staticVTable(), evalErrorPrototype);
- RangeErrorPrototype *rangeErrorPrototype = new (memoryManager) RangeErrorPrototype(errorClass);
+ ScopedObject rangeErrorPrototype(scope, memoryManager->alloc<RangeErrorPrototype>(errorClass));
rangeErrorClass = InternalClass::create(this, RangeErrorObject::staticVTable(), rangeErrorPrototype);
- ReferenceErrorPrototype *referenceErrorPrototype = new (memoryManager) ReferenceErrorPrototype(errorClass);
+ ScopedObject referenceErrorPrototype(scope, memoryManager->alloc<ReferenceErrorPrototype>(errorClass));
referenceErrorClass = InternalClass::create(this, ReferenceErrorObject::staticVTable(), referenceErrorPrototype);
- SyntaxErrorPrototype *syntaxErrorPrototype = new (memoryManager) SyntaxErrorPrototype(errorClass);
+ ScopedObject syntaxErrorPrototype(scope, memoryManager->alloc<SyntaxErrorPrototype>(errorClass));
syntaxErrorClass = InternalClass::create(this, SyntaxErrorObject::staticVTable(), syntaxErrorPrototype);
- TypeErrorPrototype *typeErrorPrototype = new (memoryManager) TypeErrorPrototype(errorClass);
+ ScopedObject typeErrorPrototype(scope, memoryManager->alloc<TypeErrorPrototype>(errorClass));
typeErrorClass = InternalClass::create(this, TypeErrorObject::staticVTable(), typeErrorPrototype);
- URIErrorPrototype *uRIErrorPrototype = new (memoryManager) URIErrorPrototype(errorClass);
+ ScopedObject uRIErrorPrototype(scope, memoryManager->alloc<URIErrorPrototype>(errorClass));
uriErrorClass = InternalClass::create(this, URIErrorObject::staticVTable(), uRIErrorPrototype);
- VariantPrototype *variantPrototype = new (memoryManager) VariantPrototype(InternalClass::create(this, VariantPrototype::staticVTable(), objectPrototype));
+ ScopedObject variantPrototype(scope, memoryManager->alloc<VariantPrototype>(InternalClass::create(this, VariantPrototype::staticVTable(), objectPrototype)));
variantClass = InternalClass::create(this, VariantObject::staticVTable(), variantPrototype);
Q_ASSERT(variantClass->prototype == variantPrototype);
- Q_ASSERT(variantPrototype->internalClass->prototype == objectPrototype);
-
- sequencePrototype = new (memoryManager) SequencePrototype(arrayClass);
-
- objectCtor = new (memoryManager) ObjectCtor(rootContext);
- stringCtor = new (memoryManager) StringCtor(rootContext);
- numberCtor = new (memoryManager) NumberCtor(rootContext);
- booleanCtor = new (memoryManager) BooleanCtor(rootContext);
- arrayCtor = new (memoryManager) ArrayCtor(rootContext);
- functionCtor = new (memoryManager) FunctionCtor(rootContext);
- dateCtor = new (memoryManager) DateCtor(rootContext);
- regExpCtor = new (memoryManager) RegExpCtor(rootContext);
- errorCtor = new (memoryManager) ErrorCtor(rootContext);
- evalErrorCtor = new (memoryManager) EvalErrorCtor(rootContext);
- rangeErrorCtor = new (memoryManager) RangeErrorCtor(rootContext);
- referenceErrorCtor = new (memoryManager) ReferenceErrorCtor(rootContext);
- syntaxErrorCtor = new (memoryManager) SyntaxErrorCtor(rootContext);
- typeErrorCtor = new (memoryManager) TypeErrorCtor(rootContext);
- uRIErrorCtor = new (memoryManager) URIErrorCtor(rootContext);
-
- objectPrototype->init(this, objectCtor);
- stringPrototype->init(this, stringCtor);
- numberPrototype->init(this, numberCtor);
- booleanPrototype->init(this, booleanCtor);
- arrayPrototype->init(this, arrayCtor);
- datePrototype->init(this, dateCtor);
- functionPrototype->init(this, functionCtor);
- regExpPrototype->init(this, regExpCtor);
- errorPrototype->init(this, errorCtor);
- evalErrorPrototype->init(this, evalErrorCtor);
- rangeErrorPrototype->init(this, rangeErrorCtor);
- referenceErrorPrototype->init(this, referenceErrorCtor);
- syntaxErrorPrototype->init(this, syntaxErrorCtor);
- typeErrorPrototype->init(this, typeErrorCtor);
- uRIErrorPrototype->init(this, uRIErrorCtor);
-
- variantPrototype->init();
+ Q_ASSERT(variantPrototype->internalClass()->prototype == objectPrototype);
+
+ sequencePrototype = ScopedValue(scope, memoryManager->alloc<SequencePrototype>(arrayClass));
+
+ objectCtor = memoryManager->alloc<ObjectCtor>(rootContext);
+ stringCtor = memoryManager->alloc<StringCtor>(rootContext);
+ numberCtor = memoryManager->alloc<NumberCtor>(rootContext);
+ booleanCtor = memoryManager->alloc<BooleanCtor>(rootContext);
+ arrayCtor = memoryManager->alloc<ArrayCtor>(rootContext);
+ functionCtor = memoryManager->alloc<FunctionCtor>(rootContext);
+ dateCtor = memoryManager->alloc<DateCtor>(rootContext);
+ regExpCtor = memoryManager->alloc<RegExpCtor>(rootContext);
+ errorCtor = memoryManager->alloc<ErrorCtor>(rootContext);
+ evalErrorCtor = memoryManager->alloc<EvalErrorCtor>(rootContext);
+ rangeErrorCtor = memoryManager->alloc<RangeErrorCtor>(rootContext);
+ referenceErrorCtor = memoryManager->alloc<ReferenceErrorCtor>(rootContext);
+ syntaxErrorCtor = memoryManager->alloc<SyntaxErrorCtor>(rootContext);
+ typeErrorCtor = memoryManager->alloc<TypeErrorCtor>(rootContext);
+ uRIErrorCtor = memoryManager->alloc<URIErrorCtor>(rootContext);
+
+ static_cast<ObjectPrototype *>(objectPrototype.getPointer())->init(this, objectCtor.asObject());
+ static_cast<StringPrototype *>(stringPrototype.getPointer())->init(this, stringCtor.asObject());
+ static_cast<NumberPrototype *>(numberPrototype.getPointer())->init(this, numberCtor.asObject());
+ static_cast<BooleanPrototype *>(booleanPrototype.getPointer())->init(this, booleanCtor.asObject());
+ static_cast<ArrayPrototype *>(arrayPrototype.getPointer())->init(this, arrayCtor.asObject());
+ static_cast<DatePrototype *>(datePrototype.getPointer())->init(this, dateCtor.asObject());
+ static_cast<FunctionPrototype *>(functionPrototype.getPointer())->init(this, functionCtor.asObject());
+ static_cast<RegExpPrototype *>(regExpPrototype.getPointer())->init(this, regExpCtor.asObject());
+ static_cast<ErrorPrototype *>(errorPrototype.getPointer())->init(this, errorCtor.asObject());
+ static_cast<EvalErrorPrototype *>(evalErrorPrototype.getPointer())->init(this, evalErrorCtor.asObject());
+ static_cast<RangeErrorPrototype *>(rangeErrorPrototype.getPointer())->init(this, rangeErrorCtor.asObject());
+ static_cast<ReferenceErrorPrototype *>(referenceErrorPrototype.getPointer())->init(this, referenceErrorCtor.asObject());
+ static_cast<SyntaxErrorPrototype *>(syntaxErrorPrototype.getPointer())->init(this, syntaxErrorCtor.asObject());
+ static_cast<TypeErrorPrototype *>(typeErrorPrototype.getPointer())->init(this, typeErrorCtor.asObject());
+ static_cast<URIErrorPrototype *>(uRIErrorPrototype.getPointer())->init(this, uRIErrorCtor.asObject());
+
+ static_cast<VariantPrototype *>(variantPrototype.getPointer())->init();
static_cast<SequencePrototype *>(sequencePrototype.managed())->init();
//
// set up the global object
//
globalObject = newObject()->getPointer();
- rootContext->global = globalObject;
- rootContext->callData->thisObject = globalObject;
- Q_ASSERT(globalObject->internalClass->vtable);
+ rootContext->d()->global = globalObject;
+ rootContext->d()->callData->thisObject = globalObject;
+ Q_ASSERT(globalObject->internalClass()->vtable);
globalObject->defineDefaultProperty(QStringLiteral("Object"), objectCtor);
globalObject->defineDefaultProperty(QStringLiteral("String"), stringCtor);
@@ -390,14 +391,15 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
globalObject->defineDefaultProperty(QStringLiteral("TypeError"), typeErrorCtor);
globalObject->defineDefaultProperty(QStringLiteral("URIError"), uRIErrorCtor);
ScopedObject o(scope);
- globalObject->defineDefaultProperty(QStringLiteral("Math"), (o = new (memoryManager) MathObject(QV4::InternalClass::create(this, MathObject::staticVTable(), objectPrototype))));
- globalObject->defineDefaultProperty(QStringLiteral("JSON"), (o = new (memoryManager) JsonObject(QV4::InternalClass::create(this, JsonObject::staticVTable(), objectPrototype))));
+ globalObject->defineDefaultProperty(QStringLiteral("Math"), (o = memoryManager->alloc<MathObject>(QV4::InternalClass::create(this, MathObject::staticVTable(), objectPrototype))));
+ globalObject->defineDefaultProperty(QStringLiteral("JSON"), (o = memoryManager->alloc<JsonObject>(QV4::InternalClass::create(this, JsonObject::staticVTable(), objectPrototype))));
globalObject->defineReadonlyProperty(QStringLiteral("undefined"), Primitive::undefinedValue());
globalObject->defineReadonlyProperty(QStringLiteral("NaN"), Primitive::fromDouble(std::numeric_limits<double>::quiet_NaN()));
globalObject->defineReadonlyProperty(QStringLiteral("Infinity"), Primitive::fromDouble(Q_INFINITY));
- evalFunction = new (memoryManager) EvalFunction(rootContext);
+
+ evalFunction = Scoped<EvalFunction>(scope, memoryManager->alloc<EvalFunction>(rootContext));
globalObject->defineDefaultProperty(QStringLiteral("eval"), (o = evalFunction));
globalObject->defineDefaultProperty(QStringLiteral("parseInt"), GlobalFunctions::method_parseInt, 2);
@@ -412,13 +414,15 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
globalObject->defineDefaultProperty(QStringLiteral("unescape"), GlobalFunctions::method_unescape, 1);
Scoped<String> name(scope, newString(QStringLiteral("thrower")));
- thrower = newBuiltinFunction(rootContext, name, throwTypeError)->getPointer();
+ thrower = ScopedFunctionObject(scope, BuiltinFunction::create(rootContext, name.getPointer(), throwTypeError)).getPointer();
}
ExecutionEngine::~ExecutionEngine()
{
delete debugger;
+ debugger = 0;
delete profiler;
+ profiler = 0;
delete m_multiplyWrappedQObjects;
m_multiplyWrappedQObjects = 0;
delete identifierTable;
@@ -451,18 +455,20 @@ void ExecutionEngine::enableDebugger()
void ExecutionEngine::enableProfiler()
{
Q_ASSERT(!profiler);
- profiler = new QV4::Profiling::Profiler();
+ profiler = new QV4::Profiling::Profiler(this);
}
void ExecutionEngine::initRootContext()
{
- rootContext = static_cast<GlobalContext *>(memoryManager->allocManaged(sizeof(GlobalContext) + sizeof(CallData)));
- new (rootContext) GlobalContext(this);
- rootContext->callData = reinterpret_cast<CallData *>(rootContext + 1);
- rootContext->callData->tag = QV4::Value::_Integer_Type;
- rootContext->callData->argc = 0;
- rootContext->callData->thisObject = globalObject;
- rootContext->callData->args[0] = Encode::undefined();
+ GlobalContext *r = static_cast<GlobalContext*>(memoryManager->allocManaged(sizeof(GlobalContext::Data) + sizeof(CallData)));
+ new (r->d()) GlobalContext::Data(this);
+ r->d()->callData = reinterpret_cast<CallData *>(r->d() + 1);
+ r->d()->callData->tag = QV4::Value::_Integer_Type;
+ r->d()->callData->argc = 0;
+ r->d()->callData->thisObject = globalObject;
+ r->d()->callData->args[0] = Encode::undefined();
+
+ rootContext = r;
}
InternalClass *ExecutionEngine::newClass(const InternalClass &other)
@@ -472,43 +478,32 @@ InternalClass *ExecutionEngine::newClass(const InternalClass &other)
ExecutionContext *ExecutionEngine::pushGlobalContext()
{
- GlobalContext *g = new (memoryManager) GlobalContext(this);
- g->callData = rootContext->callData;
+ GlobalContext *g = memoryManager->alloc<GlobalContext>(this);
+ g->d()->callData = rootContext->d()->callData;
Q_ASSERT(currentContext() == g);
return g;
}
-Returned<FunctionObject> *ExecutionEngine::newBuiltinFunction(ExecutionContext *scope, const StringRef name, ReturnedValue (*code)(CallContext *))
-{
- BuiltinFunction *f = new (memoryManager) BuiltinFunction(scope, name, code);
- return f->asReturned<FunctionObject>();
-}
-
-Returned<BoundFunction> *ExecutionEngine::newBoundFunction(ExecutionContext *scope, FunctionObjectRef target, const ValueRef boundThis, const QVector<Value> &boundArgs)
-{
- Q_ASSERT(target);
-
- BoundFunction *f = new (memoryManager) BoundFunction(scope, target, boundThis, boundArgs);
- return f->asReturned<BoundFunction>();
-}
-
Returned<Object> *ExecutionEngine::newObject()
{
- Object *object = new (memoryManager) Object(this);
+ Scope scope(this);
+ ScopedObject object(scope, memoryManager->alloc<Object>(this));
return object->asReturned<Object>();
}
Returned<Object> *ExecutionEngine::newObject(InternalClass *internalClass)
{
- Object *object = new (memoryManager) Object(internalClass);
+ Scope scope(this);
+ ScopedObject object(scope, memoryManager->alloc<Object>(internalClass));
return object->asReturned<Object>();
}
Returned<String> *ExecutionEngine::newString(const QString &s)
{
- return (new (memoryManager) String(this, s))->asReturned<String>();
+ Scope scope(this);
+ return ScopedString(scope, memoryManager->alloc<String>(this, s))->asReturned<String>();
}
String *ExecutionEngine::newIdentifier(const QString &text)
@@ -518,29 +513,31 @@ String *ExecutionEngine::newIdentifier(const QString &text)
Returned<Object> *ExecutionEngine::newStringObject(const ValueRef value)
{
- StringObject *object = new (memoryManager) StringObject(this, value);
+ Scope scope(this);
+ Scoped<StringObject> object(scope, memoryManager->alloc<StringObject>(this, value));
return object->asReturned<Object>();
}
Returned<Object> *ExecutionEngine::newNumberObject(const ValueRef value)
{
- NumberObject *object = new (memoryManager) NumberObject(this, value);
+ Scope scope(this);
+ Scoped<NumberObject> object(scope, memoryManager->alloc<NumberObject>(this, value));
return object->asReturned<Object>();
}
Returned<Object> *ExecutionEngine::newBooleanObject(const ValueRef value)
{
- Object *object = new (memoryManager) BooleanObject(this, value);
+ Scope scope(this);
+ ScopedObject object(scope, memoryManager->alloc<BooleanObject>(this, value));
return object->asReturned<Object>();
}
Returned<ArrayObject> *ExecutionEngine::newArrayObject(int count)
{
- ArrayObject *object = new (memoryManager) ArrayObject(this);
+ Scope scope(this);
+ ScopedArrayObject object(scope, memoryManager->alloc<ArrayObject>(this));
if (count) {
- Scope scope(this);
- ScopedValue protectArray(scope, object);
if (count < 0x1000)
object->arrayReserve(count);
object->setArrayLengthUnchecked(count);
@@ -550,26 +547,30 @@ Returned<ArrayObject> *ExecutionEngine::newArrayObject(int count)
Returned<ArrayObject> *ExecutionEngine::newArrayObject(const QStringList &list)
{
- ArrayObject *object = new (memoryManager) ArrayObject(this, list);
+ Scope scope(this);
+ ScopedArrayObject object(scope, memoryManager->alloc<ArrayObject>(this, list));
return object->asReturned<ArrayObject>();
}
Returned<ArrayObject> *ExecutionEngine::newArrayObject(InternalClass *ic)
{
- ArrayObject *object = new (memoryManager) ArrayObject(ic);
+ Scope scope(this);
+ ScopedArrayObject object(scope, memoryManager->alloc<ArrayObject>(ic));
return object->asReturned<ArrayObject>();
}
Returned<DateObject> *ExecutionEngine::newDateObject(const ValueRef value)
{
- DateObject *object = new (memoryManager) DateObject(this, value);
+ Scope scope(this);
+ Scoped<DateObject> object(scope, memoryManager->alloc<DateObject>(this, value));
return object->asReturned<DateObject>();
}
Returned<DateObject> *ExecutionEngine::newDateObject(const QDateTime &dt)
{
- DateObject *object = new (memoryManager) DateObject(this, dt);
+ Scope scope(this);
+ Scoped<DateObject> object(scope, memoryManager->alloc<DateObject>(this, dt));
return object->asReturned<DateObject>();
}
@@ -588,21 +589,24 @@ Returned<RegExpObject> *ExecutionEngine::newRegExpObject(const QString &pattern,
return newRegExpObject(re, global);
}
-Returned<RegExpObject> *ExecutionEngine::newRegExpObject(RegExpRef re, bool global)
+Returned<RegExpObject> *ExecutionEngine::newRegExpObject(RegExp *re, bool global)
{
- RegExpObject *object = new (memoryManager) RegExpObject(this, re, global);
+ Scope scope(this);
+ Scoped<RegExpObject> object(scope, memoryManager->alloc<RegExpObject>(this, re, global));
return object->asReturned<RegExpObject>();
}
Returned<RegExpObject> *ExecutionEngine::newRegExpObject(const QRegExp &re)
{
- RegExpObject *object = new (memoryManager) RegExpObject(this, re);
+ Scope scope(this);
+ Scoped<RegExpObject> object(scope, memoryManager->alloc<RegExpObject>(this, re));
return object->asReturned<RegExpObject>();
}
Returned<Object> *ExecutionEngine::newErrorObject(const ValueRef value)
{
- ErrorObject *object = new (memoryManager) ErrorObject(errorClass, value);
+ Scope scope(this);
+ ScopedObject object(scope, memoryManager->alloc<ErrorObject>(errorClass, value));
return object->asReturned<Object>();
}
@@ -610,57 +614,65 @@ Returned<Object> *ExecutionEngine::newSyntaxErrorObject(const QString &message)
{
Scope scope(this);
ScopedString s(scope, newString(message));
- Object *error = new (memoryManager) SyntaxErrorObject(this, s);
+ ScopedObject error(scope, memoryManager->alloc<SyntaxErrorObject>(this, s));
return error->asReturned<Object>();
}
Returned<Object> *ExecutionEngine::newSyntaxErrorObject(const QString &message, const QString &fileName, int line, int column)
{
- Object *error = new (memoryManager) SyntaxErrorObject(this, message, fileName, line, column);
+ Scope scope(this);
+ ScopedObject error(scope, memoryManager->alloc<SyntaxErrorObject>(this, message, fileName, line, column));
return error->asReturned<Object>();
}
Returned<Object> *ExecutionEngine::newReferenceErrorObject(const QString &message)
{
- Object *o = new (memoryManager) ReferenceErrorObject(this, message);
+ Scope scope(this);
+ ScopedObject o(scope, memoryManager->alloc<ReferenceErrorObject>(this, message));
return o->asReturned<Object>();
}
Returned<Object> *ExecutionEngine::newReferenceErrorObject(const QString &message, const QString &fileName, int lineNumber, int columnNumber)
{
- Object *o = new (memoryManager) ReferenceErrorObject(this, message, fileName, lineNumber, columnNumber);
+ Scope scope(this);
+ ScopedObject o(scope, memoryManager->alloc<ReferenceErrorObject>(this, message, fileName, lineNumber, columnNumber));
return o->asReturned<Object>();
}
Returned<Object> *ExecutionEngine::newTypeErrorObject(const QString &message)
{
- Object *o = new (memoryManager) TypeErrorObject(this, message);
+ Scope scope(this);
+ ScopedObject o(scope, memoryManager->alloc<TypeErrorObject>(this, message));
return o->asReturned<Object>();
}
Returned<Object> *ExecutionEngine::newRangeErrorObject(const QString &message)
{
- Object *o = new (memoryManager) RangeErrorObject(this, message);
+ Scope scope(this);
+ ScopedObject o(scope, memoryManager->alloc<RangeErrorObject>(this, message));
return o->asReturned<Object>();
}
Returned<Object> *ExecutionEngine::newURIErrorObject(const ValueRef message)
{
- Object *o = new (memoryManager) URIErrorObject(this, message);
+ Scope scope(this);
+ ScopedObject o(scope, memoryManager->alloc<URIErrorObject>(this, message));
return o->asReturned<Object>();
}
Returned<Object> *ExecutionEngine::newVariantObject(const QVariant &v)
{
- Object *o = new (memoryManager) VariantObject(this, v);
+ Scope scope(this);
+ ScopedObject o(scope, memoryManager->alloc<VariantObject>(this, v));
return o->asReturned<Object>();
}
-Returned<Object> *ExecutionEngine::newForEachIteratorObject(ExecutionContext *ctx, const ObjectRef o)
+Returned<Object> *ExecutionEngine::newForEachIteratorObject(ExecutionContext *ctx, Object *o)
{
- Object *obj = new (memoryManager) ForEachIteratorObject(ctx, o);
+ Scope scope(this);
+ ScopedObject obj(scope, memoryManager->alloc<ForEachIteratorObject>(ctx, o));
return obj->asReturned<Object>();
}
@@ -668,20 +680,20 @@ Returned<Object> *ExecutionEngine::qmlContextObject() const
{
ExecutionContext *ctx = currentContext();
- if (ctx->type == QV4::ExecutionContext::Type_SimpleCallContext && !ctx->outer)
- ctx = ctx->parent;
+ if (ctx->d()->type == QV4::ExecutionContext::Type_SimpleCallContext && !ctx->d()->outer)
+ ctx = ctx->d()->parent;
- if (!ctx->outer)
+ if (!ctx->d()->outer)
return 0;
- while (ctx->outer && ctx->outer->type != ExecutionContext::Type_GlobalContext)
- ctx = ctx->outer;
+ while (ctx->d()->outer && ctx->d()->outer->d()->type != ExecutionContext::Type_GlobalContext)
+ ctx = ctx->d()->outer;
Q_ASSERT(ctx);
- if (ctx->type != ExecutionContext::Type_QmlContext)
+ if (ctx->d()->type != ExecutionContext::Type_QmlContext)
return 0;
- return static_cast<CallContext *>(ctx)->activation->asReturned<Object>();
+ return static_cast<CallContext *>(ctx)->d()->activation->asReturned<Object>();
}
QVector<StackFrame> ExecutionEngine::stackTrace(int frameLimit) const
@@ -693,30 +705,30 @@ QVector<StackFrame> ExecutionEngine::stackTrace(int frameLimit) const
QV4::ExecutionContext *c = currentContext();
while (c && frameLimit) {
CallContext *callCtx = c->asCallContext();
- if (callCtx && callCtx->function) {
+ if (callCtx && callCtx->d()->function) {
StackFrame frame;
- if (callCtx->function->function)
- frame.source = callCtx->function->function->sourceFile();
- name = callCtx->function->name();
+ if (callCtx->d()->function->function())
+ frame.source = callCtx->d()->function->function()->sourceFile();
+ name = callCtx->d()->function->name();
frame.function = name->toQString();
frame.line = -1;
frame.column = -1;
- if (callCtx->function->function)
+ if (callCtx->d()->function->function())
// line numbers can be negative for places where you can't set a real breakpoint
- frame.line = qAbs(callCtx->lineNumber);
+ frame.line = qAbs(callCtx->d()->lineNumber);
stack.append(frame);
--frameLimit;
}
- c = c->parent;
+ c = c->d()->parent;
}
if (frameLimit && globalCode) {
StackFrame frame;
frame.source = globalCode->sourceFile();
frame.function = globalCode->name()->toQString();
- frame.line = rootContext->lineNumber;
+ frame.line = rootContext->d()->lineNumber;
frame.column = -1;
@@ -750,8 +762,8 @@ static inline char *v4StackTrace(const ExecutionContext *context)
QString result;
QTextStream str(&result);
str << "stack=[";
- if (context && context->engine) {
- const QVector<StackFrame> stackTrace = context->engine->stackTrace(20);
+ if (context && context->d()->engine) {
+ const QVector<StackFrame> stackTrace = context->d()->engine->stackTrace(20);
for (int i = 0; i < stackTrace.size(); ++i) {
if (i)
str << ',';
@@ -781,12 +793,12 @@ QUrl ExecutionEngine::resolvedUrl(const QString &file)
QV4::ExecutionContext *c = currentContext();
while (c) {
CallContext *callCtx = c->asCallContext();
- if (callCtx && callCtx->function) {
- if (callCtx->function->function)
- base.setUrl(callCtx->function->function->sourceFile());
+ if (callCtx && callCtx->d()->function) {
+ if (callCtx->d()->function->function())
+ base.setUrl(callCtx->d()->function->function()->sourceFile());
break;
}
- c = c->parent;
+ c = c->d()->parent;
}
if (base.isEmpty() && globalCode)
@@ -817,8 +829,8 @@ void ExecutionEngine::requireArgumentsAccessors(int n)
delete [] oldAccessors;
}
for (int i = oldSize; i < nArgumentsAccessors; ++i) {
- argumentsAccessors[i].value = Value::fromManaged(new (memoryManager) ArgumentsGetterFunction(rootContext, i));
- argumentsAccessors[i].set = Value::fromManaged(new (memoryManager) ArgumentsSetterFunction(rootContext, i));
+ argumentsAccessors[i].value = ScopedValue(scope, memoryManager->alloc<ArgumentsGetterFunction>(rootContext, i));
+ argumentsAccessors[i].set = ScopedValue(scope, memoryManager->alloc<ArgumentsSetterFunction>(rootContext, i));
}
}
}
@@ -839,12 +851,12 @@ void ExecutionEngine::markObjects()
ExecutionContext *c = currentContext();
while (c) {
- Q_ASSERT(c->inUse);
- if (!c->markBit) {
- c->markBit = 1;
+ Q_ASSERT(c->inUse());
+ if (!c->markBit()) {
+ c->d()->markBit = 1;
c->markObjects(c, this);
}
- c = c->parent;
+ c = c->d()->parent;
}
id_empty->mark(this);
@@ -932,7 +944,7 @@ ReturnedValue ExecutionEngine::throwException(const ValueRef value)
QV4::Scope scope(this);
QV4::Scoped<ErrorObject> error(scope, value);
if (!!error)
- exceptionStackTrace = error->stackTrace;
+ exceptionStackTrace = error->d()->stackTrace;
else
exceptionStackTrace = stackTrace();
@@ -971,7 +983,7 @@ QQmlError ExecutionEngine::catchExceptionAsQmlError(ExecutionContext *context)
QV4::Scoped<QV4::ErrorObject> errorObj(scope, exception);
if (!!errorObj && errorObj->asSyntaxError()) {
QV4::ScopedString m(scope, errorObj->engine()->newString(QStringLiteral("message")));
- QV4::ScopedValue v(scope, errorObj->get(m));
+ QV4::ScopedValue v(scope, errorObj->get(m.getPointer()));
error.setDescription(v->toQStringNoThrow());
} else
error.setDescription(exception->toQStringNoThrow());
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index d678d6595e..a3f83de338 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -86,6 +86,7 @@ struct SyntaxErrorObject;
struct ArgumentsObject;
struct ExecutionContext;
struct ExecutionEngine;
+struct Members;
class MemoryManager;
class ExecutableAllocator;
@@ -111,7 +112,7 @@ struct IdentifierTable;
struct InternalClass;
struct InternalClassPool;
class MultiplyWrappedQObjectMap;
-class RegExp;
+struct RegExp;
class RegExpCache;
struct QmlExtensions;
struct Exception;
@@ -169,7 +170,6 @@ public:
return jsStackTop->managed();
}
-
IdentifierTable *identifierTable;
QV4::Debugging::Debugger *debugger;
@@ -285,7 +285,7 @@ public:
// calling preserve() on the object which removes it from this scarceResource list.
class ScarceResourceData {
public:
- ScarceResourceData(const QVariant &data) : data(data) {}
+ ScarceResourceData(const QVariant &data = QVariant()) : data(data) {}
QVariant data;
QIntrusiveListNode node;
};
@@ -306,9 +306,6 @@ public:
void pushContext(CallContext *context);
ExecutionContext *popContext();
- Returned<FunctionObject> *newBuiltinFunction(ExecutionContext *scope, const StringRef name, ReturnedValue (*code)(CallContext *));
- Returned<BoundFunction> *newBoundFunction(ExecutionContext *scope, FunctionObjectRef target, const ValueRef boundThis, const QVector<Value> &boundArgs);
-
Returned<Object> *newObject();
Returned<Object> *newObject(InternalClass *internalClass);
@@ -327,7 +324,7 @@ public:
Returned<DateObject> *newDateObject(const QDateTime &dt);
Returned<RegExpObject> *newRegExpObject(const QString &pattern, int flags);
- Returned<RegExpObject> *newRegExpObject(RegExpRef re, bool global);
+ Returned<RegExpObject> *newRegExpObject(RegExp *re, bool global);
Returned<RegExpObject> *newRegExpObject(const QRegExp &re);
Returned<Object> *newErrorObject(const ValueRef value);
@@ -341,7 +338,7 @@ public:
Returned<Object> *newVariantObject(const QVariant &v);
- Returned<Object> *newForEachIteratorObject(ExecutionContext *ctx, const ObjectRef o);
+ Returned<Object> *newForEachIteratorObject(ExecutionContext *ctx, Object *o);
Returned<Object> *qmlContextObject() const;
@@ -378,10 +375,10 @@ private:
inline
void Managed::mark(QV4::ExecutionEngine *engine)
{
- Q_ASSERT(inUse);
- if (markBit)
+ Q_ASSERT(inUse());
+ if (markBit())
return;
- markBit = 1;
+ d()->markBit = 1;
engine->pushForGC(this);
}
diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp
index 9d6403e7dd..b99a82a1f5 100644
--- a/src/qml/jsruntime/qv4errorobject.cpp
+++ b/src/qml/jsruntime/qv4errorobject.cpp
@@ -71,104 +71,100 @@
using namespace QV4;
-ErrorObject::ErrorObject(InternalClass *ic)
- : Object(ic)
- , stack(0)
+ErrorObject::Data::Data(InternalClass *ic)
+ : Object::Data(ic)
{
- Scope scope(engine());
- ScopedValue protectThis(scope, this);
+ Scope scope(ic->engine);
+ Scoped<ErrorObject> e(scope, this);
- ScopedString s(scope, ic->engine->newString(QStringLiteral("Error")));
- defineDefaultProperty(QStringLiteral("name"), s);
+ ScopedString s(scope, scope.engine->newString(QStringLiteral("Error")));
+ e->defineDefaultProperty(QStringLiteral("name"), s);
}
-ErrorObject::ErrorObject(InternalClass *ic, const ValueRef message, ErrorType t)
- : Object(ic)
- , stack(0)
+ErrorObject::Data::Data(InternalClass *ic, const ValueRef message, ErrorType t)
+ : Object::Data(ic)
{
subtype = t;
- Scope scope(engine());
- ScopedValue protectThis(scope, this);
+ Scope scope(ic->engine);
+ Scoped<ErrorObject> e(scope, this);
- defineAccessorProperty(QStringLiteral("stack"), ErrorObject::method_get_stack, 0);
+ e->defineAccessorProperty(QStringLiteral("stack"), ErrorObject::method_get_stack, 0);
if (!message->isUndefined())
- defineDefaultProperty(QStringLiteral("message"), message);
+ e->defineDefaultProperty(QStringLiteral("message"), message);
ScopedString s(scope);
- defineDefaultProperty(QStringLiteral("name"), (s = ic->engine->newString(className())));
+ e->defineDefaultProperty(QStringLiteral("name"), (s = scope.engine->newString(e->className())));
- stackTrace = ic->engine->stackTrace();
- if (!stackTrace.isEmpty()) {
- defineDefaultProperty(QStringLiteral("fileName"), (s = ic->engine->newString(stackTrace.at(0).source)));
- defineDefaultProperty(QStringLiteral("lineNumber"), Primitive::fromInt32(stackTrace.at(0).line));
+ e->d()->stackTrace = scope.engine->stackTrace();
+ if (!e->d()->stackTrace.isEmpty()) {
+ e->defineDefaultProperty(QStringLiteral("fileName"), (s = scope.engine->newString(e->d()->stackTrace.at(0).source)));
+ e->defineDefaultProperty(QStringLiteral("lineNumber"), Primitive::fromInt32(e->d()->stackTrace.at(0).line));
}
}
-ErrorObject::ErrorObject(InternalClass *ic, const QString &message, ErrorObject::ErrorType t)
- : Object(ic)
- , stack(0)
+ErrorObject::Data::Data(InternalClass *ic, const QString &message, ErrorObject::ErrorType t)
+ : Object::Data(ic)
{
subtype = t;
- Scope scope(engine());
- ScopedValue protectThis(scope, this);
+ Scope scope(ic->engine);
+ Scoped<ErrorObject> e(scope, this);
ScopedString s(scope);
- defineAccessorProperty(QStringLiteral("stack"), ErrorObject::method_get_stack, 0);
+ e->defineAccessorProperty(QStringLiteral("stack"), ErrorObject::method_get_stack, 0);
- ScopedValue v(scope, ic->engine->newString(message));
- defineDefaultProperty(QStringLiteral("message"), v);
- defineDefaultProperty(QStringLiteral("name"), (s = ic->engine->newString(className())));
+ ScopedValue v(scope, scope.engine->newString(message));
+ e->defineDefaultProperty(QStringLiteral("message"), v);
+ e->defineDefaultProperty(QStringLiteral("name"), (s = scope.engine->newString(e->className())));
- stackTrace = ic->engine->stackTrace();
- if (!stackTrace.isEmpty()) {
- defineDefaultProperty(QStringLiteral("fileName"), (s = ic->engine->newString(stackTrace.at(0).source)));
- defineDefaultProperty(QStringLiteral("lineNumber"), Primitive::fromInt32(stackTrace.at(0).line));
+ e->d()->stackTrace = scope.engine->stackTrace();
+ if (!e->d()->stackTrace.isEmpty()) {
+ e->defineDefaultProperty(QStringLiteral("fileName"), (s = scope.engine->newString(e->d()->stackTrace.at(0).source)));
+ e->defineDefaultProperty(QStringLiteral("lineNumber"), Primitive::fromInt32(e->d()->stackTrace.at(0).line));
}
}
-ErrorObject::ErrorObject(InternalClass *ic, const QString &message, const QString &fileName, int line, int column, ErrorObject::ErrorType t)
- : Object(ic)
- , stack(0)
+ErrorObject::Data::Data(InternalClass *ic, const QString &message, const QString &fileName, int line, int column, ErrorObject::ErrorType t)
+ : Object::Data(ic)
{
subtype = t;
- Scope scope(engine());
- ScopedValue protectThis(scope, this);
+ Scope scope(ic->engine);
+ Scoped<ErrorObject> e(scope, this);
ScopedString s(scope);
- defineAccessorProperty(QStringLiteral("stack"), ErrorObject::method_get_stack, 0);
- defineDefaultProperty(QStringLiteral("name"), (s = ic->engine->newString(className())));
+ e->defineAccessorProperty(QStringLiteral("stack"), ErrorObject::method_get_stack, 0);
+ e->defineDefaultProperty(QStringLiteral("name"), (s = scope.engine->newString(e->className())));
- stackTrace = ic->engine->stackTrace();
+ e->d()->stackTrace = scope.engine->stackTrace();
StackFrame frame;
frame.source = fileName;
frame.line = line;
frame.column = column;
- stackTrace.prepend(frame);
+ e->d()->stackTrace.prepend(frame);
- if (!stackTrace.isEmpty()) {
- defineDefaultProperty(QStringLiteral("fileName"), (s = ic->engine->newString(stackTrace.at(0).source)));
- defineDefaultProperty(QStringLiteral("lineNumber"), Primitive::fromInt32(stackTrace.at(0).line));
+ if (!e->d()->stackTrace.isEmpty()) {
+ e->defineDefaultProperty(QStringLiteral("fileName"), (s = scope.engine->newString(e->d()->stackTrace.at(0).source)));
+ e->defineDefaultProperty(QStringLiteral("lineNumber"), Primitive::fromInt32(e->d()->stackTrace.at(0).line));
}
- ScopedValue v(scope, ic->engine->newString(message));
- defineDefaultProperty(QStringLiteral("message"), v);
+ ScopedValue v(scope, scope.engine->newString(message));
+ e->defineDefaultProperty(QStringLiteral("message"), v);
}
ReturnedValue ErrorObject::method_get_stack(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<ErrorObject> This(scope, ctx->callData->thisObject);
+ Scoped<ErrorObject> This(scope, ctx->d()->callData->thisObject);
if (!This)
return ctx->throwTypeError();
- if (!This->stack) {
+ if (!This->d()->stack) {
QString trace;
- for (int i = 0; i < This->stackTrace.count(); ++i) {
+ for (int i = 0; i < This->d()->stackTrace.count(); ++i) {
if (i > 0)
trace += QLatin1Char('\n');
- const StackFrame &frame = This->stackTrace[i];
+ const StackFrame &frame = This->d()->stackTrace[i];
trace += frame.function;
trace += QLatin1Char('@');
trace += frame.source;
@@ -177,16 +173,16 @@ ReturnedValue ErrorObject::method_get_stack(CallContext *ctx)
trace += QString::number(frame.line);
}
}
- This->stack = ctx->engine->newString(trace)->getPointer();
+ This->d()->stack = ctx->d()->engine->newString(trace)->getPointer();
}
- return This->stack->asReturnedValue();
+ return This->d()->stack->asReturnedValue();
}
void ErrorObject::markObjects(Managed *that, ExecutionEngine *e)
{
ErrorObject *This = that->asErrorObject();
- if (This->stack)
- This->stack->mark(e);
+ if (This->d()->stack)
+ This->d()->stack->mark(e);
Object::markObjects(that, e);
}
@@ -194,58 +190,58 @@ DEFINE_OBJECT_VTABLE(ErrorObject);
DEFINE_OBJECT_VTABLE(SyntaxErrorObject);
-SyntaxErrorObject::SyntaxErrorObject(ExecutionEngine *engine, const ValueRef msg)
- : ErrorObject(engine->syntaxErrorClass, msg, SyntaxError)
+SyntaxErrorObject::Data::Data(ExecutionEngine *engine, const ValueRef msg)
+ : ErrorObject::Data(engine->syntaxErrorClass, msg, SyntaxError)
{
}
-SyntaxErrorObject::SyntaxErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber)
- : ErrorObject(engine->syntaxErrorClass, msg, fileName, lineNumber, columnNumber, SyntaxError)
+SyntaxErrorObject::Data::Data(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber)
+ : ErrorObject::Data(engine->syntaxErrorClass, msg, fileName, lineNumber, columnNumber, SyntaxError)
{
}
-EvalErrorObject::EvalErrorObject(ExecutionEngine *engine, const ValueRef message)
- : ErrorObject(engine->evalErrorClass, message, EvalError)
+EvalErrorObject::Data::Data(ExecutionEngine *engine, const ValueRef message)
+ : ErrorObject::Data(engine->evalErrorClass, message, EvalError)
{
}
-RangeErrorObject::RangeErrorObject(ExecutionEngine *engine, const ValueRef message)
- : ErrorObject(engine->rangeErrorClass, message, RangeError)
+RangeErrorObject::Data::Data(ExecutionEngine *engine, const ValueRef message)
+ : ErrorObject::Data(engine->rangeErrorClass, message, RangeError)
{
}
-RangeErrorObject::RangeErrorObject(ExecutionEngine *engine, const QString &message)
- : ErrorObject(engine->rangeErrorClass, message, RangeError)
+RangeErrorObject::Data::Data(ExecutionEngine *engine, const QString &message)
+ : ErrorObject::Data(engine->rangeErrorClass, message, RangeError)
{
}
-ReferenceErrorObject::ReferenceErrorObject(ExecutionEngine *engine, const ValueRef message)
- : ErrorObject(engine->referenceErrorClass, message, ReferenceError)
+ReferenceErrorObject::Data::Data(ExecutionEngine *engine, const ValueRef message)
+ : ErrorObject::Data(engine->referenceErrorClass, message, ReferenceError)
{
}
-ReferenceErrorObject::ReferenceErrorObject(ExecutionEngine *engine, const QString &message)
- : ErrorObject(engine->referenceErrorClass, message, ReferenceError)
+ReferenceErrorObject::Data::Data(ExecutionEngine *engine, const QString &message)
+ : ErrorObject::Data(engine->referenceErrorClass, message, ReferenceError)
{
}
-ReferenceErrorObject::ReferenceErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber)
- : ErrorObject(engine->referenceErrorClass, msg, fileName, lineNumber, columnNumber, ReferenceError)
+ReferenceErrorObject::Data::Data(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber)
+ : ErrorObject::Data(engine->referenceErrorClass, msg, fileName, lineNumber, columnNumber, ReferenceError)
{
}
-TypeErrorObject::TypeErrorObject(ExecutionEngine *engine, const ValueRef message)
- : ErrorObject(engine->typeErrorClass, message, TypeError)
+TypeErrorObject::Data::Data(ExecutionEngine *engine, const ValueRef message)
+ : ErrorObject::Data(engine->typeErrorClass, message, TypeError)
{
}
-TypeErrorObject::TypeErrorObject(ExecutionEngine *engine, const QString &message)
- : ErrorObject(engine->typeErrorClass, message, TypeError)
+TypeErrorObject::Data::Data(ExecutionEngine *engine, const QString &message)
+ : ErrorObject::Data(engine->typeErrorClass, message, TypeError)
{
}
-URIErrorObject::URIErrorObject(ExecutionEngine *engine, const ValueRef message)
- : ErrorObject(engine->uriErrorClass, message, URIError)
+URIErrorObject::Data::Data(ExecutionEngine *engine, const ValueRef message)
+ : ErrorObject::Data(engine->uriErrorClass, message, URIError)
{
}
@@ -257,14 +253,14 @@ DEFINE_OBJECT_VTABLE(SyntaxErrorCtor);
DEFINE_OBJECT_VTABLE(TypeErrorCtor);
DEFINE_OBJECT_VTABLE(URIErrorCtor);
-ErrorCtor::ErrorCtor(ExecutionContext *scope)
- : FunctionObject(scope, QStringLiteral("Error"))
+ErrorCtor::Data::Data(ExecutionContext *scope)
+ : FunctionObject::Data(scope, QStringLiteral("Error"))
{
setVTable(staticVTable());
}
-ErrorCtor::ErrorCtor(ExecutionContext *scope, const QString &name)
- : FunctionObject(scope, name)
+ErrorCtor::Data::Data(ExecutionContext *scope, const QString &name)
+ : FunctionObject::Data(scope, name)
{
setVTable(staticVTable());
}
@@ -281,8 +277,8 @@ ReturnedValue ErrorCtor::call(Managed *that, CallData *callData)
return static_cast<Object *>(that)->construct(callData);
}
-EvalErrorCtor::EvalErrorCtor(ExecutionContext *scope)
- : ErrorCtor(scope, QStringLiteral("EvalError"))
+EvalErrorCtor::Data::Data(ExecutionContext *scope)
+ : ErrorCtor::Data(scope, QStringLiteral("EvalError"))
{
setVTable(staticVTable());
}
@@ -291,11 +287,11 @@ ReturnedValue EvalErrorCtor::construct(Managed *m, CallData *callData)
{
Scope scope(m->engine());
ScopedValue v(scope, callData->argument(0));
- return (new (m->engine()->memoryManager) EvalErrorObject(m->engine(), v))->asReturnedValue();
+ return (m->engine()->memoryManager->alloc<EvalErrorObject>(m->engine(), v))->asReturnedValue();
}
-RangeErrorCtor::RangeErrorCtor(ExecutionContext *scope)
- : ErrorCtor(scope, QStringLiteral("RangeError"))
+RangeErrorCtor::Data::Data(ExecutionContext *scope)
+ : ErrorCtor::Data(scope, QStringLiteral("RangeError"))
{
setVTable(staticVTable());
}
@@ -304,11 +300,11 @@ ReturnedValue RangeErrorCtor::construct(Managed *m, CallData *callData)
{
Scope scope(m->engine());
ScopedValue v(scope, callData->argument(0));
- return (new (m->engine()->memoryManager) RangeErrorObject(scope.engine, v))->asReturnedValue();
+ return (m->engine()->memoryManager->alloc<RangeErrorObject>(scope.engine, v))->asReturnedValue();
}
-ReferenceErrorCtor::ReferenceErrorCtor(ExecutionContext *scope)
- : ErrorCtor(scope, QStringLiteral("ReferenceError"))
+ReferenceErrorCtor::Data::Data(ExecutionContext *scope)
+ : ErrorCtor::Data(scope, QStringLiteral("ReferenceError"))
{
setVTable(staticVTable());
}
@@ -317,11 +313,11 @@ ReturnedValue ReferenceErrorCtor::construct(Managed *m, CallData *callData)
{
Scope scope(m->engine());
ScopedValue v(scope, callData->argument(0));
- return (new (m->engine()->memoryManager) ReferenceErrorObject(scope.engine, v))->asReturnedValue();
+ return (m->engine()->memoryManager->alloc<ReferenceErrorObject>(scope.engine, v))->asReturnedValue();
}
-SyntaxErrorCtor::SyntaxErrorCtor(ExecutionContext *scope)
- : ErrorCtor(scope, QStringLiteral("SyntaxError"))
+SyntaxErrorCtor::Data::Data(ExecutionContext *scope)
+ : ErrorCtor::Data(scope, QStringLiteral("SyntaxError"))
{
setVTable(staticVTable());
}
@@ -330,11 +326,11 @@ ReturnedValue SyntaxErrorCtor::construct(Managed *m, CallData *callData)
{
Scope scope(m->engine());
ScopedValue v(scope, callData->argument(0));
- return (new (m->engine()->memoryManager) SyntaxErrorObject(scope.engine, v))->asReturnedValue();
+ return (m->engine()->memoryManager->alloc<SyntaxErrorObject>(scope.engine, v))->asReturnedValue();
}
-TypeErrorCtor::TypeErrorCtor(ExecutionContext *scope)
- : ErrorCtor(scope, QStringLiteral("TypeError"))
+TypeErrorCtor::Data::Data(ExecutionContext *scope)
+ : ErrorCtor::Data(scope, QStringLiteral("TypeError"))
{
setVTable(staticVTable());
}
@@ -343,11 +339,11 @@ ReturnedValue TypeErrorCtor::construct(Managed *m, CallData *callData)
{
Scope scope(m->engine());
ScopedValue v(scope, callData->argument(0));
- return (new (m->engine()->memoryManager) TypeErrorObject(scope.engine, v))->asReturnedValue();
+ return (m->engine()->memoryManager->alloc<TypeErrorObject>(scope.engine, v))->asReturnedValue();
}
-URIErrorCtor::URIErrorCtor(ExecutionContext *scope)
- : ErrorCtor(scope, QStringLiteral("URIError"))
+URIErrorCtor::Data::Data(ExecutionContext *scope)
+ : ErrorCtor::Data(scope, QStringLiteral("URIError"))
{
setVTable(staticVTable());
}
@@ -356,10 +352,10 @@ ReturnedValue URIErrorCtor::construct(Managed *m, CallData *callData)
{
Scope scope(m->engine());
ScopedValue v(scope, callData->argument(0));
- return (new (m->engine()->memoryManager) URIErrorObject(scope.engine, v))->asReturnedValue();
+ return (m->engine()->memoryManager->alloc<URIErrorObject>(scope.engine, v))->asReturnedValue();
}
-void ErrorPrototype::init(ExecutionEngine *engine, ObjectRef ctor, Object *obj)
+void ErrorPrototype::init(ExecutionEngine *engine, Object *ctor, Object *obj)
{
Scope scope(engine);
ScopedString s(scope);
@@ -375,19 +371,19 @@ ReturnedValue ErrorPrototype::method_toString(CallContext *ctx)
{
Scope scope(ctx);
- Object *o = ctx->callData->thisObject.asObject();
+ Object *o = ctx->d()->callData->thisObject.asObject();
if (!o)
return ctx->throwTypeError();
- ScopedValue name(scope, o->get(ctx->engine->id_name));
+ ScopedValue name(scope, o->get(ctx->d()->engine->id_name));
QString qname;
if (name->isUndefined())
qname = QString::fromLatin1("Error");
else
qname = name->toQString();
- ScopedString s(scope, ctx->engine->newString(QString::fromLatin1("message")));
- ScopedValue message(scope, o->get(s));
+ ScopedString s(scope, ctx->d()->engine->newString(QString::fromLatin1("message")));
+ ScopedValue message(scope, o->get(s.getPointer()));
QString qmessage;
if (!message->isUndefined())
qmessage = message->toQString();
@@ -401,5 +397,5 @@ ReturnedValue ErrorPrototype::method_toString(CallContext *ctx)
str = qname + QLatin1String(": ") + qmessage;
}
- return ctx->engine->newString(str)->asReturnedValue();
+ return ctx->d()->engine->newString(str)->asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4errorobject_p.h b/src/qml/jsruntime/qv4errorobject_p.h
index c44cc5cdb2..ddf30d2059 100644
--- a/src/qml/jsruntime/qv4errorobject_p.h
+++ b/src/qml/jsruntime/qv4errorobject_p.h
@@ -51,8 +51,6 @@ namespace QV4 {
struct SyntaxErrorObject;
struct ErrorObject: Object {
- V4_OBJECT
- Q_MANAGED_TYPE(ErrorObject)
enum {
IsErrorObject = true
};
@@ -66,17 +64,19 @@ struct ErrorObject: Object {
TypeError,
URIError
};
-
- ErrorObject(InternalClass *ic);
- ErrorObject(InternalClass *ic, const ValueRef message, ErrorType t = Error);
- ErrorObject(InternalClass *ic, const QString &message, ErrorType t = Error);
- ErrorObject(InternalClass *ic, const QString &message, const QString &fileName, int line, int column, ErrorType t = Error);
+ struct Data : Object::Data {
+ Data(InternalClass *ic);
+ Data(InternalClass *ic, const ValueRef message, ErrorType t = Error);
+ Data(InternalClass *ic, const QString &message, ErrorType t = Error);
+ Data(InternalClass *ic, const QString &message, const QString &fileName, int line, int column, ErrorType t = Error);
+ StackTrace stackTrace;
+ String *stack;
+ };
+ V4_OBJECT(Object)
+ Q_MANAGED_TYPE(ErrorObject)
SyntaxErrorObject *asSyntaxError();
- StackTrace stackTrace;
- String *stack;
-
static ReturnedValue method_get_stack(CallContext *ctx);
static void markObjects(Managed *that, ExecutionEngine *e);
static void destroy(Managed *that) { static_cast<ErrorObject *>(that)->~ErrorObject(); }
@@ -88,40 +88,55 @@ inline ErrorObject *value_cast(const Value &v) {
}
struct EvalErrorObject: ErrorObject {
- EvalErrorObject(ExecutionEngine *engine, const ValueRef message);
+ struct Data : ErrorObject::Data {
+ Data(ExecutionEngine *engine, const ValueRef message);
+ };
};
struct RangeErrorObject: ErrorObject {
- RangeErrorObject(ExecutionEngine *engine, const ValueRef message);
- RangeErrorObject(ExecutionEngine *engine, const QString &msg);
+ struct Data : ErrorObject::Data {
+ Data(ExecutionEngine *engine, const ValueRef message);
+ Data(ExecutionEngine *engine, const QString &msg);
+ };
};
struct ReferenceErrorObject: ErrorObject {
- ReferenceErrorObject(ExecutionEngine *engine, const ValueRef message);
- ReferenceErrorObject(ExecutionEngine *engine, const QString &msg);
- ReferenceErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber);
+ struct Data : ErrorObject::Data {
+ Data(ExecutionEngine *engine, const ValueRef message);
+ Data(ExecutionEngine *engine, const QString &msg);
+ Data(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber);
+ };
};
struct SyntaxErrorObject: ErrorObject {
- V4_OBJECT
- SyntaxErrorObject(ExecutionEngine *engine, const ValueRef msg);
- SyntaxErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber);
+ struct Data : ErrorObject::Data {
+ Data(ExecutionEngine *engine, const ValueRef message);
+ Data(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber);
+ };
+ V4_OBJECT(ErrorObject)
};
struct TypeErrorObject: ErrorObject {
- TypeErrorObject(ExecutionEngine *engine, const ValueRef message);
- TypeErrorObject(ExecutionEngine *engine, const QString &msg);
+ struct Data : ErrorObject::Data {
+ Data(ExecutionEngine *engine, const ValueRef message);
+ Data(ExecutionEngine *engine, const QString &msg);
+ };
};
struct URIErrorObject: ErrorObject {
- URIErrorObject(ExecutionEngine *engine, const ValueRef message);
+ struct Data : ErrorObject::Data {
+ Data(ExecutionEngine *engine, const ValueRef message);
+ };
};
struct ErrorCtor: FunctionObject
{
- V4_OBJECT
- ErrorCtor(ExecutionContext *scope);
- ErrorCtor(ExecutionContext *scope, const QString &name);
+ struct Data : FunctionObject::Data {
+ Data(ExecutionContext *scope);
+ Data(ExecutionContext *scope, const QString &name);
+ };
+
+ V4_OBJECT(FunctionObject)
static ReturnedValue construct(Managed *, CallData *callData);
static ReturnedValue call(Managed *that, CallData *callData);
@@ -129,103 +144,107 @@ struct ErrorCtor: FunctionObject
struct EvalErrorCtor: ErrorCtor
{
- V4_OBJECT
- EvalErrorCtor(ExecutionContext *scope);
+ struct Data : ErrorCtor::Data {
+ Data(ExecutionContext *scope);
+ };
+ V4_OBJECT(ErrorCtor)
static ReturnedValue construct(Managed *m, CallData *callData);
};
struct RangeErrorCtor: ErrorCtor
{
- V4_OBJECT
- RangeErrorCtor(ExecutionContext *scope);
+ struct Data : ErrorCtor::Data {
+ Data(ExecutionContext *scope);
+ };
+ V4_OBJECT(ErrorCtor)
static ReturnedValue construct(Managed *m, CallData *callData);
};
struct ReferenceErrorCtor: ErrorCtor
{
- V4_OBJECT
- ReferenceErrorCtor(ExecutionContext *scope);
+ struct Data : ErrorCtor::Data {
+ Data(ExecutionContext *scope);
+ };
+ V4_OBJECT(ErrorCtor)
static ReturnedValue construct(Managed *m, CallData *callData);
};
struct SyntaxErrorCtor: ErrorCtor
{
- V4_OBJECT
- SyntaxErrorCtor(ExecutionContext *scope);
+ struct Data : ErrorCtor::Data {
+ Data(ExecutionContext *scope);
+ };
+ V4_OBJECT(ErrorCtor)
static ReturnedValue construct(Managed *m, CallData *callData);
};
struct TypeErrorCtor: ErrorCtor
{
- V4_OBJECT
- TypeErrorCtor(ExecutionContext *scope);
+ struct Data : ErrorCtor::Data {
+ Data(ExecutionContext *scope);
+ };
+ V4_OBJECT(ErrorCtor)
static ReturnedValue construct(Managed *m, CallData *callData);
};
struct URIErrorCtor: ErrorCtor
{
- V4_OBJECT
- URIErrorCtor(ExecutionContext *scope);
+ struct Data : ErrorCtor::Data {
+ Data(ExecutionContext *scope);
+ };
+ V4_OBJECT(ErrorCtor)
static ReturnedValue construct(Managed *m, CallData *callData);
};
-struct ErrorPrototype: ErrorObject
+struct ErrorPrototype : ErrorObject
{
- // ### shouldn't be undefined
- ErrorPrototype(InternalClass *ic): ErrorObject(ic) {}
- void init(ExecutionEngine *engine, ObjectRef ctor) { init(engine, ctor, this); }
+ void init(ExecutionEngine *engine, Object *ctor) { init(engine, ctor, this); }
- static void init(ExecutionEngine *engine, ObjectRef ctor, Object *obj);
+ static void init(ExecutionEngine *engine, Object *ctor, Object *obj);
static ReturnedValue method_toString(CallContext *ctx);
};
-struct EvalErrorPrototype: ErrorObject
+struct EvalErrorPrototype : ErrorObject
{
- EvalErrorPrototype(InternalClass *ic): ErrorObject(ic) { setVTable(staticVTable()); }
- void init(ExecutionEngine *engine, ObjectRef ctor) { ErrorPrototype::init(engine, ctor, this); }
+ void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this); }
};
-struct RangeErrorPrototype: ErrorObject
+struct RangeErrorPrototype : ErrorObject
{
- RangeErrorPrototype(InternalClass *ic): ErrorObject(ic) { setVTable(staticVTable()); }
- void init(ExecutionEngine *engine, ObjectRef ctor) { ErrorPrototype::init(engine, ctor, this); }
+ void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this); }
};
-struct ReferenceErrorPrototype: ErrorObject
+struct ReferenceErrorPrototype : ErrorObject
{
- ReferenceErrorPrototype(InternalClass *ic): ErrorObject(ic) { setVTable(staticVTable()); }
- void init(ExecutionEngine *engine, ObjectRef ctor) { ErrorPrototype::init(engine, ctor, this); }
+ void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this); }
};
-struct SyntaxErrorPrototype: ErrorObject
+struct SyntaxErrorPrototype : ErrorObject
{
- SyntaxErrorPrototype(InternalClass *ic): ErrorObject(ic) { setVTable(staticVTable()); }
- void init(ExecutionEngine *engine, ObjectRef ctor) { ErrorPrototype::init(engine, ctor, this); }
+ void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this); }
};
-struct TypeErrorPrototype: ErrorObject
+struct TypeErrorPrototype : ErrorObject
{
- TypeErrorPrototype(InternalClass *ic): ErrorObject(ic) { setVTable(staticVTable()); }
- void init(ExecutionEngine *engine, ObjectRef ctor) { ErrorPrototype::init(engine, ctor, this); }
+ void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this); }
};
-struct URIErrorPrototype: ErrorObject
+struct URIErrorPrototype : ErrorObject
{
- URIErrorPrototype(InternalClass *ic): ErrorObject(ic) { setVTable(staticVTable()); }
- void init(ExecutionEngine *engine, ObjectRef ctor) { ErrorPrototype::init(engine, ctor, this); }
+ void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this); }
};
inline SyntaxErrorObject *ErrorObject::asSyntaxError()
{
- return subtype == SyntaxError ? static_cast<SyntaxErrorObject *>(this) : 0;
+ return subtype() == SyntaxError ? static_cast<SyntaxErrorObject *>(this) : 0;
}
}
diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp
index 6fdf61f2c3..bf77b4434c 100644
--- a/src/qml/jsruntime/qv4function.cpp
+++ b/src/qml/jsruntime/qv4function.cpp
@@ -45,6 +45,7 @@
#include "qv4value_inl_p.h"
#include "qv4engine_p.h"
#include "qv4lookup_p.h"
+#include "qv4mm_p.h"
QT_BEGIN_NAMESPACE
@@ -62,6 +63,8 @@ Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit,
internalClass = engine->emptyClass;
const quint32 *formalsIndices = compiledFunction->formalsTable();
// iterate backwards, so we get the right ordering for duplicate names
+ Scope scope(engine);
+ ScopedString s(scope);
for (int i = static_cast<int>(compiledFunction->nFormals - 1); i >= 0; --i) {
String *arg = compilationUnit->runtimeStrings[formalsIndices[i]].asString();
while (1) {
@@ -71,7 +74,7 @@ Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit,
break;
}
// duplicate arguments, need some trick to store them
- arg = new (engine->memoryManager) String(engine, arg, engine->newString(QString(0xfffe))->getPointer());
+ arg = (s = engine->memoryManager->alloc<String>(engine, arg, engine->newString(QString(0xfffe))->getPointer())).getPointer();
}
}
diff --git a/src/qml/jsruntime/qv4function_p.h b/src/qml/jsruntime/qv4function_p.h
index e6385d861c..482f247319 100644
--- a/src/qml/jsruntime/qv4function_p.h
+++ b/src/qml/jsruntime/qv4function_p.h
@@ -94,8 +94,8 @@ struct Q_QML_EXPORT Function {
ReturnedValue (*codePtr)(ExecutionContext *, const uchar *));
~Function();
- inline StringRef name() {
- return compilationUnit->runtimeStrings[compiledFunction->nameIndex];
+ inline String *name() {
+ return compilationUnit->runtimeStrings[compiledFunction->nameIndex].getPointer();
}
inline QString sourceFile() const { return compilationUnit->fileName(); }
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index 39a123c4d2..10974780f3 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -74,88 +74,88 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(FunctionObject);
-FunctionObject::FunctionObject(ExecutionContext *scope, const StringRef name, bool createProto)
- : Object(scope->engine->functionClass)
+FunctionObject::Data::Data(ExecutionContext *scope, String *name, bool createProto)
+ : Object::Data(scope->d()->engine->functionClass)
, scope(scope)
- , function(0)
{
- init(name, createProto);
+ Scope s(scope);
+ ScopedFunctionObject f(s, this);
+ f->init(name, createProto);
}
-FunctionObject::FunctionObject(ExecutionContext *scope, const QString &name, bool createProto)
- : Object(scope->engine->functionClass)
+
+FunctionObject::Data::Data(ExecutionContext *scope, const QString &name, bool createProto)
+ : Object::Data(scope->d()->engine->functionClass)
, scope(scope)
- , function(0)
{
Scope s(scope);
- ScopedValue protectThis(s, this);
+ ScopedFunctionObject f(s, this);
ScopedString n(s, s.engine->newString(name));
- init(n, createProto);
+ f->init(n.getPointer(), createProto);
}
-FunctionObject::FunctionObject(ExecutionContext *scope, const ReturnedValue name)
- : Object(scope->engine->functionClass)
+FunctionObject::Data::Data(ExecutionContext *scope, const ReturnedValue name)
+ : Object::Data(scope->d()->engine->functionClass)
, scope(scope)
- , function(0)
{
Scope s(scope);
- ScopedValue protectThis(s, this);
+ ScopedFunctionObject f(s, this);
ScopedString n(s, name);
- init(n, false);
+ f->init(n.getPointer(), false);
}
-FunctionObject::FunctionObject(InternalClass *ic)
- : Object(ic)
+FunctionObject::Data::Data(InternalClass *ic)
+ : Object::Data(ic)
, scope(ic->engine->rootContext)
- , function(0)
{
- needsActivation = false;
- strictMode = false;
+ memberData.ensureIndex(ic->engine, Index_Prototype);
memberData[Index_Prototype] = Encode::undefined();
}
-FunctionObject::~FunctionObject()
+
+FunctionObject::Data::~Data()
{
if (function)
function->compilationUnit->deref();
}
-void FunctionObject::init(const StringRef n, bool createProto)
+void FunctionObject::init(String *n, bool createProto)
{
- Scope s(internalClass->engine);
+ Scope s(internalClass()->engine);
ScopedValue protectThis(s, this);
- needsActivation = true;
- strictMode = false;
+ d()->needsActivation = true;
+ d()->strictMode = false;
+ memberData().ensureIndex(s.engine, Index_Prototype);
if (createProto) {
- Scoped<Object> proto(s, scope->engine->newObject(scope->engine->protoClass));
- proto->memberData[Index_ProtoConstructor] = this->asReturnedValue();
- memberData[Index_Prototype] = proto.asReturnedValue();
+ Scoped<Object> proto(s, scope()->d()->engine->newObject(scope()->d()->engine->protoClass));
+ proto->memberData()[Index_ProtoConstructor] = this->asReturnedValue();
+ memberData()[Index_Prototype] = proto.asReturnedValue();
} else {
- memberData[Index_Prototype] = Encode::undefined();
+ memberData()[Index_Prototype] = Encode::undefined();
}
- ScopedValue v(s, n.asReturnedValue());
- defineReadonlyProperty(scope->engine->id_name, v);
+ ScopedValue v(s, n);
+ defineReadonlyProperty(s.engine->id_name, v);
}
ReturnedValue FunctionObject::name()
{
- return get(scope->engine->id_name);
+ return get(scope()->d()->engine->id_name);
}
ReturnedValue FunctionObject::newInstance()
{
- Scope scope(internalClass->engine);
+ Scope scope(internalClass()->engine);
ScopedCallData callData(scope, 0);
return construct(callData);
}
ReturnedValue FunctionObject::construct(Managed *that, CallData *)
{
- that->internalClass->engine->currentContext()->throwTypeError();
+ that->internalClass()->engine->currentContext()->throwTypeError();
return Encode::undefined();
}
@@ -167,8 +167,8 @@ ReturnedValue FunctionObject::call(Managed *, CallData *)
void FunctionObject::markObjects(Managed *that, ExecutionEngine *e)
{
FunctionObject *o = static_cast<FunctionObject *>(that);
- if (o->scope)
- o->scope->mark(e);
+ if (o->scope())
+ o->scope()->mark(e);
Object::markObjects(that, e);
}
@@ -179,14 +179,14 @@ FunctionObject *FunctionObject::createScriptFunction(ExecutionContext *scope, Fu
function->compiledFunction->flags & CompiledData::Function::HasCatchOrWith ||
function->compiledFunction->nFormals > QV4::Global::ReservedArgumentCount ||
function->isNamedExpression())
- return new (scope->engine->memoryManager) ScriptFunction(scope, function);
- return new (scope->engine->memoryManager) SimpleScriptFunction(scope, function, createProto);
+ return scope->d()->engine->memoryManager->alloc<ScriptFunction>(scope, function);
+ return scope->d()->engine->memoryManager->alloc<SimpleScriptFunction>(scope, function, createProto);
}
DEFINE_OBJECT_VTABLE(FunctionCtor);
-FunctionCtor::FunctionCtor(ExecutionContext *scope)
- : FunctionObject(scope, QStringLiteral("Function"))
+FunctionCtor::Data::Data(ExecutionContext *scope)
+ : FunctionObject::Data(scope, QStringLiteral("Function"))
{
setVTable(staticVTable());
}
@@ -195,7 +195,7 @@ FunctionCtor::FunctionCtor(ExecutionContext *scope)
ReturnedValue FunctionCtor::construct(Managed *that, CallData *callData)
{
FunctionCtor *f = static_cast<FunctionCtor *>(that);
- ExecutionEngine *v4 = f->internalClass->engine;
+ ExecutionEngine *v4 = f->internalClass()->engine;
ExecutionContext *ctx = v4->currentContext();
QString arguments;
QString body;
@@ -207,7 +207,7 @@ ReturnedValue FunctionCtor::construct(Managed *that, CallData *callData)
}
body = callData->args[callData->argc - 1].toString(ctx)->toQString();
}
- if (ctx->engine->hasException)
+ if (ctx->d()->engine->hasException)
return Encode::undefined();
QString function = QLatin1String("function(") + arguments + QLatin1String("){") + body + QLatin1String("}");
@@ -229,7 +229,7 @@ ReturnedValue FunctionCtor::construct(Managed *that, CallData *callData)
IR::Module module(v4->debugger != 0);
- QQmlJS::RuntimeCodegen cg(v4->currentContext(), f->strictMode);
+ QQmlJS::RuntimeCodegen cg(v4->currentContext(), f->strictMode());
cg.generateFromFunctionExpression(QString(), function, fe, &module);
QV4::Compiler::JSUnitGenerator jsGenerator(&module);
@@ -246,12 +246,14 @@ ReturnedValue FunctionCtor::call(Managed *that, CallData *callData)
return construct(that, callData);
}
-FunctionPrototype::FunctionPrototype(InternalClass *ic)
- : FunctionObject(ic)
+DEFINE_OBJECT_VTABLE(FunctionPrototype);
+
+FunctionPrototype::Data::Data(InternalClass *ic)
+ : FunctionObject::Data(ic)
{
}
-void FunctionPrototype::init(ExecutionEngine *engine, ObjectRef ctor)
+void FunctionPrototype::init(ExecutionEngine *engine, Object *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
@@ -270,17 +272,17 @@ void FunctionPrototype::init(ExecutionEngine *engine, ObjectRef ctor)
ReturnedValue FunctionPrototype::method_toString(CallContext *ctx)
{
- FunctionObject *fun = ctx->callData->thisObject.asFunctionObject();
+ FunctionObject *fun = ctx->d()->callData->thisObject.asFunctionObject();
if (!fun)
return ctx->throwTypeError();
- return ctx->engine->newString(QStringLiteral("function() { [code] }"))->asReturnedValue();
+ return ctx->d()->engine->newString(QStringLiteral("function() { [code] }"))->asReturnedValue();
}
ReturnedValue FunctionPrototype::method_apply(CallContext *ctx)
{
Scope scope(ctx);
- FunctionObject *o = ctx->callData->thisObject.asFunctionObject();
+ FunctionObject *o = ctx->d()->callData->thisObject.asFunctionObject();
if (!o)
return ctx->throwTypeError();
@@ -300,13 +302,13 @@ ReturnedValue FunctionPrototype::method_apply(CallContext *ctx)
ScopedCallData callData(scope, len);
if (len) {
- if (arr->arrayType() != ArrayData::Simple || arr->protoHasArray() || arr->hasAccessorProperty) {
+ if (arr->arrayType() != ArrayData::Simple || arr->protoHasArray() || arr->hasAccessorProperty()) {
for (quint32 i = 0; i < len; ++i)
callData->args[i] = arr->getIndexed(i);
} else {
- int alen = qMin(len, arr->arrayData->length());
+ int alen = qMin(len, arr->arrayData()->length());
if (alen)
- memcpy(callData->args, arr->arrayData->data, alen*sizeof(Value));
+ memcpy(callData->args, arr->arrayData()->arrayData(), alen*sizeof(Value));
for (quint32 i = alen; i < len; ++i)
callData->args[i] = Primitive::undefinedValue();
}
@@ -320,14 +322,14 @@ ReturnedValue FunctionPrototype::method_call(CallContext *ctx)
{
Scope scope(ctx);
- FunctionObject *o = ctx->callData->thisObject.asFunctionObject();
+ FunctionObject *o = ctx->d()->callData->thisObject.asFunctionObject();
if (!o)
return ctx->throwTypeError();
- ScopedCallData callData(scope, ctx->callData->argc ? ctx->callData->argc - 1 : 0);
- if (ctx->callData->argc) {
- for (int i = 1; i < ctx->callData->argc; ++i)
- callData->args[i - 1] = ctx->callData->args[i];
+ ScopedCallData callData(scope, ctx->d()->callData->argc ? ctx->d()->callData->argc - 1 : 0);
+ if (ctx->d()->callData->argc) {
+ for (int i = 1; i < ctx->d()->callData->argc; ++i)
+ callData->args[i - 1] = ctx->d()->callData->args[i];
}
callData->thisObject = ctx->argument(0);
return o->call(callData);
@@ -336,49 +338,34 @@ ReturnedValue FunctionPrototype::method_call(CallContext *ctx)
ReturnedValue FunctionPrototype::method_bind(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<FunctionObject> target(scope, ctx->callData->thisObject);
+ Scoped<FunctionObject> target(scope, ctx->d()->callData->thisObject);
if (!target)
return ctx->throwTypeError();
ScopedValue boundThis(scope, ctx->argument(0));
- QVector<Value> boundArgs;
- for (int i = 1; i < ctx->callData->argc; ++i)
- boundArgs += ctx->callData->args[i];
+ Members boundArgs;
+ boundArgs.reset();
+ if (ctx->d()->callData->argc > 1) {
+ boundArgs.ensureIndex(scope.engine, ctx->d()->callData->argc - 1);
+ boundArgs.d()->d()->size = ctx->d()->callData->argc - 1;
+ memcpy(boundArgs.data(), ctx->d()->callData->args + 1, (ctx->d()->callData->argc - 1)*sizeof(Value));
+ }
+ ScopedValue protectBoundArgs(scope, boundArgs.d());
- return ctx->engine->newBoundFunction(ctx->engine->rootContext, target, boundThis, boundArgs)->asReturnedValue();
+ return BoundFunction::create(ctx->d()->engine->rootContext, target, boundThis, boundArgs)->asReturnedValue();
}
DEFINE_OBJECT_VTABLE(ScriptFunction);
-ScriptFunction::ScriptFunction(ExecutionContext *scope, Function *function)
- : SimpleScriptFunction(scope, function, true)
+ScriptFunction::Data::Data(ExecutionContext *scope, Function *function)
+ : SimpleScriptFunction::Data(scope, function, true)
{
setVTable(staticVTable());
-
- Scope s(scope);
- ScopedValue protectThis(s, this);
-
- // global function
- if (!scope)
- return;
-
- ExecutionEngine *v4 = scope->engine;
-
- needsActivation = function->needsActivation();
- strictMode = function->isStrict();
-
- defineReadonlyProperty(scope->engine->id_length, Primitive::fromInt32(formalParameterCount()));
-
- if (scope->strictMode) {
- Property pd(v4->thrower, v4->thrower);
- insertMember(scope->engine->id_caller, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
- insertMember(scope->engine->id_arguments, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
- }
}
ReturnedValue ScriptFunction::construct(Managed *that, CallData *callData)
{
- ExecutionEngine *v4 = that->internalClass->engine;
+ ExecutionEngine *v4 = that->engine();
if (v4->hasException)
return Encode::undefined();
CHECK_STACK_LIMITS(v4);
@@ -391,13 +378,13 @@ ReturnedValue ScriptFunction::construct(Managed *that, CallData *callData)
ExecutionContext *context = v4->currentContext();
callData->thisObject = obj.asReturnedValue();
- ExecutionContext *ctx = context->newCallContext(f.getPointer(), callData);
+ ExecutionContext *ctx = reinterpret_cast<ExecutionContext *>(context->newCallContext(f.getPointer(), callData));
ExecutionContextSaver ctxSaver(context);
- ScopedValue result(scope, Q_V4_PROFILE(v4, ctx, f->function));
+ ScopedValue result(scope, Q_V4_PROFILE(v4, ctx, f->function()));
- if (f->function->compiledFunction->hasQmlDependencies())
- QmlContextWrapper::registerQmlDependencies(v4, f->function->compiledFunction);
+ if (f->function()->compiledFunction->hasQmlDependencies())
+ QmlContextWrapper::registerQmlDependencies(v4, f->function()->compiledFunction);
if (result->isObject())
return result.asReturnedValue();
@@ -407,7 +394,7 @@ ReturnedValue ScriptFunction::construct(Managed *that, CallData *callData)
ReturnedValue ScriptFunction::call(Managed *that, CallData *callData)
{
ScriptFunction *f = static_cast<ScriptFunction *>(that);
- ExecutionEngine *v4 = f->internalClass->engine;
+ ExecutionEngine *v4 = f->engine();
if (v4->hasException)
return Encode::undefined();
CHECK_STACK_LIMITS(v4);
@@ -415,53 +402,51 @@ ReturnedValue ScriptFunction::call(Managed *that, CallData *callData)
ExecutionContext *context = v4->currentContext();
Scope scope(context);
- CallContext *ctx = context->newCallContext(f, callData);
+ CallContext *ctx = reinterpret_cast<CallContext *>(context->newCallContext(f, callData));
ExecutionContextSaver ctxSaver(context);
- ScopedValue result(scope, Q_V4_PROFILE(v4, ctx, f->function));
+ ScopedValue result(scope, Q_V4_PROFILE(v4, ctx, f->function()));
- if (f->function->compiledFunction->hasQmlDependencies())
- QmlContextWrapper::registerQmlDependencies(ctx->engine, f->function->compiledFunction);
+ if (f->function()->compiledFunction->hasQmlDependencies())
+ QmlContextWrapper::registerQmlDependencies(ctx->d()->engine, f->function()->compiledFunction);
return result.asReturnedValue();
}
DEFINE_OBJECT_VTABLE(SimpleScriptFunction);
-SimpleScriptFunction::SimpleScriptFunction(ExecutionContext *scope, Function *function, bool createProto)
- : FunctionObject(scope, function->name(), createProto)
+SimpleScriptFunction::Data::Data(ExecutionContext *scope, Function *function, bool createProto)
+ : FunctionObject::Data(scope, function->name(), createProto)
{
setVTable(staticVTable());
- Scope s(scope);
- ScopedValue protectThis(s, this);
-
this->function = function;
- this->function->compilationUnit->ref();
+ function->compilationUnit->ref();
Q_ASSERT(function);
Q_ASSERT(function->code);
+ needsActivation = function->needsActivation();
+ strictMode = function->isStrict();
+
// global function
if (!scope)
return;
- ExecutionEngine *v4 = scope->engine;
-
- needsActivation = function->needsActivation();
- strictMode = function->isStrict();
+ Scope s(scope);
+ ScopedFunctionObject f(s, this);
- defineReadonlyProperty(scope->engine->id_length, Primitive::fromInt32(formalParameterCount()));
+ f->defineReadonlyProperty(scope->d()->engine->id_length, Primitive::fromInt32(f->formalParameterCount()));
- if (scope->strictMode) {
- Property pd(v4->thrower, v4->thrower);
- insertMember(scope->engine->id_caller, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
- insertMember(scope->engine->id_arguments, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
+ if (scope->d()->strictMode) {
+ Property pd(s.engine->thrower, s.engine->thrower);
+ f->insertMember(scope->d()->engine->id_caller, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
+ f->insertMember(scope->d()->engine->id_arguments, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
}
}
ReturnedValue SimpleScriptFunction::construct(Managed *that, CallData *callData)
{
- ExecutionEngine *v4 = that->internalClass->engine;
+ ExecutionEngine *v4 = that->engine();
if (v4->hasException)
return Encode::undefined();
CHECK_STACK_LIMITS(v4);
@@ -475,24 +460,24 @@ ReturnedValue SimpleScriptFunction::construct(Managed *that, CallData *callData)
ExecutionContext *context = v4->currentContext();
ExecutionContextSaver ctxSaver(context);
- CallContext ctx(v4);
- ctx.strictMode = f->strictMode;
+ CallContext::Data ctx(v4);
+ ctx.strictMode = f->strictMode();
ctx.callData = callData;
ctx.function = f.getPointer();
- ctx.compilationUnit = f->function->compilationUnit;
+ ctx.compilationUnit = f->function()->compilationUnit;
ctx.lookups = ctx.compilationUnit->runtimeLookups;
- ctx.outer = f->scope;
+ ctx.outer = f->scope();
ctx.locals = v4->stackPush(f->varCount());
while (callData->argc < (int)f->formalParameterCount()) {
callData->args[callData->argc] = Encode::undefined();
++callData->argc;
}
- Q_ASSERT(v4->currentContext() == &ctx);
+ Q_ASSERT(v4->currentContext()->d() == &ctx);
- Scoped<Object> result(scope, Q_V4_PROFILE(v4, &ctx, f->function));
+ Scoped<Object> result(scope, Q_V4_PROFILE(v4, reinterpret_cast<CallContext *>(&ctx), f->function()));
- if (f->function->compiledFunction->hasQmlDependencies())
- QmlContextWrapper::registerQmlDependencies(v4, f->function->compiledFunction);
+ if (f->function()->compiledFunction->hasQmlDependencies())
+ QmlContextWrapper::registerQmlDependencies(v4, f->function()->compiledFunction);
if (!result)
return callData->thisObject.asReturnedValue();
@@ -501,7 +486,7 @@ ReturnedValue SimpleScriptFunction::construct(Managed *that, CallData *callData)
ReturnedValue SimpleScriptFunction::call(Managed *that, CallData *callData)
{
- ExecutionEngine *v4 = that->internalClass->engine;
+ ExecutionEngine *v4 = that->internalClass()->engine;
if (v4->hasException)
return Encode::undefined();
CHECK_STACK_LIMITS(v4);
@@ -512,24 +497,24 @@ ReturnedValue SimpleScriptFunction::call(Managed *that, CallData *callData)
ExecutionContext *context = v4->currentContext();
ExecutionContextSaver ctxSaver(context);
- CallContext ctx(v4);
- ctx.strictMode = f->strictMode;
+ CallContext::Data ctx(v4);
+ ctx.strictMode = f->strictMode();
ctx.callData = callData;
ctx.function = f;
- ctx.compilationUnit = f->function->compilationUnit;
+ ctx.compilationUnit = f->function()->compilationUnit;
ctx.lookups = ctx.compilationUnit->runtimeLookups;
- ctx.outer = f->scope;
+ ctx.outer = f->scope();
ctx.locals = v4->stackPush(f->varCount());
while (callData->argc < (int)f->formalParameterCount()) {
callData->args[callData->argc] = Encode::undefined();
++callData->argc;
}
- Q_ASSERT(v4->currentContext() == &ctx);
+ Q_ASSERT(v4->currentContext()->d() == &ctx);
- ScopedValue result(scope, Q_V4_PROFILE(v4, &ctx, f->function));
+ ScopedValue result(scope, Q_V4_PROFILE(v4, reinterpret_cast<CallContext *>(&ctx), f->function()));
- if (f->function->compiledFunction->hasQmlDependencies())
- QmlContextWrapper::registerQmlDependencies(v4, f->function->compiledFunction);
+ if (f->function()->compiledFunction->hasQmlDependencies())
+ QmlContextWrapper::registerQmlDependencies(v4, f->function()->compiledFunction);
return result.asReturnedValue();
}
@@ -538,10 +523,10 @@ InternalClass *SimpleScriptFunction::internalClassForConstructor()
{
ReturnedValue proto = protoProperty();
InternalClass *classForConstructor;
- Scope scope(internalClass->engine);
+ Scope scope(internalClass()->engine);
ScopedObject p(scope, proto);
if (p)
- classForConstructor = internalClass->engine->constructClass->changePrototype(p.getPointer());
+ classForConstructor = internalClass()->engine->constructClass->changePrototype(p.getPointer());
else
classForConstructor = scope.engine->objectClass;
@@ -552,8 +537,8 @@ InternalClass *SimpleScriptFunction::internalClassForConstructor()
DEFINE_OBJECT_VTABLE(BuiltinFunction);
-BuiltinFunction::BuiltinFunction(ExecutionContext *scope, const StringRef name, ReturnedValue (*code)(CallContext *))
- : FunctionObject(scope, name)
+BuiltinFunction::Data::Data(ExecutionContext *scope, String *name, ReturnedValue (*code)(CallContext *))
+ : FunctionObject::Data(scope, name)
, code(code)
{
setVTable(staticVTable());
@@ -561,13 +546,13 @@ BuiltinFunction::BuiltinFunction(ExecutionContext *scope, const StringRef name,
ReturnedValue BuiltinFunction::construct(Managed *f, CallData *)
{
- return f->internalClass->engine->currentContext()->throwTypeError();
+ return f->internalClass()->engine->currentContext()->throwTypeError();
}
ReturnedValue BuiltinFunction::call(Managed *that, CallData *callData)
{
BuiltinFunction *f = static_cast<BuiltinFunction *>(that);
- ExecutionEngine *v4 = f->internalClass->engine;
+ ExecutionEngine *v4 = f->internalClass()->engine;
if (v4->hasException)
return Encode::undefined();
CHECK_STACK_LIMITS(v4);
@@ -575,18 +560,18 @@ ReturnedValue BuiltinFunction::call(Managed *that, CallData *callData)
ExecutionContext *context = v4->currentContext();
ExecutionContextSaver ctxSaver(context);
- CallContext ctx(v4);
- ctx.strictMode = f->scope->strictMode; // ### needed? scope or parent context?
+ CallContext::Data ctx(v4);
+ ctx.strictMode = f->scope()->d()->strictMode; // ### needed? scope or parent context?
ctx.callData = callData;
- Q_ASSERT(v4->currentContext() == &ctx);
+ Q_ASSERT(v4->currentContext()->d() == &ctx);
- return f->code(&ctx);
+ return f->d()->code(reinterpret_cast<CallContext *>(&ctx));
}
ReturnedValue IndexedBuiltinFunction::call(Managed *that, CallData *callData)
{
IndexedBuiltinFunction *f = static_cast<IndexedBuiltinFunction *>(that);
- ExecutionEngine *v4 = f->internalClass->engine;
+ ExecutionEngine *v4 = f->internalClass()->engine;
if (v4->hasException)
return Encode::undefined();
CHECK_STACK_LIMITS(v4);
@@ -594,82 +579,76 @@ ReturnedValue IndexedBuiltinFunction::call(Managed *that, CallData *callData)
ExecutionContext *context = v4->currentContext();
ExecutionContextSaver ctxSaver(context);
- CallContext ctx(v4);
- ctx.strictMode = f->scope->strictMode; // ### needed? scope or parent context?
+ CallContext::Data ctx(v4);
+ ctx.strictMode = f->scope()->d()->strictMode; // ### needed? scope or parent context?
ctx.callData = callData;
- Q_ASSERT(v4->currentContext() == &ctx);
+ Q_ASSERT(v4->currentContext()->d() == &ctx);
- return f->code(&ctx, f->index);
+ return f->d()->code(reinterpret_cast<CallContext *>(&ctx), f->d()->index);
}
DEFINE_OBJECT_VTABLE(IndexedBuiltinFunction);
DEFINE_OBJECT_VTABLE(BoundFunction);
-BoundFunction::BoundFunction(ExecutionContext *scope, FunctionObjectRef target, const ValueRef boundThis, const QVector<Value> &boundArgs)
- : FunctionObject(scope, QStringLiteral("__bound function__"))
+BoundFunction::Data::Data(ExecutionContext *scope, FunctionObject *target, const ValueRef boundThis, const Members &boundArgs)
+ : FunctionObject::Data(scope, QStringLiteral("__bound function__"))
, target(target)
, boundArgs(boundArgs)
{
+ this->boundThis = boundThis;
setVTable(staticVTable());
subtype = FunctionObject::BoundFunction;
- this->boundThis = boundThis;
Scope s(scope);
- ScopedValue protectThis(s, this);
+ ScopedObject f(s, this);
- ScopedValue l(s, target->get(scope->engine->id_length));
+ ScopedValue l(s, target->get(s.engine->id_length));
int len = l->toUInt32();
len -= boundArgs.size();
if (len < 0)
len = 0;
- defineReadonlyProperty(scope->engine->id_length, Primitive::fromInt32(len));
+ f->defineReadonlyProperty(s.engine->id_length, Primitive::fromInt32(len));
- ExecutionEngine *v4 = scope->engine;
+ ExecutionEngine *v4 = s.engine;
Property pd(v4->thrower, v4->thrower);
- insertMember(scope->engine->id_arguments, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
- insertMember(scope->engine->id_caller, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
-}
-
-void BoundFunction::destroy(Managed *that)
-{
- static_cast<BoundFunction *>(that)->~BoundFunction();
+ f->insertMember(s.engine->id_arguments, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
+ f->insertMember(s.engine->id_caller, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
}
ReturnedValue BoundFunction::call(Managed *that, CallData *dd)
{
BoundFunction *f = static_cast<BoundFunction *>(that);
- Scope scope(f->scope->engine);
+ Scope scope(f->scope()->d()->engine);
if (scope.hasException())
return Encode::undefined();
- ScopedCallData callData(scope, f->boundArgs.size() + dd->argc);
- callData->thisObject = f->boundThis;
- memcpy(callData->args, f->boundArgs.constData(), f->boundArgs.size()*sizeof(Value));
- memcpy(callData->args + f->boundArgs.size(), dd->args, dd->argc*sizeof(Value));
- return f->target->call(callData);
+ ScopedCallData callData(scope, f->boundArgs().size() + dd->argc);
+ callData->thisObject = f->boundThis();
+ memcpy(callData->args, f->boundArgs().data(), f->boundArgs().size()*sizeof(Value));
+ memcpy(callData->args + f->boundArgs().size(), dd->args, dd->argc*sizeof(Value));
+ return f->target()->call(callData);
}
ReturnedValue BoundFunction::construct(Managed *that, CallData *dd)
{
BoundFunction *f = static_cast<BoundFunction *>(that);
- Scope scope(f->scope->engine);
+ Scope scope(f->scope()->d()->engine);
if (scope.hasException())
return Encode::undefined();
- ScopedCallData callData(scope, f->boundArgs.size() + dd->argc);
- memcpy(callData->args, f->boundArgs.constData(), f->boundArgs.size()*sizeof(Value));
- memcpy(callData->args + f->boundArgs.size(), dd->args, dd->argc*sizeof(Value));
- return f->target->construct(callData);
+ ScopedCallData callData(scope, f->boundArgs().size() + dd->argc);
+ memcpy(callData->args, f->boundArgs().data(), f->boundArgs().size()*sizeof(Value));
+ memcpy(callData->args + f->boundArgs().size(), dd->args, dd->argc*sizeof(Value));
+ return f->target()->construct(callData);
}
void BoundFunction::markObjects(Managed *that, ExecutionEngine *e)
{
BoundFunction *o = static_cast<BoundFunction *>(that);
- o->target->mark(e);
- o->boundThis.mark(e);
- for (int i = 0; i < o->boundArgs.size(); ++i)
- o->boundArgs.at(i).mark(e);
+ o->target()->mark(e);
+ o->boundThis().mark(e);
+ o->boundArgs().mark(e);
FunctionObject::markObjects(that, e);
}
diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h
index 5b832d0595..907b660911 100644
--- a/src/qml/jsruntime/qv4functionobject_p.h
+++ b/src/qml/jsruntime/qv4functionobject_p.h
@@ -51,6 +51,7 @@
#include "qv4property_p.h"
#include "qv4function_p.h"
#include "qv4objectiterator_p.h"
+#include "qv4mm_p.h"
#include <QtCore/QString>
#include <QtCore/QHash>
@@ -94,7 +95,17 @@ struct InternalClass;
struct Lookup;
struct Q_QML_EXPORT FunctionObject: Object {
- V4_OBJECT
+ struct Q_QML_PRIVATE_EXPORT Data : Object::Data {
+ Data(ExecutionContext *scope, String *name, bool createProto = false);
+ Data(ExecutionContext *scope, const QString &name = QString(), bool createProto = false);
+ Data(ExecutionContext *scope, const ReturnedValue name);
+ Data(InternalClass *ic);
+ ~Data();
+
+ ExecutionContext *scope;
+ Function *function;
+ };
+ V4_OBJECT(Object)
Q_MANAGED_TYPE(FunctionObject)
enum {
IsFunctionObject = true
@@ -111,18 +122,15 @@ struct Q_QML_EXPORT FunctionObject: Object {
Index_ProtoConstructor = 0
};
- ExecutionContext *scope;
- ReturnedValue name();
- unsigned int formalParameterCount() { return function ? function->compiledFunction->nFormals : 0; }
- unsigned int varCount() { return function ? function->compiledFunction->nLocals : 0; }
- Function *function;
- FunctionObject(ExecutionContext *scope, const StringRef name, bool createProto = false);
- FunctionObject(ExecutionContext *scope, const QString &name = QString(), bool createProto = false);
- FunctionObject(ExecutionContext *scope, const ReturnedValue name);
- ~FunctionObject();
+ ExecutionContext *scope() { return d()->scope; }
+ Function *function() { return d()->function; }
+
+ ReturnedValue name();
+ unsigned int formalParameterCount() { return function() ? function()->compiledFunction->nFormals : 0; }
+ unsigned int varCount() { return function() ? function()->compiledFunction->nLocals : 0; }
- void init(const StringRef name, bool createProto);
+ void init(String *name, bool createProto);
ReturnedValue newInstance();
@@ -130,6 +138,9 @@ struct Q_QML_EXPORT FunctionObject: Object {
using Object::call;
static ReturnedValue construct(Managed *that, CallData *);
static ReturnedValue call(Managed *that, CallData *d);
+ static void destroy(Managed *m) {
+ static_cast<FunctionObject *>(m)->d()->~Data();
+ }
static FunctionObject *cast(const Value &v) {
return v.asFunctionObject();
@@ -137,14 +148,13 @@ struct Q_QML_EXPORT FunctionObject: Object {
static FunctionObject *createScriptFunction(ExecutionContext *scope, Function *function, bool createProto = true);
- ReturnedValue protoProperty() { return memberData[Index_Prototype].asReturnedValue(); }
+ ReturnedValue protoProperty() { return memberData()[Index_Prototype].asReturnedValue(); }
-protected:
- FunctionObject(InternalClass *ic);
+ bool needsActivation() const { return d()->needsActivation; }
+ bool strictMode() const { return d()->strictMode; }
+ bool bindingKeyFlag() const { return d()->bindingKeyFlag; }
static void markObjects(Managed *that, ExecutionEngine *e);
- static void destroy(Managed *that)
- { static_cast<FunctionObject*>(that)->~FunctionObject(); }
};
template<>
@@ -152,12 +162,13 @@ inline FunctionObject *value_cast(const Value &v) {
return v.asFunctionObject();
}
-DEFINE_REF(FunctionObject, Object);
-
struct FunctionCtor: FunctionObject
{
- V4_OBJECT
- FunctionCtor(ExecutionContext *scope);
+ struct Data : FunctionObject::Data {
+ Data(ExecutionContext *scope);
+ };
+
+ V4_OBJECT(FunctionObject)
static ReturnedValue construct(Managed *that, CallData *callData);
static ReturnedValue call(Managed *that, CallData *callData);
@@ -165,8 +176,12 @@ struct FunctionCtor: FunctionObject
struct FunctionPrototype: FunctionObject
{
- FunctionPrototype(InternalClass *ic);
- void init(ExecutionEngine *engine, ObjectRef ctor);
+ struct Data : FunctionObject::Data {
+ Data(InternalClass *ic);
+ };
+ V4_OBJECT(FunctionObject)
+
+ void init(ExecutionEngine *engine, Object *ctor);
static ReturnedValue method_toString(CallContext *ctx);
static ReturnedValue method_apply(CallContext *ctx);
@@ -174,11 +189,17 @@ struct FunctionPrototype: FunctionObject
static ReturnedValue method_bind(CallContext *ctx);
};
-struct BuiltinFunction: FunctionObject {
- V4_OBJECT
- ReturnedValue (*code)(CallContext *);
+struct Q_QML_EXPORT BuiltinFunction: FunctionObject {
+ struct Q_QML_EXPORT Data : FunctionObject::Data {
+ Data(ExecutionContext *scope, String *name, ReturnedValue (*code)(CallContext *));
+ ReturnedValue (*code)(CallContext *);
+ };
+ V4_OBJECT(FunctionObject)
- BuiltinFunction(ExecutionContext *scope, const StringRef name, ReturnedValue (*code)(CallContext *));
+ static BuiltinFunction *create(ExecutionContext *scope, String *name, ReturnedValue (*code)(CallContext *))
+ {
+ return scope->engine()->memoryManager->alloc<BuiltinFunction>(scope, name, code);
+ }
static ReturnedValue construct(Managed *, CallData *);
static ReturnedValue call(Managed *that, CallData *callData);
@@ -186,18 +207,18 @@ struct BuiltinFunction: FunctionObject {
struct IndexedBuiltinFunction: FunctionObject
{
- V4_OBJECT
-
- ReturnedValue (*code)(CallContext *ctx, uint index);
- uint index;
-
- IndexedBuiltinFunction(ExecutionContext *scope, uint index, ReturnedValue (*code)(CallContext *ctx, uint index))
- : FunctionObject(scope)
- , code(code)
- , index(index)
- {
- setVTable(staticVTable());
- }
+ struct Data : FunctionObject::Data {
+ Data(ExecutionContext *scope, uint index, ReturnedValue (*code)(CallContext *ctx, uint index))
+ : FunctionObject::Data(scope),
+ code(code)
+ , index(index)
+ {
+ setVTable(staticVTable());
+ }
+ ReturnedValue (*code)(CallContext *, uint index);
+ uint index;
+ };
+ V4_OBJECT(FunctionObject)
static ReturnedValue construct(Managed *m, CallData *)
{
@@ -209,8 +230,10 @@ struct IndexedBuiltinFunction: FunctionObject
struct SimpleScriptFunction: FunctionObject {
- V4_OBJECT
- SimpleScriptFunction(ExecutionContext *scope, Function *function, bool createProto);
+ struct Data : FunctionObject::Data {
+ Data(ExecutionContext *scope, Function *function, bool createProto);
+ };
+ V4_OBJECT(FunctionObject)
static ReturnedValue construct(Managed *, CallData *callData);
static ReturnedValue call(Managed *that, CallData *callData);
@@ -219,8 +242,10 @@ struct SimpleScriptFunction: FunctionObject {
};
struct ScriptFunction: SimpleScriptFunction {
- V4_OBJECT
- ScriptFunction(ExecutionContext *scope, Function *function);
+ struct Data : SimpleScriptFunction::Data {
+ Data(ExecutionContext *scope, Function *function);
+ };
+ V4_OBJECT(FunctionObject)
static ReturnedValue construct(Managed *, CallData *callData);
static ReturnedValue call(Managed *that, CallData *callData);
@@ -228,19 +253,26 @@ struct ScriptFunction: SimpleScriptFunction {
struct BoundFunction: FunctionObject {
- V4_OBJECT
- FunctionObject *target;
- Value boundThis;
- QVector<Value> boundArgs;
+ struct Data : FunctionObject::Data {
+ Data(ExecutionContext *scope, FunctionObject *target, const ValueRef boundThis, const Members &boundArgs);
+ FunctionObject *target;
+ Value boundThis;
+ Members boundArgs;
+ };
+ V4_OBJECT(FunctionObject)
- BoundFunction(ExecutionContext *scope, FunctionObjectRef target, const ValueRef boundThis, const QVector<Value> &boundArgs);
- ~BoundFunction() {}
+ static BoundFunction *create(ExecutionContext *scope, FunctionObject *target, const ValueRef boundThis, const QV4::Members &boundArgs)
+ {
+ return scope->engine()->memoryManager->alloc<BoundFunction>(scope, target, boundThis, boundArgs);
+ }
+ FunctionObject *target() { return d()->target; }
+ Value boundThis() const { return d()->boundThis; }
+ Members boundArgs() const { return d()->boundArgs; }
static ReturnedValue construct(Managed *, CallData *d);
static ReturnedValue call(Managed *that, CallData *dd);
- static void destroy(Managed *);
static void markObjects(Managed *that, ExecutionEngine *e);
};
diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h
index a00231c3a1..039f5c1e78 100644
--- a/src/qml/jsruntime/qv4global_p.h
+++ b/src/qml/jsruntime/qv4global_p.h
@@ -74,15 +74,19 @@ inline double trunc(double d) { return d > 0 ? floor(d) : ceil(d); }
// Decide whether to enable or disable the JIT
// White list architectures
+//
+// NOTE: This should match the logic in qv4targetplatform_p.h!
-#if defined(Q_PROCESSOR_X86)
+#if defined(Q_PROCESSOR_X86) && (defined(Q_OS_WINDOWS) || defined(Q_OS_LINUX) || defined(Q_OS_QNX) || defined(Q_OS_FREEBSD))
#define V4_ENABLE_JIT
-#elif defined(Q_PROCESSOR_X86_64)
+#elif defined(Q_PROCESSOR_X86_64) && (defined(Q_OS_WINDOWS) || defined(Q_OS_LINUX) || defined(Q_OS_MAC) || defined(Q_OS_FREEBSD))
#define V4_ENABLE_JIT
#elif defined(Q_PROCESSOR_ARM_32)
#if defined(thumb2) || defined(__thumb2__) || ((defined(__thumb) || defined(__thumb__)) && __TARGET_ARCH_THUMB-0 == 4)
#define V4_ENABLE_JIT
+#elif defined(__ARM_ARCH_ISA_THUMB) && __ARM_ARCH_ISA_THUMB == 2 // clang 3.5 and later will set this if the core supports the Thumb-2 ISA.
+#define V4_ENABLE_JIT
#endif
#endif
@@ -161,12 +165,6 @@ template<typename T> struct Returned;
typedef Returned<String> ReturnedString;
typedef Returned<Object> ReturnedObject;
typedef Returned<FunctionObject> ReturnedFunctionObject;
-struct ManagedRef;
-struct StringRef;
-struct ObjectRef;
-struct ArrayObjectRef;
-struct FunctionObjectRef;
-struct RegExpRef;
struct PersistentValuePrivate;
class PersistentValue;
diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp
index eb0994c1e6..fc4a097915 100644
--- a/src/qml/jsruntime/qv4globalobject.cpp
+++ b/src/qml/jsruntime/qv4globalobject.cpp
@@ -346,11 +346,13 @@ static QString decode(const QString &input, DecodeMode decodeMode, bool *ok)
DEFINE_OBJECT_VTABLE(EvalFunction);
-EvalFunction::EvalFunction(ExecutionContext *scope)
- : FunctionObject(scope, scope->engine->id_eval)
+EvalFunction::Data::Data(ExecutionContext *scope)
+ : FunctionObject::Data(scope, scope->d()->engine->id_eval)
{
setVTable(staticVTable());
- defineReadonlyProperty(scope->engine->id_length, Primitive::fromInt32(1));
+ Scope s(scope);
+ ScopedFunctionObject f(s, this);
+ f->defineReadonlyProperty(s.engine->id_length, Primitive::fromInt32(1));
}
ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall)
@@ -363,16 +365,16 @@ ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall)
ContextStateSaver(ExecutionContext *context)
: savedContext(context)
- , strictMode(context->strictMode)
- , evalCode(context->currentEvalCode)
- , compilationUnit(context->compilationUnit)
+ , strictMode(context->d()->strictMode)
+ , evalCode(context->d()->currentEvalCode)
+ , compilationUnit(context->d()->compilationUnit)
{}
~ContextStateSaver()
{
- savedContext->strictMode = strictMode;
- savedContext->currentEvalCode = evalCode;
- savedContext->compilationUnit = compilationUnit;
+ savedContext->d()->strictMode = strictMode;
+ savedContext->d()->currentEvalCode = evalCode;
+ savedContext->d()->compilationUnit = compilationUnit;
}
};
@@ -396,10 +398,10 @@ ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall)
return callData->args[0].asReturnedValue();
const QString code = callData->args[0].stringValue()->toQString();
- bool inheritContext = !ctx->strictMode;
+ bool inheritContext = !ctx->d()->strictMode;
Script script(ctx, code, QStringLiteral("eval code"));
- script.strictMode = (directCall && parentContext->strictMode);
+ script.strictMode = (directCall && parentContext->d()->strictMode);
script.inheritContext = inheritContext;
script.parse();
if (scope.engine->hasException)
@@ -409,14 +411,14 @@ ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall)
if (!function)
return Encode::undefined();
- strictMode = function->isStrict() || (ctx->strictMode);
+ d()->strictMode = function->isStrict() || (ctx->d()->strictMode);
- needsActivation = function->needsActivation();
+ d()->needsActivation = function->needsActivation();
- if (strictMode) {
+ if (strictMode()) {
ScopedFunctionObject e(scope, FunctionObject::createScriptFunction(ctx, function));
ScopedCallData callData(scope, 0);
- callData->thisObject = ctx->callData->thisObject;
+ callData->thisObject = ctx->d()->callData->thisObject;
return e->call(callData);
}
@@ -424,12 +426,12 @@ ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall)
ExecutionContext::EvalCode evalCode;
evalCode.function = function;
- evalCode.next = ctx->currentEvalCode;
- ctx->currentEvalCode = &evalCode;
+ evalCode.next = ctx->d()->currentEvalCode;
+ ctx->d()->currentEvalCode = &evalCode;
// set the correct strict mode flag on the context
- ctx->strictMode = strictMode;
- ctx->compilationUnit = function->compilationUnit;
+ ctx->d()->strictMode = strictMode();
+ ctx->d()->compilationUnit = function->compilationUnit;
return function->code(ctx, function->codeData);
}
@@ -470,7 +472,7 @@ ReturnedValue GlobalFunctions::method_parseInt(CallContext *ctx)
String *inputString = string->toString(ctx); // 1
QString trimmed = inputString->toQString().trimmed(); // 2
- if (ctx->engine->hasException)
+ if (ctx->d()->engine->hasException)
return Encode::undefined();
const QChar *pos = trimmed.constData();
@@ -574,117 +576,117 @@ ReturnedValue GlobalFunctions::method_parseFloat(CallContext *ctx)
/// isNaN [15.1.2.4]
ReturnedValue GlobalFunctions::method_isNaN(CallContext *ctx)
{
- if (!ctx->callData->argc)
+ if (!ctx->d()->callData->argc)
// undefined gets converted to NaN
return Encode(true);
- if (ctx->callData->args[0].integerCompatible())
+ if (ctx->d()->callData->args[0].integerCompatible())
return Encode(false);
- double d = ctx->callData->args[0].toNumber();
+ double d = ctx->d()->callData->args[0].toNumber();
return Encode((bool)std::isnan(d));
}
/// isFinite [15.1.2.5]
ReturnedValue GlobalFunctions::method_isFinite(CallContext *ctx)
{
- if (!ctx->callData->argc)
+ if (!ctx->d()->callData->argc)
// undefined gets converted to NaN
return Encode(false);
- if (ctx->callData->args[0].integerCompatible())
+ if (ctx->d()->callData->args[0].integerCompatible())
return Encode(true);
- double d = ctx->callData->args[0].toNumber();
+ double d = ctx->d()->callData->args[0].toNumber();
return Encode((bool)std::isfinite(d));
}
/// decodeURI [15.1.3.1]
ReturnedValue GlobalFunctions::method_decodeURI(CallContext *context)
{
- if (context->callData->argc == 0)
+ if (context->d()->callData->argc == 0)
return Encode::undefined();
- QString uriString = context->callData->args[0].toString(context)->toQString();
+ QString uriString = context->d()->callData->args[0].toString(context)->toQString();
bool ok;
QString out = decode(uriString, DecodeNonReserved, &ok);
if (!ok) {
Scope scope(context);
- ScopedString s(scope, context->engine->newString(QStringLiteral("malformed URI sequence")));
+ ScopedString s(scope, context->d()->engine->newString(QStringLiteral("malformed URI sequence")));
return context->throwURIError(s);
}
- return context->engine->newString(out)->asReturnedValue();
+ return context->d()->engine->newString(out)->asReturnedValue();
}
/// decodeURIComponent [15.1.3.2]
ReturnedValue GlobalFunctions::method_decodeURIComponent(CallContext *context)
{
- if (context->callData->argc == 0)
+ if (context->d()->callData->argc == 0)
return Encode::undefined();
- QString uriString = context->callData->args[0].toString(context)->toQString();
+ QString uriString = context->d()->callData->args[0].toString(context)->toQString();
bool ok;
QString out = decode(uriString, DecodeAll, &ok);
if (!ok) {
Scope scope(context);
- ScopedString s(scope, context->engine->newString(QStringLiteral("malformed URI sequence")));
+ ScopedString s(scope, context->d()->engine->newString(QStringLiteral("malformed URI sequence")));
return context->throwURIError(s);
}
- return context->engine->newString(out)->asReturnedValue();
+ return context->d()->engine->newString(out)->asReturnedValue();
}
/// encodeURI [15.1.3.3]
ReturnedValue GlobalFunctions::method_encodeURI(CallContext *context)
{
- if (context->callData->argc == 0)
+ if (context->d()->callData->argc == 0)
return Encode::undefined();
- QString uriString = context->callData->args[0].toString(context)->toQString();
+ QString uriString = context->d()->callData->args[0].toString(context)->toQString();
bool ok;
QString out = encode(uriString, uriUnescapedReserved, &ok);
if (!ok) {
Scope scope(context);
- ScopedString s(scope, context->engine->newString(QStringLiteral("malformed URI sequence")));
+ ScopedString s(scope, context->d()->engine->newString(QStringLiteral("malformed URI sequence")));
return context->throwURIError(s);
}
- return context->engine->newString(out)->asReturnedValue();
+ return context->d()->engine->newString(out)->asReturnedValue();
}
/// encodeURIComponent [15.1.3.4]
ReturnedValue GlobalFunctions::method_encodeURIComponent(CallContext *context)
{
- if (context->callData->argc == 0)
+ if (context->d()->callData->argc == 0)
return Encode::undefined();
- QString uriString = context->callData->args[0].toString(context)->toQString();
+ QString uriString = context->d()->callData->args[0].toString(context)->toQString();
bool ok;
QString out = encode(uriString, uriUnescaped, &ok);
if (!ok) {
Scope scope(context);
- ScopedString s(scope, context->engine->newString(QStringLiteral("malformed URI sequence")));
+ ScopedString s(scope, context->d()->engine->newString(QStringLiteral("malformed URI sequence")));
return context->throwURIError(s);
}
- return context->engine->newString(out)->asReturnedValue();
+ return context->d()->engine->newString(out)->asReturnedValue();
}
ReturnedValue GlobalFunctions::method_escape(CallContext *context)
{
- if (!context->callData->argc)
- return context->engine->newString(QStringLiteral("undefined"))->asReturnedValue();
+ if (!context->d()->callData->argc)
+ return context->d()->engine->newString(QStringLiteral("undefined"))->asReturnedValue();
- QString str = context->callData->args[0].toString(context)->toQString();
- return context->engine->newString(escape(str))->asReturnedValue();
+ QString str = context->d()->callData->args[0].toString(context)->toQString();
+ return context->d()->engine->newString(escape(str))->asReturnedValue();
}
ReturnedValue GlobalFunctions::method_unescape(CallContext *context)
{
- if (!context->callData->argc)
- return context->engine->newString(QStringLiteral("undefined"))->asReturnedValue();
+ if (!context->d()->callData->argc)
+ return context->d()->engine->newString(QStringLiteral("undefined"))->asReturnedValue();
- QString str = context->callData->args[0].toString(context)->toQString();
- return context->engine->newString(unescape(str))->asReturnedValue();
+ QString str = context->d()->callData->args[0].toString(context)->toQString();
+ return context->d()->engine->newString(unescape(str))->asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4globalobject_p.h b/src/qml/jsruntime/qv4globalobject_p.h
index 63823acc19..b3fcb0c89b 100644
--- a/src/qml/jsruntime/qv4globalobject_p.h
+++ b/src/qml/jsruntime/qv4globalobject_p.h
@@ -50,8 +50,11 @@ namespace QV4 {
struct Q_QML_EXPORT EvalFunction : FunctionObject
{
- V4_OBJECT
- EvalFunction(ExecutionContext *scope);
+ struct Data : FunctionObject::Data {
+ Data(ExecutionContext *scope);
+ };
+
+ V4_OBJECT(FunctionObject)
ReturnedValue evalCall(CallData *callData, bool directCall);
diff --git a/src/qml/jsruntime/qv4identifier.cpp b/src/qml/jsruntime/qv4identifier.cpp
index 87fbd6f8e4..bbb756bab3 100644
--- a/src/qml/jsruntime/qv4identifier.cpp
+++ b/src/qml/jsruntime/qv4identifier.cpp
@@ -149,8 +149,8 @@ const IdentifierHashEntry *IdentifierHashBase::lookup(String *str) const
{
if (!d)
return 0;
- if (str->identifier)
- return lookup(str->identifier);
+ if (str->d()->identifier)
+ return lookup(str->d()->identifier);
return lookup(str->toQString());
}
diff --git a/src/qml/jsruntime/qv4identifiertable.cpp b/src/qml/jsruntime/qv4identifiertable.cpp
index e300a4811e..8627438fe1 100644
--- a/src/qml/jsruntime/qv4identifiertable.cpp
+++ b/src/qml/jsruntime/qv4identifiertable.cpp
@@ -69,7 +69,7 @@ IdentifierTable::~IdentifierTable()
{
for (int i = 0; i < alloc; ++i)
if (entries[i])
- delete entries[i]->identifier;
+ delete entries[i]->d()->identifier;
free(entries);
}
@@ -77,12 +77,12 @@ void IdentifierTable::addEntry(String *str)
{
uint hash = str->hashValue();
- if (str->subtype == String::StringType_ArrayIndex)
+ if (str->subtype() == String::StringType_ArrayIndex)
return;
- str->identifier = new Identifier;
- str->identifier->string = str->toQString();
- str->identifier->hashValue = hash;
+ str->d()->identifier = new Identifier;
+ str->d()->identifier->string = str->toQString();
+ str->d()->identifier->hashValue = hash;
bool grow = (alloc <= size*2);
@@ -95,7 +95,7 @@ void IdentifierTable::addEntry(String *str)
String *e = entries[i];
if (!e)
continue;
- uint idx = e->stringHash % newAlloc;
+ uint idx = e->d()->stringHash % newAlloc;
while (newEntries[idx]) {
++idx;
idx %= newAlloc;
@@ -123,7 +123,7 @@ String *IdentifierTable::insertString(const QString &s)
uint hash = String::createHashValue(s.constData(), s.length());
uint idx = hash % alloc;
while (String *e = entries[idx]) {
- if (e->stringHash == hash && e->toQString() == s)
+ if (e->d()->stringHash == hash && e->toQString() == s)
return e;
++idx;
idx %= alloc;
@@ -137,29 +137,29 @@ String *IdentifierTable::insertString(const QString &s)
Identifier *IdentifierTable::identifierImpl(const String *str)
{
- if (str->identifier)
- return str->identifier;
+ if (str->d()->identifier)
+ return str->d()->identifier;
uint hash = str->hashValue();
- if (str->subtype == String::StringType_ArrayIndex)
+ if (str->subtype() == String::StringType_ArrayIndex)
return 0;
uint idx = hash % alloc;
while (String *e = entries[idx]) {
- if (e->stringHash == hash && e->isEqualTo(str)) {
- str->identifier = e->identifier;
- return e->identifier;
+ if (e->d()->stringHash == hash && e->isEqualTo(str)) {
+ str->d()->identifier = e->d()->identifier;
+ return e->d()->identifier;
}
++idx;
idx %= alloc;
}
addEntry(const_cast<QV4::String *>(str));
- return str->identifier;
+ return str->d()->identifier;
}
Identifier *IdentifierTable::identifier(const QString &s)
{
- return insertString(s)->identifier;
+ return insertString(s)->d()->identifier;
}
Identifier *IdentifierTable::identifier(const char *s, int len)
@@ -171,15 +171,15 @@ Identifier *IdentifierTable::identifier(const char *s, int len)
QLatin1String latin(s, len);
uint idx = hash % alloc;
while (String *e = entries[idx]) {
- if (e->stringHash == hash && e->toQString() == latin)
- return e->identifier;
+ if (e->d()->stringHash == hash && e->toQString() == latin)
+ return e->d()->identifier;
++idx;
idx %= alloc;
}
String *str = engine->newString(QString::fromLatin1(s, len))->getPointer();
addEntry(str);
- return str->identifier;
+ return str->d()->identifier;
}
}
diff --git a/src/qml/jsruntime/qv4identifiertable_p.h b/src/qml/jsruntime/qv4identifiertable_p.h
index 09956fc342..7675d1642e 100644
--- a/src/qml/jsruntime/qv4identifiertable_p.h
+++ b/src/qml/jsruntime/qv4identifiertable_p.h
@@ -69,8 +69,8 @@ public:
String *insertString(const QString &s);
Identifier *identifier(const String *str) {
- if (str->identifier)
- return str->identifier;
+ if (str->d()->identifier)
+ return str->d()->identifier;
return identifierImpl(str);
}
@@ -82,11 +82,11 @@ public:
void mark(ExecutionEngine *e) {
for (int i = 0; i < alloc; ++i) {
String *entry = entries[i];
- if (!entry || entry->markBit)
+ if (!entry || entry->markBit())
continue;
- entry->markBit = 1;
- Q_ASSERT(entry->internalClass->vtable->markObjects);
- entry->internalClass->vtable->markObjects(entry, e);
+ entry->d()->markBit = 1;
+ Q_ASSERT(entry->internalClass()->vtable->markObjects);
+ entry->internalClass()->vtable->markObjects(entry, e);
}
}
};
diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp
index d5bae0e35e..b9576e1bee 100644
--- a/src/qml/jsruntime/qv4include.cpp
+++ b/src/qml/jsruntime/qv4include.cpp
@@ -89,11 +89,11 @@ QV4::ReturnedValue QV4Include::resultValue(QV4::ExecutionEngine *v4, Status stat
QV4::ScopedObject o(scope, v4->newObject());
QV4::ScopedString s(scope);
QV4::ScopedValue v(scope);
- o->put((s = v4->newString(QStringLiteral("OK"))), (v = QV4::Primitive::fromInt32(Ok)));
- o->put((s = v4->newString(QStringLiteral("LOADING"))), (v = QV4::Primitive::fromInt32(Loading)));
- o->put((s = v4->newString(QStringLiteral("NETWORK_ERROR"))), (v = QV4::Primitive::fromInt32(NetworkError)));
- o->put((s = v4->newString(QStringLiteral("EXCEPTION"))), (v = QV4::Primitive::fromInt32(Exception)));
- o->put((s = v4->newString(QStringLiteral("status"))), (v = QV4::Primitive::fromInt32(status)));
+ o->put((s = v4->newString(QStringLiteral("OK"))).getPointer(), (v = QV4::Primitive::fromInt32(Ok)));
+ o->put((s = v4->newString(QStringLiteral("LOADING"))).getPointer(), (v = QV4::Primitive::fromInt32(Loading)));
+ o->put((s = v4->newString(QStringLiteral("NETWORK_ERROR"))).getPointer(), (v = QV4::Primitive::fromInt32(NetworkError)));
+ o->put((s = v4->newString(QStringLiteral("EXCEPTION"))).getPointer(), (v = QV4::Primitive::fromInt32(Exception)));
+ o->put((s = v4->newString(QStringLiteral("status"))).getPointer(), (v = QV4::Primitive::fromInt32(status)));
return o.asReturnedValue();
}
@@ -160,13 +160,13 @@ void QV4Include::finished()
script.run();
if (scope.engine->hasException) {
QV4::ScopedValue ex(scope, ctx->catchException());
- resultObj->put(status, QV4::ScopedValue(scope, QV4::Primitive::fromInt32(Exception)));
- resultObj->put(QV4::ScopedString(scope, v4->newString(QStringLiteral("exception"))), ex);
+ resultObj->put(status.getPointer(), QV4::ScopedValue(scope, QV4::Primitive::fromInt32(Exception)));
+ resultObj->put(v4->newString(QStringLiteral("exception"))->getPointer(), ex);
} else {
- resultObj->put(status, QV4::ScopedValue(scope, QV4::Primitive::fromInt32(Ok)));
+ resultObj->put(status.getPointer(), QV4::ScopedValue(scope, QV4::Primitive::fromInt32(Ok)));
}
} else {
- resultObj->put(QV4::ScopedString(scope, v4->newString(QStringLiteral("status"))), QV4::ScopedValue(scope, QV4::Primitive::fromInt32(NetworkError)));
+ resultObj->put(v4->newString(QStringLiteral("status"))->getPointer(), QV4::ScopedValue(scope, QV4::Primitive::fromInt32(NetworkError)));
}
QV4::ScopedValue cb(scope, m_callbackFunction.value());
@@ -181,27 +181,26 @@ void QV4Include::finished()
*/
QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx)
{
- if (!ctx->callData->argc)
+ if (!ctx->d()->callData->argc)
return QV4::Encode::undefined();
- QV4::ExecutionEngine *v4 = ctx->engine;
- QV4::Scope scope(v4);
- QV8Engine *engine = v4->v8Engine;
- QQmlContextData *context = QV4::QmlContextWrapper::callingContext(v4);
+ QV4::Scope scope(ctx->engine());
+ QV8Engine *engine = scope.engine->v8Engine;
+ QQmlContextData *context = QV4::QmlContextWrapper::callingContext(scope.engine);
if (!context || !context->isJSContext)
V4THROW_ERROR("Qt.include(): Can only be called from JavaScript files");
- QUrl url(ctx->engine->resolvedUrl(ctx->callData->args[0].toQStringNoThrow()));
+ QUrl url(scope.engine->resolvedUrl(ctx->d()->callData->args[0].toQStringNoThrow()));
QV4::ScopedValue callbackFunction(scope, QV4::Primitive::undefinedValue());
- if (ctx->callData->argc >= 2 && ctx->callData->args[1].asFunctionObject())
- callbackFunction = ctx->callData->args[1];
+ if (ctx->d()->callData->argc >= 2 && ctx->d()->callData->args[1].asFunctionObject())
+ callbackFunction = ctx->d()->callData->args[1];
QString localFile = QQmlFile::urlToLocalFileOrQrc(url);
QV4::ScopedValue result(scope);
- QV4::ScopedObject qmlcontextobject(scope, v4->qmlContextObject());
+ QV4::ScopedObject qmlcontextobject(scope, scope.engine->qmlContextObject());
if (localFile.isEmpty()) {
QV4Include *i = new QV4Include(url, engine, context,
@@ -218,21 +217,21 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx)
QString code = QString::fromUtf8(data);
QmlIR::Document::removeScriptPragmas(code);
- QV4::Script script(v4, qmlcontextobject, code, url.toString());
+ QV4::Script script(scope.engine, qmlcontextobject, code, url.toString());
- QV4::ExecutionContext *ctx = v4->currentContext();
+ QV4::ExecutionContext *ctx = scope.engine->currentContext();
script.parse();
- if (!v4->hasException)
+ if (!scope.engine->hasException)
script.run();
- if (v4->hasException) {
+ if (scope.engine->hasException) {
QV4::ScopedValue ex(scope, ctx->catchException());
- result = resultValue(v4, Exception);
- result->asObject()->put(QV4::ScopedString(scope, v4->newString(QStringLiteral("exception"))), ex);
+ result = resultValue(scope.engine, Exception);
+ result->asObject()->put(scope.engine->newString(QStringLiteral("exception"))->getPointer(), ex);
} else {
- result = resultValue(v4, Ok);
+ result = resultValue(scope.engine, Ok);
}
} else {
- result = resultValue(v4, NetworkError);
+ result = resultValue(scope.engine, NetworkError);
}
callback(callbackFunction, result);
diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp
index 3dc20b8e76..2edaf6fe96 100644
--- a/src/qml/jsruntime/qv4internalclass.cpp
+++ b/src/qml/jsruntime/qv4internalclass.cpp
@@ -155,18 +155,18 @@ InternalClass::InternalClass(const QV4::InternalClass &other)
void InternalClass::changeMember(Object *object, String *string, PropertyAttributes data, uint *index)
{
uint idx;
- InternalClass *newClass = object->internalClass->changeMember(string, data, &idx);
+ InternalClass *newClass = object->internalClass()->changeMember(string, data, &idx);
if (index)
*index = idx;
- if (newClass->size > object->internalClass->size) {
- Q_ASSERT(newClass->size == object->internalClass->size + 1);
- memmove(object->memberData.data() + idx + 2, object->memberData.data() + idx + 1, (object->internalClass->size - idx - 1)*sizeof(Value));
- } else if (newClass->size < object->internalClass->size) {
- Q_ASSERT(newClass->size == object->internalClass->size - 1);
- memmove(object->memberData.data() + idx + 1, object->memberData.data() + idx + 2, (object->internalClass->size - idx - 2)*sizeof(Value));
+ if (newClass->size > object->internalClass()->size) {
+ Q_ASSERT(newClass->size == object->internalClass()->size + 1);
+ memmove(object->memberData().data() + idx + 2, object->memberData().data() + idx + 1, (object->internalClass()->size - idx - 1)*sizeof(Value));
+ } else if (newClass->size < object->internalClass()->size) {
+ Q_ASSERT(newClass->size == object->internalClass()->size - 1);
+ memmove(object->memberData().data() + idx + 1, object->memberData().data() + idx + 2, (object->internalClass()->size - idx - 2)*sizeof(Value));
}
- object->internalClass = newClass;
+ object->setInternalClass(newClass);
}
InternalClass *InternalClass::changeMember(String *string, PropertyAttributes data, uint *index)
@@ -181,7 +181,7 @@ InternalClass *InternalClass::changeMember(String *string, PropertyAttributes da
if (data == propertyData.at(idx))
return this;
- Transition t = { { string->identifier }, (int)data.flags() };
+ Transition t = { { string->d()->identifier }, (int)data.flags() };
QHash<Transition, InternalClass *>::const_iterator tit = transitions.constFind(t);
if (tit != transitions.constEnd())
return tit.value();
@@ -271,40 +271,30 @@ InternalClass *InternalClass::changeVTable(const ManagedVTable *vt)
return newClass;
}
-void InternalClass::addMember(Object *object, StringRef string, PropertyAttributes data, uint *index)
-{
- return addMember(object, string.getPointer(), data, index);
-}
-
void InternalClass::addMember(Object *object, String *string, PropertyAttributes data, uint *index)
{
data.resolve();
- object->internalClass->engine->identifierTable->identifier(string);
- if (object->internalClass->propertyTable.lookup(string->identifier) < object->internalClass->size) {
+ object->internalClass()->engine->identifierTable->identifier(string);
+ if (object->internalClass()->propertyTable.lookup(string->d()->identifier) < object->internalClass()->size) {
changeMember(object, string, data, index);
return;
}
uint idx;
- InternalClass *newClass = object->internalClass->addMemberImpl(string, data, &idx);
+ InternalClass *newClass = object->internalClass()->addMemberImpl(string, data, &idx);
if (index)
*index = idx;
- object->internalClass = newClass;
+ object->setInternalClass(newClass);
}
-InternalClass *InternalClass::addMember(StringRef string, PropertyAttributes data, uint *index)
-{
- return addMember(string.getPointer(), data, index);
-}
-
InternalClass *InternalClass::addMember(String *string, PropertyAttributes data, uint *index)
{
data.resolve();
engine->identifierTable->identifier(string);
- if (propertyTable.lookup(string->identifier) < size)
+ if (propertyTable.lookup(string->d()->identifier) < size)
return changeMember(string, data, index);
return addMemberImpl(string, data, index);
@@ -312,7 +302,7 @@ InternalClass *InternalClass::addMember(String *string, PropertyAttributes data,
InternalClass *InternalClass::addMemberImpl(String *string, PropertyAttributes data, uint *index)
{
- Transition t = { { string->identifier }, (int)data.flags() };
+ Transition t = { { string->d()->identifier }, (int)data.flags() };
QHash<Transition, InternalClass *>::const_iterator tit = transitions.constFind(t);
if (index)
@@ -322,7 +312,7 @@ InternalClass *InternalClass::addMemberImpl(String *string, PropertyAttributes d
// create a new class and add it to the tree
InternalClass *newClass = engine->newClass(*this);
- PropertyHash::Entry e = { string->identifier, newClass->size };
+ PropertyHash::Entry e = { string->d()->identifier, newClass->size };
newClass->propertyTable.addEntry(e, newClass->size);
// The incoming string can come from anywhere, so make sure to
@@ -346,15 +336,15 @@ InternalClass *InternalClass::addMemberImpl(String *string, PropertyAttributes d
void InternalClass::removeMember(Object *object, Identifier *id)
{
- InternalClass *oldClass = object->internalClass;
+ InternalClass *oldClass = object->internalClass();
uint propIdx = oldClass->propertyTable.lookup(id);
Q_ASSERT(propIdx < oldClass->size);
Transition t = { { id } , -1 };
- QHash<Transition, InternalClass *>::const_iterator tit = object->internalClass->transitions.constFind(t);
+ QHash<Transition, InternalClass *>::const_iterator tit = object->internalClass()->transitions.constFind(t);
- if (tit != object->internalClass->transitions.constEnd()) {
- object->internalClass = tit.value();
+ if (tit != object->internalClass()->transitions.constEnd()) {
+ object->setInternalClass(tit.value());
} else {
// create a new class and add it to the tree
InternalClass *newClass = oldClass->engine->emptyClass->changeVTable(oldClass->vtable);
@@ -365,24 +355,19 @@ void InternalClass::removeMember(Object *object, Identifier *id)
if (!oldClass->propertyData.at(i).isEmpty())
newClass = newClass->addMember(oldClass->nameMap.at(i), oldClass->propertyData.at(i));
}
- object->internalClass = newClass;
+ object->setInternalClass(newClass);
}
// remove the entry in memberdata
- memmove(object->memberData.data() + propIdx, object->memberData.data() + propIdx + 1, (object->internalClass->size - propIdx)*sizeof(Value));
-
- oldClass->transitions.insert(t, object->internalClass);
-}
+ memmove(object->memberData().data() + propIdx, object->memberData().data() + propIdx + 1, (object->internalClass()->size - propIdx)*sizeof(Value));
-uint InternalClass::find(const StringRef string)
-{
- return find(string.getPointer());
+ oldClass->transitions.insert(t, object->internalClass());
}
uint InternalClass::find(const String *string)
{
engine->identifierTable->identifier(string);
- const Identifier *id = string->identifier;
+ const Identifier *id = string->d()->identifier;
uint index = propertyTable.lookup(id);
if (index < size)
diff --git a/src/qml/jsruntime/qv4internalclass_p.h b/src/qml/jsruntime/qv4internalclass_p.h
index bd1828a146..830d5f792f 100644
--- a/src/qml/jsruntime/qv4internalclass_p.h
+++ b/src/qml/jsruntime/qv4internalclass_p.h
@@ -234,14 +234,11 @@ struct InternalClass : public QQmlJS::Managed {
static InternalClass *create(ExecutionEngine *engine, const ManagedVTable *vtable, Object *proto);
InternalClass *changePrototype(Object *proto);
InternalClass *changeVTable(const ManagedVTable *vt);
- static void addMember(Object *object, StringRef string, PropertyAttributes data, uint *index);
static void addMember(Object *object, String *string, PropertyAttributes data, uint *index);
- InternalClass *addMember(StringRef string, PropertyAttributes data, uint *index = 0);
InternalClass *addMember(String *string, PropertyAttributes data, uint *index = 0);
InternalClass *changeMember(String *string, PropertyAttributes data, uint *index = 0);
static void changeMember(Object *object, String *string, PropertyAttributes data, uint *index = 0);
static void removeMember(Object *object, Identifier *id);
- uint find(const StringRef string);
uint find(const String *s);
InternalClass *sealed();
diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp
index ca82af1b30..2cbb72e15f 100644
--- a/src/qml/jsruntime/qv4jsonobject.cpp
+++ b/src/qml/jsruntime/qv4jsonobject.cpp
@@ -81,7 +81,7 @@ private:
ReturnedValue parseObject();
ReturnedValue parseArray();
- bool parseMember(ObjectRef o);
+ bool parseMember(Object *o);
bool parseString(QString *string);
bool parseValue(ValueRef val);
bool parseNumber(ValueRef val);
@@ -237,7 +237,7 @@ ReturnedValue JsonParser::parseObject()
BEGIN << "parseObject pos=" << json;
Scope scope(context);
- ScopedObject o(scope, context->engine->newObject());
+ ScopedObject o(scope, context->d()->engine->newObject());
QChar token = nextToken();
while (token == Quote) {
@@ -268,7 +268,7 @@ ReturnedValue JsonParser::parseObject()
/*
member = string name-separator value
*/
-bool JsonParser::parseMember(ObjectRef o)
+bool JsonParser::parseMember(Object *o)
{
BEGIN << "parseMember";
Scope scope(context);
@@ -285,12 +285,12 @@ bool JsonParser::parseMember(ObjectRef o)
if (!parseValue(val))
return false;
- ScopedString s(scope, context->engine->newIdentifier(key));
+ ScopedString s(scope, context->d()->engine->newIdentifier(key));
uint idx = s->asArrayIndex();
if (idx < UINT_MAX) {
o->putIndexed(idx, val);
} else {
- o->insertMember(s, val);
+ o->insertMember(s.getPointer(), val);
}
END;
@@ -304,7 +304,7 @@ ReturnedValue JsonParser::parseArray()
{
Scope scope(context);
BEGIN << "parseArray";
- Scoped<ArrayObject> array(scope, context->engine->newArrayObject());
+ Scoped<ArrayObject> array(scope, context->d()->engine->newArrayObject());
if (++nestingLevel > nestingLimit) {
lastError = QJsonParseError::DeepNesting;
@@ -407,7 +407,7 @@ bool JsonParser::parseValue(ValueRef val)
return false;
DEBUG << "value: string";
END;
- val = context->engine->newString(value);
+ val = context->d()->engine->newString(value);
return true;
}
case BeginArray: {
@@ -656,8 +656,8 @@ struct Stringify
Stringify(ExecutionContext *ctx) : ctx(ctx), replacerFunction(0) {}
QString Str(const QString &key, ValueRef v);
- QString JA(ArrayObjectRef a);
- QString JO(ObjectRef o);
+ QString JA(ArrayObject *a);
+ QString JO(Object *o);
QString makeMember(const QString &key, ValueRef v);
};
@@ -710,21 +710,21 @@ QString Stringify::Str(const QString &key, ValueRef v)
ScopedValue value(scope, *v);
ScopedObject o(scope, value);
if (o) {
- ScopedString s(scope, ctx->engine->newString(QStringLiteral("toJSON")));
- Scoped<FunctionObject> toJSON(scope, o->get(s));
+ ScopedString s(scope, ctx->d()->engine->newString(QStringLiteral("toJSON")));
+ Scoped<FunctionObject> toJSON(scope, o->get(s.getPointer()));
if (!!toJSON) {
ScopedCallData callData(scope, 1);
callData->thisObject = value;
- callData->args[0] = ctx->engine->newString(key);
+ callData->args[0] = ctx->d()->engine->newString(key);
value = toJSON->call(callData);
}
}
if (replacerFunction) {
- ScopedObject holder(scope, ctx->engine->newObject());
+ ScopedObject holder(scope, ctx->d()->engine->newObject());
holder->put(ctx, QString(), value);
ScopedCallData callData(scope, 2);
- callData->args[0] = ctx->engine->newString(key);
+ callData->args[0] = ctx->d()->engine->newString(key);
callData->args[1] = value;
callData->thisObject = holder;
value = replacerFunction->call(callData);
@@ -733,11 +733,11 @@ QString Stringify::Str(const QString &key, ValueRef v)
o = value.asReturnedValue();
if (o) {
if (NumberObject *n = o->asNumberObject())
- value = n->value;
+ value = n->value();
else if (StringObject *so = o->asStringObject())
- value = so->value;
+ value = so->d()->value;
else if (BooleanObject *b =o->asBooleanObject())
- value = b->value;
+ value = b->value();
}
if (value->isNull())
@@ -780,9 +780,9 @@ QString Stringify::makeMember(const QString &key, ValueRef v)
return QString();
}
-QString Stringify::JO(ObjectRef o)
+QString Stringify::JO(Object *o)
{
- if (stack.contains(o.getPointer())) {
+ if (stack.contains(o)) {
ctx->throwTypeError();
return QString();
}
@@ -790,7 +790,7 @@ QString Stringify::JO(ObjectRef o)
Scope scope(ctx);
QString result;
- stack.push(o.getPointer());
+ stack.push(o);
QString stepback = indent;
indent += gap;
@@ -814,7 +814,7 @@ QString Stringify::JO(ObjectRef o)
for (int i = 0; i < propertyList.size(); ++i) {
bool exists;
s = propertyList.at(i);
- ScopedValue v(scope, o->get(s, &exists));
+ ScopedValue v(scope, o->get(s.getPointer(), &exists));
if (!exists)
continue;
QString member = makeMember(s->toQString(), v);
@@ -837,9 +837,9 @@ QString Stringify::JO(ObjectRef o)
return result;
}
-QString Stringify::JA(ArrayObjectRef a)
+QString Stringify::JA(ArrayObject *a)
{
- if (stack.contains(a.getPointer())) {
+ if (stack.contains(a)) {
ctx->throwTypeError();
return QString();
}
@@ -847,7 +847,7 @@ QString Stringify::JA(ArrayObjectRef a)
Scope scope(a->engine());
QString result;
- stack.push(a.getPointer());
+ stack.push(a);
QString stepback = indent;
indent += gap;
@@ -883,14 +883,14 @@ QString Stringify::JA(ArrayObjectRef a)
}
-JsonObject::JsonObject(InternalClass *ic)
- : Object(ic)
+JsonObject::Data::Data(InternalClass *ic)
+ : Object::Data(ic)
{
Scope scope(ic->engine);
- ScopedObject protectThis(scope, this);
+ ScopedObject o(scope, this);
- defineDefaultProperty(QStringLiteral("parse"), method_parse, 2);
- defineDefaultProperty(QStringLiteral("stringify"), method_stringify, 3);
+ o->defineDefaultProperty(QStringLiteral("parse"), method_parse, 2);
+ o->defineDefaultProperty(QStringLiteral("stringify"), method_stringify, 3);
}
@@ -939,9 +939,9 @@ ReturnedValue JsonObject::method_stringify(CallContext *ctx)
ScopedValue s(scope, ctx->argument(2));
if (NumberObject *n = s->asNumberObject())
- s = n->value;
+ s = n->value();
else if (StringObject *so = s->asStringObject())
- s = so->value;
+ s = so->d()->value;
if (s->isNumber()) {
stringify.gap = QString(qMin(10, (int)s->toInteger()), ' ');
@@ -954,7 +954,7 @@ ReturnedValue JsonObject::method_stringify(CallContext *ctx)
QString result = stringify.Str(QString(), arg0);
if (result.isEmpty() || scope.engine->hasException)
return Encode::undefined();
- return ctx->engine->newString(result)->asReturnedValue();
+ return ctx->d()->engine->newString(result)->asReturnedValue();
}
@@ -962,7 +962,7 @@ ReturnedValue JsonObject::method_stringify(CallContext *ctx)
ReturnedValue JsonObject::fromJsonValue(ExecutionEngine *engine, const QJsonValue &value)
{
if (value.isString())
- return engine->currentContext()->engine->newString(value.toString())->asReturnedValue();
+ return engine->currentContext()->d()->engine->newString(value.toString())->asReturnedValue();
else if (value.isDouble())
return Encode(value.toDouble());
else if (value.isBool())
@@ -1008,12 +1008,12 @@ QV4::ReturnedValue JsonObject::fromJsonObject(ExecutionEngine *engine, const QJs
ScopedValue v(scope);
for (QJsonObject::const_iterator it = object.begin(); it != object.end(); ++it) {
v = fromJsonValue(engine, it.value());
- o->put((s = engine->newString(it.key())), v);
+ o->put((s = engine->newString(it.key())).getPointer(), v);
}
return o.asReturnedValue();
}
-QJsonObject JsonObject::toJsonObject(ObjectRef o, V4ObjectSet &visitedObjects)
+QJsonObject JsonObject::toJsonObject(Object *o, V4ObjectSet &visitedObjects)
{
QJsonObject result;
if (!o || o->asFunctionObject())
@@ -1061,7 +1061,7 @@ QV4::ReturnedValue JsonObject::fromJsonArray(ExecutionEngine *engine, const QJso
return a.asReturnedValue();
}
-QJsonArray JsonObject::toJsonArray(ArrayObjectRef a, V4ObjectSet &visitedObjects)
+QJsonArray JsonObject::toJsonArray(ArrayObject *a, V4ObjectSet &visitedObjects)
{
QJsonArray result;
if (!a)
diff --git a/src/qml/jsruntime/qv4jsonobject_p.h b/src/qml/jsruntime/qv4jsonobject_p.h
index 34a4f4dd4b..03d5ad29c8 100644
--- a/src/qml/jsruntime/qv4jsonobject_p.h
+++ b/src/qml/jsruntime/qv4jsonobject_p.h
@@ -51,12 +51,14 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
struct JsonObject : Object {
+ struct Data : Object::Data {
+ Data(InternalClass *ic);
+ };
Q_MANAGED_TYPE(JsonObject)
- V4_OBJECT
+ V4_OBJECT(Object)
private:
typedef QSet<QV4::Object *> V4ObjectSet;
public:
- JsonObject(InternalClass *ic);
static ReturnedValue method_parse(CallContext *ctx);
static ReturnedValue method_stringify(CallContext *ctx);
@@ -67,15 +69,15 @@ public:
static inline QJsonValue toJsonValue(const QV4::ValueRef value)
{ V4ObjectSet visitedObjects; return toJsonValue(value, visitedObjects); }
- static inline QJsonObject toJsonObject(QV4::ObjectRef o)
+ static inline QJsonObject toJsonObject(QV4::Object *o)
{ V4ObjectSet visitedObjects; return toJsonObject(o, visitedObjects); }
- static inline QJsonArray toJsonArray(QV4::ArrayObjectRef a)
+ static inline QJsonArray toJsonArray(QV4::ArrayObject *a)
{ V4ObjectSet visitedObjects; return toJsonArray(a, visitedObjects); }
private:
static QJsonValue toJsonValue(const QV4::ValueRef value, V4ObjectSet &visitedObjects);
- static QJsonObject toJsonObject(QV4::ObjectRef o, V4ObjectSet &visitedObjects);
- static QJsonArray toJsonArray(QV4::ArrayObjectRef a, V4ObjectSet &visitedObjects);
+ static QJsonObject toJsonObject(Object *o, V4ObjectSet &visitedObjects);
+ static QJsonArray toJsonArray(ArrayObject *a, V4ObjectSet &visitedObjects);
};
diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp
index 1155bbf9e9..57154c4779 100644
--- a/src/qml/jsruntime/qv4lookup.cpp
+++ b/src/qml/jsruntime/qv4lookup.cpp
@@ -51,13 +51,13 @@ ReturnedValue Lookup::lookup(ValueRef thisObject, Object *obj, PropertyAttribute
{
int i = 0;
while (i < Size && obj) {
- classList[i] = obj->internalClass;
+ classList[i] = obj->internalClass();
- index = obj->internalClass->find(name);
+ index = obj->internalClass()->find(name);
if (index != UINT_MAX) {
level = i;
- *attrs = obj->internalClass->propertyData.at(index);
- return !attrs->isAccessor() ? obj->memberData[index].asReturnedValue() : obj->getValue(thisObject, obj->propertyAt(index), *attrs);
+ *attrs = obj->internalClass()->propertyData.at(index);
+ return !attrs->isAccessor() ? obj->memberData()[index].asReturnedValue() : obj->getValue(thisObject, obj->propertyAt(index), *attrs);
}
obj = obj->prototype();
@@ -66,10 +66,10 @@ ReturnedValue Lookup::lookup(ValueRef thisObject, Object *obj, PropertyAttribute
level = Size;
while (obj) {
- index = obj->internalClass->find(name);
+ index = obj->internalClass()->find(name);
if (index != UINT_MAX) {
- *attrs = obj->internalClass->propertyData.at(index);
- return !attrs->isAccessor() ? obj->memberData[index].asReturnedValue() : obj->getValue(thisObject, obj->propertyAt(index), *attrs);
+ *attrs = obj->internalClass()->propertyData.at(index);
+ return !attrs->isAccessor() ? obj->memberData()[index].asReturnedValue() : obj->getValue(thisObject, obj->propertyAt(index), *attrs);
}
obj = obj->prototype();
@@ -82,13 +82,13 @@ ReturnedValue Lookup::lookup(Object *obj, PropertyAttributes *attrs)
Object *thisObject = obj;
int i = 0;
while (i < Size && obj) {
- classList[i] = obj->internalClass;
+ classList[i] = obj->internalClass();
- index = obj->internalClass->find(name);
+ index = obj->internalClass()->find(name);
if (index != UINT_MAX) {
level = i;
- *attrs = obj->internalClass->propertyData.at(index);
- return !attrs->isAccessor() ? obj->memberData[index].asReturnedValue() : thisObject->getValue(obj->propertyAt(index), *attrs);
+ *attrs = obj->internalClass()->propertyData.at(index);
+ return !attrs->isAccessor() ? obj->memberData()[index].asReturnedValue() : thisObject->getValue(obj->propertyAt(index), *attrs);
}
obj = obj->prototype();
@@ -97,10 +97,10 @@ ReturnedValue Lookup::lookup(Object *obj, PropertyAttributes *attrs)
level = Size;
while (obj) {
- index = obj->internalClass->find(name);
+ index = obj->internalClass()->find(name);
if (index != UINT_MAX) {
- *attrs = obj->internalClass->propertyData.at(index);
- return !attrs->isAccessor() ? obj->memberData[index].asReturnedValue() : thisObject->getValue(obj->propertyAt(index), *attrs);
+ *attrs = obj->internalClass()->propertyData.at(index);
+ return !attrs->isAccessor() ? obj->memberData()[index].asReturnedValue() : thisObject->getValue(obj->propertyAt(index), *attrs);
}
obj = obj->prototype();
@@ -147,8 +147,8 @@ ReturnedValue Lookup::indexedGetterFallback(Lookup *l, const ValueRef object, co
}
if (idx < UINT_MAX) {
- if (!o->arrayData->hasAttributes()) {
- ScopedValue v(scope, o->arrayData->get(idx));
+ if (!o->arrayData()->hasAttributes()) {
+ ScopedValue v(scope, o->arrayData()->get(idx));
if (!v->isEmpty())
return v->asReturnedValue();
}
@@ -159,7 +159,7 @@ ReturnedValue Lookup::indexedGetterFallback(Lookup *l, const ValueRef object, co
ScopedString name(scope, index->toString(ctx));
if (scope.hasException())
return Encode::undefined();
- return o->get(name);
+ return o->get(name.getPointer());
}
@@ -171,10 +171,10 @@ ReturnedValue Lookup::indexedGetterObjectInt(Lookup *l, const ValueRef object, c
return indexedGetterGeneric(l, object, index);
Object *o = object->objectValue();
- if (o->arrayData && o->arrayData->type == ArrayData::Simple) {
- if (idx < static_cast<SimpleArrayData *>(o->arrayData)->len)
- if (!o->arrayData->data[idx].isEmpty())
- return o->arrayData->data[idx].asReturnedValue();
+ if (o->arrayData() && o->arrayData()->type() == ArrayData::Simple) {
+ if (idx < static_cast<SimpleArrayData *>(o->arrayData())->len())
+ if (!o->arrayData()->arrayData()[idx].isEmpty())
+ return o->arrayData()->arrayData()[idx].asReturnedValue();
}
return indexedGetterFallback(l, object, index);
@@ -184,7 +184,7 @@ void Lookup::indexedSetterGeneric(Lookup *l, const ValueRef object, const ValueR
{
if (object->isObject()) {
Object *o = object->objectValue();
- if (o->arrayData && o->arrayData->type == ArrayData::Simple && index->asArrayIndex() < UINT_MAX) {
+ if (o->arrayData() && o->arrayData()->type() == ArrayData::Simple && index->asArrayIndex() < UINT_MAX) {
l->indexedSetter = indexedSetterObjectInt;
indexedSetterObjectInt(l, object, index, v);
return;
@@ -203,10 +203,10 @@ void Lookup::indexedSetterFallback(Lookup *l, const ValueRef object, const Value
uint idx = index->asArrayIndex();
if (idx < UINT_MAX) {
- if (o->arrayData && o->arrayData->type == ArrayData::Simple) {
- SimpleArrayData *s = static_cast<SimpleArrayData *>(o->arrayData);
- if (s && idx < s->len && !s->data[idx].isEmpty()) {
- s->data[idx] = value;
+ if (o->arrayData() && o->arrayData()->type() == ArrayData::Simple) {
+ SimpleArrayData *s = static_cast<SimpleArrayData *>(o->arrayData());
+ if (s && idx < s->len() && !s->arrayData()[idx].isEmpty()) {
+ s->arrayData()[idx] = value;
return;
}
}
@@ -215,7 +215,7 @@ void Lookup::indexedSetterFallback(Lookup *l, const ValueRef object, const Value
}
ScopedString name(scope, index->toString(ctx));
- o->put(name, value);
+ o->put(name.getPointer(), value);
}
void Lookup::indexedSetterObjectInt(Lookup *l, const ValueRef object, const ValueRef index, const ValueRef v)
@@ -227,10 +227,10 @@ void Lookup::indexedSetterObjectInt(Lookup *l, const ValueRef object, const Valu
}
Object *o = object->objectValue();
- if (o->arrayData && o->arrayData->type == ArrayData::Simple) {
- SimpleArrayData *s = static_cast<SimpleArrayData *>(o->arrayData);
- if (idx < s->len && !s->data[idx].isEmpty()) {
- s->data[idx] = v;
+ if (o->arrayData() && o->arrayData()->type() == ArrayData::Simple) {
+ SimpleArrayData *s = static_cast<SimpleArrayData *>(o->arrayData());
+ if (idx < s->len() && !s->arrayData()[idx].isEmpty()) {
+ s->arrayData()[idx] = v;
return;
}
}
@@ -254,7 +254,7 @@ ReturnedValue Lookup::getterGeneric(QV4::Lookup *l, const ValueRef object)
case Value::Managed_Type:
Q_ASSERT(object->isString());
proto = engine->stringObjectClass->prototype;
- if (l->name->equals(engine->id_length)) {
+ if (l->name->equals(engine->id_length.getPointer())) {
// special case, as the property is on the object itself
l->getter = stringLengthGetter;
return stringLengthGetter(l, object);
@@ -331,7 +331,7 @@ ReturnedValue Lookup::getterFallback(Lookup *l, const ValueRef object)
if (!o)
return Encode::undefined();
QV4::ScopedString s(scope, l->name);
- return o->get(s);
+ return o->get(s.getPointer());
}
ReturnedValue Lookup::getter0(Lookup *l, const ValueRef object)
@@ -340,8 +340,8 @@ ReturnedValue Lookup::getter0(Lookup *l, const ValueRef object)
// we can safely cast to a QV4::Object here. If object is actually a string,
// the internal class won't match
Object *o = object->objectValue();
- if (l->classList[0] == o->internalClass)
- return o->memberData[l->index].asReturnedValue();
+ if (l->classList[0] == o->internalClass())
+ return o->memberData()[l->index].asReturnedValue();
}
return getterTwoClasses(l, object);
}
@@ -352,9 +352,9 @@ ReturnedValue Lookup::getter1(Lookup *l, const ValueRef object)
// we can safely cast to a QV4::Object here. If object is actually a string,
// the internal class won't match
Object *o = object->objectValue();
- if (l->classList[0] == o->internalClass &&
- l->classList[1] == o->prototype()->internalClass)
- return o->prototype()->memberData[l->index].asReturnedValue();
+ if (l->classList[0] == o->internalClass() &&
+ l->classList[1] == o->prototype()->internalClass())
+ return o->prototype()->memberData()[l->index].asReturnedValue();
}
return getterTwoClasses(l, object);
}
@@ -365,12 +365,12 @@ ReturnedValue Lookup::getter2(Lookup *l, const ValueRef object)
// we can safely cast to a QV4::Object here. If object is actually a string,
// the internal class won't match
Object *o = object->objectValue();
- if (l->classList[0] == o->internalClass) {
+ if (l->classList[0] == o->internalClass()) {
o = o->prototype();
- if (l->classList[1] == o->internalClass) {
+ if (l->classList[1] == o->internalClass()) {
o = o->prototype();
- if (l->classList[2] == o->internalClass)
- return o->memberData[l->index].asReturnedValue();
+ if (l->classList[2] == o->internalClass())
+ return o->memberData()[l->index].asReturnedValue();
}
}
}
@@ -384,10 +384,10 @@ ReturnedValue Lookup::getter0getter0(Lookup *l, const ValueRef object)
// we can safely cast to a QV4::Object here. If object is actually a string,
// the internal class won't match
Object *o = object->objectValue();
- if (l->classList[0] == o->internalClass)
- return o->memberData[l->index].asReturnedValue();
- if (l->classList[2] == o->internalClass)
- return o->memberData[l->index2].asReturnedValue();
+ if (l->classList[0] == o->internalClass())
+ return o->memberData()[l->index].asReturnedValue();
+ if (l->classList[2] == o->internalClass())
+ return o->memberData()[l->index2].asReturnedValue();
}
l->getter = getterFallback;
return getterFallback(l, object);
@@ -399,11 +399,11 @@ ReturnedValue Lookup::getter0getter1(Lookup *l, const ValueRef object)
// we can safely cast to a QV4::Object here. If object is actually a string,
// the internal class won't match
Object *o = object->objectValue();
- if (l->classList[0] == o->internalClass)
- return o->memberData[l->index].asReturnedValue();
- if (l->classList[2] == o->internalClass &&
- l->classList[3] == o->prototype()->internalClass)
- return o->prototype()->memberData[l->index2].asReturnedValue();
+ if (l->classList[0] == o->internalClass())
+ return o->memberData()[l->index].asReturnedValue();
+ if (l->classList[2] == o->internalClass() &&
+ l->classList[3] == o->prototype()->internalClass())
+ return o->prototype()->memberData()[l->index2].asReturnedValue();
}
l->getter = getterFallback;
return getterFallback(l, object);
@@ -415,12 +415,12 @@ ReturnedValue Lookup::getter1getter1(Lookup *l, const ValueRef object)
// we can safely cast to a QV4::Object here. If object is actually a string,
// the internal class won't match
Object *o = object->objectValue();
- if (l->classList[0] == o->internalClass &&
- l->classList[1] == o->prototype()->internalClass)
- return o->prototype()->memberData[l->index].asReturnedValue();
- if (l->classList[2] == o->internalClass &&
- l->classList[3] == o->prototype()->internalClass)
- return o->prototype()->memberData[l->index2].asReturnedValue();
+ if (l->classList[0] == o->internalClass() &&
+ l->classList[1] == o->prototype()->internalClass())
+ return o->prototype()->memberData()[l->index].asReturnedValue();
+ if (l->classList[2] == o->internalClass() &&
+ l->classList[3] == o->prototype()->internalClass())
+ return o->prototype()->memberData()[l->index2].asReturnedValue();
return getterFallback(l, object);
}
l->getter = getterFallback;
@@ -434,7 +434,7 @@ ReturnedValue Lookup::getterAccessor0(Lookup *l, const ValueRef object)
// we can safely cast to a QV4::Object here. If object is actually a string,
// the internal class won't match
Object *o = object->objectValue();
- if (l->classList[0] == o->internalClass) {
+ if (l->classList[0] == o->internalClass()) {
Scope scope(o->engine());
FunctionObject *getter = o->propertyAt(l->index)->getter();
if (!getter)
@@ -455,8 +455,8 @@ ReturnedValue Lookup::getterAccessor1(Lookup *l, const ValueRef object)
// we can safely cast to a QV4::Object here. If object is actually a string,
// the internal class won't match
Object *o = object->objectValue();
- if (l->classList[0] == o->internalClass &&
- l->classList[1] == o->prototype()->internalClass) {
+ if (l->classList[0] == o->internalClass() &&
+ l->classList[1] == o->prototype()->internalClass()) {
Scope scope(o->engine());
FunctionObject *getter = o->prototype()->propertyAt(l->index)->getter();
if (!getter)
@@ -477,11 +477,11 @@ ReturnedValue Lookup::getterAccessor2(Lookup *l, const ValueRef object)
// we can safely cast to a QV4::Object here. If object is actually a string,
// the internal class won't match
Object *o = object->objectValue();
- if (l->classList[0] == o->internalClass) {
+ if (l->classList[0] == o->internalClass()) {
o = o->prototype();
- if (l->classList[1] == o->internalClass) {
+ if (l->classList[1] == o->internalClass()) {
o = o->prototype();
- if (l->classList[2] == o->internalClass) {
+ if (l->classList[2] == o->internalClass()) {
Scope scope(o->engine());
FunctionObject *getter = o->propertyAt(l->index)->getter();
if (!getter)
@@ -502,8 +502,8 @@ ReturnedValue Lookup::primitiveGetter0(Lookup *l, const ValueRef object)
{
if (object->type() == l->type) {
Object *o = l->proto;
- if (l->classList[0] == o->internalClass)
- return o->memberData[l->index].asReturnedValue();
+ if (l->classList[0] == o->internalClass())
+ return o->memberData()[l->index].asReturnedValue();
}
l->getter = getterGeneric;
return getterGeneric(l, object);
@@ -513,9 +513,9 @@ ReturnedValue Lookup::primitiveGetter1(Lookup *l, const ValueRef object)
{
if (object->type() == l->type) {
Object *o = l->proto;
- if (l->classList[0] == o->internalClass &&
- l->classList[1] == o->prototype()->internalClass)
- return o->prototype()->memberData[l->index].asReturnedValue();
+ if (l->classList[0] == o->internalClass() &&
+ l->classList[1] == o->prototype()->internalClass())
+ return o->prototype()->memberData()[l->index].asReturnedValue();
}
l->getter = getterGeneric;
return getterGeneric(l, object);
@@ -525,7 +525,7 @@ ReturnedValue Lookup::primitiveGetterAccessor0(Lookup *l, const ValueRef object)
{
if (object->type() == l->type) {
Object *o = l->proto;
- if (l->classList[0] == o->internalClass) {
+ if (l->classList[0] == o->internalClass()) {
Scope scope(o->engine());
FunctionObject *getter = o->propertyAt(l->index)->getter();
if (!getter)
@@ -544,8 +544,8 @@ ReturnedValue Lookup::primitiveGetterAccessor1(Lookup *l, const ValueRef object)
{
if (object->type() == l->type) {
Object *o = l->proto;
- if (l->classList[0] == o->internalClass &&
- l->classList[1] == o->prototype()->internalClass) {
+ if (l->classList[0] == o->internalClass() &&
+ l->classList[1] == o->prototype()->internalClass()) {
Scope scope(o->engine());
FunctionObject *getter = o->prototype()->propertyAt(l->index)->getter();
if (!getter)
@@ -563,7 +563,7 @@ ReturnedValue Lookup::primitiveGetterAccessor1(Lookup *l, const ValueRef object)
ReturnedValue Lookup::stringLengthGetter(Lookup *l, const ValueRef object)
{
if (String *s = object->asString())
- return Encode(s->length());
+ return Encode(s->d()->length());
l->getter = getterGeneric;
return getterGeneric(l, object);
@@ -572,7 +572,7 @@ ReturnedValue Lookup::stringLengthGetter(Lookup *l, const ValueRef object)
ReturnedValue Lookup::arrayLengthGetter(Lookup *l, const ValueRef object)
{
if (ArrayObject *a = object->asArrayObject())
- return a->memberData[ArrayObject::LengthPropertyIndex].asReturnedValue();
+ return a->memberData()[ArrayObject::LengthPropertyIndex].asReturnedValue();
l->getter = getterGeneric;
return getterGeneric(l, object);
@@ -581,7 +581,7 @@ ReturnedValue Lookup::arrayLengthGetter(Lookup *l, const ValueRef object)
ReturnedValue Lookup::globalGetterGeneric(Lookup *l, ExecutionContext *ctx)
{
- Object *o = ctx->engine->globalObject;
+ Object *o = ctx->d()->engine->globalObject;
PropertyAttributes attrs;
ReturnedValue v = l->lookup(o, &attrs);
if (v != Primitive::emptyValue().asReturnedValue()) {
@@ -610,9 +610,9 @@ ReturnedValue Lookup::globalGetterGeneric(Lookup *l, ExecutionContext *ctx)
ReturnedValue Lookup::globalGetter0(Lookup *l, ExecutionContext *ctx)
{
- Object *o = ctx->engine->globalObject;
- if (l->classList[0] == o->internalClass)
- return o->memberData[l->index].asReturnedValue();
+ Object *o = ctx->d()->engine->globalObject;
+ if (l->classList[0] == o->internalClass())
+ return o->memberData()[l->index].asReturnedValue();
l->globalGetter = globalGetterGeneric;
return globalGetterGeneric(l, ctx);
@@ -620,10 +620,10 @@ ReturnedValue Lookup::globalGetter0(Lookup *l, ExecutionContext *ctx)
ReturnedValue Lookup::globalGetter1(Lookup *l, ExecutionContext *ctx)
{
- Object *o = ctx->engine->globalObject;
- if (l->classList[0] == o->internalClass &&
- l->classList[1] == o->prototype()->internalClass)
- return o->prototype()->memberData[l->index].asReturnedValue();
+ Object *o = ctx->d()->engine->globalObject;
+ if (l->classList[0] == o->internalClass() &&
+ l->classList[1] == o->prototype()->internalClass())
+ return o->prototype()->memberData()[l->index].asReturnedValue();
l->globalGetter = globalGetterGeneric;
return globalGetterGeneric(l, ctx);
@@ -631,13 +631,13 @@ ReturnedValue Lookup::globalGetter1(Lookup *l, ExecutionContext *ctx)
ReturnedValue Lookup::globalGetter2(Lookup *l, ExecutionContext *ctx)
{
- Object *o = ctx->engine->globalObject;
- if (l->classList[0] == o->internalClass) {
+ Object *o = ctx->d()->engine->globalObject;
+ if (l->classList[0] == o->internalClass()) {
o = o->prototype();
- if (l->classList[1] == o->internalClass) {
+ if (l->classList[1] == o->internalClass()) {
o = o->prototype();
- if (l->classList[2] == o->internalClass) {
- return o->prototype()->memberData[l->index].asReturnedValue();
+ if (l->classList[2] == o->internalClass()) {
+ return o->prototype()->memberData()[l->index].asReturnedValue();
}
}
}
@@ -647,8 +647,8 @@ ReturnedValue Lookup::globalGetter2(Lookup *l, ExecutionContext *ctx)
ReturnedValue Lookup::globalGetterAccessor0(Lookup *l, ExecutionContext *ctx)
{
- Object *o = ctx->engine->globalObject;
- if (l->classList[0] == o->internalClass) {
+ Object *o = ctx->d()->engine->globalObject;
+ if (l->classList[0] == o->internalClass()) {
Scope scope(o->engine());
FunctionObject *getter = o->propertyAt(l->index)->getter();
if (!getter)
@@ -664,9 +664,9 @@ ReturnedValue Lookup::globalGetterAccessor0(Lookup *l, ExecutionContext *ctx)
ReturnedValue Lookup::globalGetterAccessor1(Lookup *l, ExecutionContext *ctx)
{
- Object *o = ctx->engine->globalObject;
- if (l->classList[0] == o->internalClass &&
- l->classList[1] == o->prototype()->internalClass) {
+ Object *o = ctx->d()->engine->globalObject;
+ if (l->classList[0] == o->internalClass() &&
+ l->classList[1] == o->prototype()->internalClass()) {
Scope scope(o->engine());
FunctionObject *getter = o->prototype()->propertyAt(l->index)->getter();
if (!getter)
@@ -682,12 +682,12 @@ ReturnedValue Lookup::globalGetterAccessor1(Lookup *l, ExecutionContext *ctx)
ReturnedValue Lookup::globalGetterAccessor2(Lookup *l, ExecutionContext *ctx)
{
- Object *o = ctx->engine->globalObject;
- if (l->classList[0] == o->internalClass) {
+ Object *o = ctx->d()->engine->globalObject;
+ if (l->classList[0] == o->internalClass()) {
o = o->prototype();
- if (l->classList[1] == o->internalClass) {
+ if (l->classList[1] == o->internalClass()) {
o = o->prototype();
- if (l->classList[2] == o->internalClass) {
+ if (l->classList[2] == o->internalClass()) {
Scope scope(o->engine());
FunctionObject *getter = o->propertyAt(l->index)->getter();
if (!getter)
@@ -712,7 +712,7 @@ void Lookup::setterGeneric(Lookup *l, const ValueRef object, const ValueRef valu
if (!o) // type error
return;
ScopedString s(scope, l->name);
- o->put(s, value);
+ o->put(s.getPointer(), value);
return;
}
o->setLookup(l, value);
@@ -743,15 +743,15 @@ void Lookup::setterFallback(Lookup *l, const ValueRef object, const ValueRef val
QV4::ScopedObject o(scope, object->toObject(scope.engine->currentContext()));
if (o) {
QV4::ScopedString s(scope, l->name);
- o->put(s, value);
+ o->put(s.getPointer(), value);
}
}
void Lookup::setter0(Lookup *l, const ValueRef object, const ValueRef value)
{
Object *o = static_cast<Object *>(object->asManaged());
- if (o && o->internalClass == l->classList[0]) {
- o->memberData[l->index] = *value;
+ if (o && o->internalClass() == l->classList[0]) {
+ o->memberData()[l->index] = *value;
return;
}
@@ -761,12 +761,12 @@ void Lookup::setter0(Lookup *l, const ValueRef object, const ValueRef value)
void Lookup::setterInsert0(Lookup *l, const ValueRef object, const ValueRef value)
{
Object *o = static_cast<Object *>(object->asManaged());
- if (o && o->internalClass == l->classList[0]) {
+ if (o && o->internalClass() == l->classList[0]) {
if (!o->prototype()) {
- if (l->index >= o->memberData.size())
+ if (l->index >= o->memberData().size())
o->ensureMemberIndex(l->index);
- o->memberData[l->index] = *value;
- o->internalClass = l->classList[3];
+ o->memberData()[l->index] = *value;
+ o->setInternalClass(l->classList[3]);
return;
}
}
@@ -778,13 +778,13 @@ void Lookup::setterInsert0(Lookup *l, const ValueRef object, const ValueRef valu
void Lookup::setterInsert1(Lookup *l, const ValueRef object, const ValueRef value)
{
Object *o = static_cast<Object *>(object->asManaged());
- if (o && o->internalClass == l->classList[0]) {
+ if (o && o->internalClass() == l->classList[0]) {
Object *p = o->prototype();
- if (p && p->internalClass == l->classList[1]) {
- if (l->index >= o->memberData.size())
+ if (p && p->internalClass() == l->classList[1]) {
+ if (l->index >= o->memberData().size())
o->ensureMemberIndex(l->index);
- o->memberData[l->index] = *value;
- o->internalClass = l->classList[3];
+ o->memberData()[l->index] = *value;
+ o->setInternalClass(l->classList[3]);
return;
}
}
@@ -796,15 +796,15 @@ void Lookup::setterInsert1(Lookup *l, const ValueRef object, const ValueRef valu
void Lookup::setterInsert2(Lookup *l, const ValueRef object, const ValueRef value)
{
Object *o = static_cast<Object *>(object->asManaged());
- if (o && o->internalClass == l->classList[0]) {
+ if (o && o->internalClass() == l->classList[0]) {
Object *p = o->prototype();
- if (p && p->internalClass == l->classList[1]) {
+ if (p && p->internalClass() == l->classList[1]) {
p = p->prototype();
- if (p && p->internalClass == l->classList[2]) {
- if (l->index >= o->memberData.size())
+ if (p && p->internalClass() == l->classList[2]) {
+ if (l->index >= o->memberData().size())
o->ensureMemberIndex(l->index);
- o->memberData[l->index] = *value;
- o->internalClass = l->classList[3];
+ o->memberData()[l->index] = *value;
+ o->setInternalClass(l->classList[3]);
return;
}
}
@@ -818,12 +818,12 @@ void Lookup::setter0setter0(Lookup *l, const ValueRef object, const ValueRef val
{
Object *o = static_cast<Object *>(object->asManaged());
if (o) {
- if (o->internalClass == l->classList[0]) {
- o->memberData[l->index] = *value;
+ if (o->internalClass() == l->classList[0]) {
+ o->memberData()[l->index] = *value;
return;
}
- if (o->internalClass == l->classList[1]) {
- o->memberData[l->index2] = *value;
+ if (o->internalClass() == l->classList[1]) {
+ o->memberData()[l->index2] = *value;
return;
}
}
diff --git a/src/qml/jsruntime/qv4managed.cpp b/src/qml/jsruntime/qv4managed.cpp
index 1f4030a4ed..6fc402e48f 100644
--- a/src/qml/jsruntime/qv4managed.cpp
+++ b/src/qml/jsruntime/qv4managed.cpp
@@ -45,8 +45,10 @@
using namespace QV4;
+
const ManagedVTable Managed::static_vtbl =
{
+ 0,
Managed::IsExecutionContext,
Managed::IsString,
Managed::IsObject,
@@ -56,7 +58,7 @@ const ManagedVTable Managed::static_vtbl =
0,
Managed::MyType,
"Managed",
- destroy,
+ 0,
0 /*markObjects*/,
isEqualTo
};
@@ -69,33 +71,15 @@ void *Managed::operator new(size_t size, MemoryManager *mm)
return mm->allocManaged(size);
}
-void Managed::operator delete(void *ptr)
-{
- if (!ptr)
- return;
-
- Managed *m = static_cast<Managed *>(ptr);
- m->_data = 0;
- m->markBit = 0;
- m->~Managed();
-}
-
-void Managed::operator delete(void *ptr, MemoryManager *mm)
-{
- Q_UNUSED(mm);
-
- operator delete(ptr);
-}
-
ExecutionEngine *Managed::engine() const
{
- return internalClass ? internalClass->engine : 0;
+ return internalClass()->engine;
}
QString Managed::className() const
{
const char *s = 0;
- switch (Type(internalClass->vtable->type)) {
+ switch (Type(internalClass()->vtable->type)) {
case Type_Invalid:
case Type_String:
return QString();
@@ -124,7 +108,7 @@ QString Managed::className() const
s = "RegExp";
break;
case Type_ErrorObject:
- switch (ErrorObject::ErrorType(subtype)) {
+ switch (ErrorObject::ErrorType(subtype())) {
case ErrorObject::Error:
s = "Error";
break;
@@ -177,10 +161,17 @@ QString Managed::className() const
void Managed::setVTable(const ManagedVTable *vt)
{
+ Q_ASSERT(internalClass());
+ d()->internalClass = internalClass()->changeVTable(vt);
+}
+
+void Managed::Data::setVTable(const ManagedVTable *vt)
+{
Q_ASSERT(internalClass);
internalClass = internalClass->changeVTable(vt);
}
+
bool Managed::isEqualTo(Managed *, Managed *)
{
return false;
diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h
index 06d3e4884b..b88531d8ed 100644
--- a/src/qml/jsruntime/qv4managed_p.h
+++ b/src/qml/jsruntime/qv4managed_p.h
@@ -62,26 +62,44 @@ inline int qYouForgotTheQ_MANAGED_Macro(T, T) { return 0; }
template <typename T1, typename T2>
inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {}
-#define V4_MANAGED \
+#ifdef Q_COMPILER_STATIC_ASSERT
+#define V4_MANAGED_SIZE_TEST void __dataTest() { Q_STATIC_ASSERT(sizeof(*this) == sizeof(Managed)); }
+#else
+#define V4_MANAGED_SIZE_TEST
+#endif
+
+#define V4_MANAGED(superClass) \
public: \
Q_MANAGED_CHECK \
+ typedef superClass SuperClass; \
static const QV4::ManagedVTable static_vtbl; \
static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl; } \
template <typename T> \
QV4::Returned<T> *asReturned() { return QV4::Returned<T>::create(this); } \
+ V4_MANAGED_SIZE_TEST \
+ const Data *d() const { return &static_cast<const Data &>(Managed::data); } \
+ Data *d() { return &static_cast<Data &>(Managed::data); }
-#define V4_OBJECT \
+#define V4_OBJECT(superClass) \
public: \
Q_MANAGED_CHECK \
+ typedef superClass SuperClass; \
static const QV4::ObjectVTable static_vtbl; \
static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl.managedVTable; } \
template <typename T> \
QV4::Returned<T> *asReturned() { return QV4::Returned<T>::create(this); } \
+ V4_MANAGED_SIZE_TEST \
+ const Data *d() const { return &static_cast<const Data &>(Managed::data); } \
+ Data *d() { return &static_cast<Data &>(Managed::data); }
#define Q_MANAGED_TYPE(type) \
public: \
enum { MyType = Type_##type };
+#define Q_VTABLE_FUNCTION(classname, func) \
+ (classname::func == QV4::Managed::func ? 0 : classname::func)
+
+
struct GCDeletable
{
GCDeletable() : next(0), lastCall(false) {}
@@ -92,6 +110,7 @@ struct GCDeletable
struct ManagedVTable
{
+ const ManagedVTable * const parent;
uint isExecutionContext : 1;
uint isString : 1;
uint isObject : 1;
@@ -111,22 +130,23 @@ struct ObjectVTable
ManagedVTable managedVTable;
ReturnedValue (*call)(Managed *, CallData *data);
ReturnedValue (*construct)(Managed *, CallData *data);
- ReturnedValue (*get)(Managed *, const StringRef name, bool *hasProperty);
+ ReturnedValue (*get)(Managed *, String *name, bool *hasProperty);
ReturnedValue (*getIndexed)(Managed *, uint index, bool *hasProperty);
- void (*put)(Managed *, const StringRef name, const ValueRef value);
+ void (*put)(Managed *, String *name, const ValueRef value);
void (*putIndexed)(Managed *, uint index, const ValueRef value);
- PropertyAttributes (*query)(const Managed *, StringRef name);
+ PropertyAttributes (*query)(const Managed *, String *name);
PropertyAttributes (*queryIndexed)(const Managed *, uint index);
- bool (*deleteProperty)(Managed *m, const StringRef name);
+ bool (*deleteProperty)(Managed *m, String *name);
bool (*deleteIndexedProperty)(Managed *m, uint index);
ReturnedValue (*getLookup)(Managed *m, Lookup *l);
void (*setLookup)(Managed *m, Lookup *l, const ValueRef v);
uint (*getLength)(const Managed *m);
- void (*advanceIterator)(Managed *m, ObjectIterator *it, StringRef name, uint *index, Property *p, PropertyAttributes *attributes);
+ void (*advanceIterator)(Managed *m, ObjectIterator *it, String *&name, uint *index, Property *p, PropertyAttributes *attributes);
};
-#define DEFINE_MANAGED_VTABLE_INT(classname) \
+#define DEFINE_MANAGED_VTABLE_INT(classname, parentVTable) \
{ \
+ parentVTable, \
classname::IsExecutionContext, \
classname::IsString, \
classname::IsObject, \
@@ -135,21 +155,20 @@ struct ObjectVTable
classname::IsArrayData, \
0, \
classname::MyType, \
- #classname, \
- destroy, \
+ #classname, \
+ Q_VTABLE_FUNCTION(classname, destroy), \
markObjects, \
isEqualTo \
}
-
#define DEFINE_MANAGED_VTABLE(classname) \
-const QV4::ManagedVTable classname::static_vtbl = DEFINE_MANAGED_VTABLE_INT(classname)
+const QV4::ManagedVTable classname::static_vtbl = DEFINE_MANAGED_VTABLE_INT(classname, 0)
#define DEFINE_OBJECT_VTABLE(classname) \
const QV4::ObjectVTable classname::static_vtbl = \
{ \
- DEFINE_MANAGED_VTABLE_INT(classname), \
+ DEFINE_MANAGED_VTABLE_INT(classname, &classname::SuperClass::static_vtbl == &Object::static_vtbl ? 0 : &classname::SuperClass::static_vtbl.managedVTable), \
call, \
construct, \
get, \
@@ -166,30 +185,43 @@ const QV4::ObjectVTable classname::static_vtbl = \
advanceIterator \
}
-#define DEFINE_MANAGED_VTABLE_WITH_NAME(classname, name) \
-const QV4::ObjectVTable classname::static_vtbl = \
-{ \
- DEFINE_MANAGED_VTABLE_INT(name), \
- call, \
- construct, \
- get, \
- getIndexed, \
- put, \
- putIndexed, \
- query, \
- queryIndexed, \
- deleteProperty, \
- deleteIndexedProperty, \
- getLookup, \
- setLookup, \
- getLength, \
- advanceIterator \
-}
-
-
struct Q_QML_PRIVATE_EXPORT Managed
{
- V4_MANAGED
+ struct Q_QML_PRIVATE_EXPORT Data : HeapObject {
+ Data() {}
+ Data(InternalClass *internal)
+ : internalClass(internal)
+ , inUse(1)
+ , extensible(1)
+ {
+ // ####
+// Q_ASSERT(internal && internal->vtable);
+ }
+ InternalClass *internalClass;
+ struct {
+ uchar markBit : 1;
+ uchar inUse : 1;
+ uchar extensible : 1; // used by Object
+ uchar _unused : 1;
+ uchar needsActivation : 1; // used by FunctionObject
+ uchar strictMode : 1; // used by FunctionObject
+ uchar bindingKeyFlag : 1;
+ uchar hasAccessorProperty : 1;
+ uchar _type;
+ mutable uchar subtype;
+ uchar _flags;
+ };
+
+ void setVTable(const ManagedVTable *vt);
+ ReturnedValue asReturnedValue() const {
+ return reinterpret_cast<Managed *>(const_cast<Data *>(this))->asReturnedValue();
+ }
+
+ void *operator new(size_t, Managed *m) { return m; }
+ void *operator new(size_t, Managed::Data *m) { return m; }
+ };
+ Data data;
+ V4_MANAGED(Managed)
enum {
IsExecutionContext = false,
IsString = false,
@@ -205,17 +237,13 @@ private:
protected:
Managed(InternalClass *internal)
- : internalClass(internal), _data(0)
+ : data(internal)
{
- Q_ASSERT(internalClass && internalClass->vtable);
- inUse = 1; extensible = 1;
}
public:
void *operator new(size_t size, MemoryManager *mm);
void *operator new(size_t, Managed *m) { return m; }
- void operator delete(void *ptr);
- void operator delete(void *ptr, MemoryManager *mm);
inline void mark(QV4::ExecutionEngine *engine);
@@ -248,12 +276,18 @@ public:
template <typename T>
T *as() {
// ### FIXME:
- if (!this || !internalClass)
+ if (!this || !internalClass())
return 0;
#if !defined(QT_NO_QOBJECT_CHECK)
static_cast<T *>(this)->qt_check_for_QMANAGED_macro(static_cast<T *>(this));
#endif
- return internalClass->vtable == T::staticVTable() ? static_cast<T *>(this) : 0;
+ const ManagedVTable *vt = internalClass()->vtable;
+ while (vt) {
+ if (vt == T::staticVTable())
+ return static_cast<T *>(this);
+ vt = vt->parent;
+ }
+ return 0;
}
template <typename T>
const T *as() const {
@@ -263,24 +297,30 @@ public:
#if !defined(QT_NO_QOBJECT_CHECK)
static_cast<T *>(this)->qt_check_for_QMANAGED_macro(static_cast<T *>(const_cast<Managed *>(this)));
#endif
- return internalClass->vtable == T::staticVTable() ? static_cast<const T *>(this) : 0;
+ const ManagedVTable *vt = internalClass()->vtable;
+ while (vt) {
+ if (vt == T::staticVTable())
+ return static_cast<T *>(this);
+ vt = vt->parent;
+ }
+ return 0;
}
- String *asString() { return internalClass->vtable->isString ? reinterpret_cast<String *>(this) : 0; }
- Object *asObject() { return internalClass->vtable->isObject ? reinterpret_cast<Object *>(this) : 0; }
- ArrayObject *asArrayObject() { return internalClass->vtable->type == Type_ArrayObject ? reinterpret_cast<ArrayObject *>(this) : 0; }
- FunctionObject *asFunctionObject() { return internalClass->vtable->isFunctionObject ? reinterpret_cast<FunctionObject *>(this) : 0; }
- BooleanObject *asBooleanObject() { return internalClass->vtable->type == Type_BooleanObject ? reinterpret_cast<BooleanObject *>(this) : 0; }
- NumberObject *asNumberObject() { return internalClass->vtable->type == Type_NumberObject ? reinterpret_cast<NumberObject *>(this) : 0; }
- StringObject *asStringObject() { return internalClass->vtable->type == Type_StringObject ? reinterpret_cast<StringObject *>(this) : 0; }
- DateObject *asDateObject() { return internalClass->vtable->type == Type_DateObject ? reinterpret_cast<DateObject *>(this) : 0; }
- ErrorObject *asErrorObject() { return internalClass->vtable->isErrorObject ? reinterpret_cast<ErrorObject *>(this) : 0; }
- ArgumentsObject *asArgumentsObject() { return internalClass->vtable->type == Type_ArgumentsObject ? reinterpret_cast<ArgumentsObject *>(this) : 0; }
+ String *asString() { return internalClass()->vtable->isString ? reinterpret_cast<String *>(this) : 0; }
+ Object *asObject() { return internalClass()->vtable->isObject ? reinterpret_cast<Object *>(this) : 0; }
+ ArrayObject *asArrayObject() { return internalClass()->vtable->type == Type_ArrayObject ? reinterpret_cast<ArrayObject *>(this) : 0; }
+ FunctionObject *asFunctionObject() { return internalClass()->vtable->isFunctionObject ? reinterpret_cast<FunctionObject *>(this) : 0; }
+ BooleanObject *asBooleanObject() { return internalClass()->vtable->type == Type_BooleanObject ? reinterpret_cast<BooleanObject *>(this) : 0; }
+ NumberObject *asNumberObject() { return internalClass()->vtable->type == Type_NumberObject ? reinterpret_cast<NumberObject *>(this) : 0; }
+ StringObject *asStringObject() { return internalClass()->vtable->type == Type_StringObject ? reinterpret_cast<StringObject *>(this) : 0; }
+ DateObject *asDateObject() { return internalClass()->vtable->type == Type_DateObject ? reinterpret_cast<DateObject *>(this) : 0; }
+ ErrorObject *asErrorObject() { return internalClass()->vtable->isErrorObject ? reinterpret_cast<ErrorObject *>(this) : 0; }
+ ArgumentsObject *asArgumentsObject() { return internalClass()->vtable->type == Type_ArgumentsObject ? reinterpret_cast<ArgumentsObject *>(this) : 0; }
- bool isListType() const { return internalClass->vtable->type == Type_QmlSequence; }
+ bool isListType() const { return internalClass()->vtable->type == Type_QmlSequence; }
- bool isArrayObject() const { return internalClass->vtable->type == Type_ArrayObject; }
- bool isStringObject() const { return internalClass->vtable->type == Type_StringObject; }
+ bool isArrayObject() const { return internalClass()->vtable->type == Type_ArrayObject; }
+ bool isStringObject() const { return internalClass()->vtable->type == Type_StringObject; }
QString className() const;
@@ -297,33 +337,22 @@ public:
void setVTable(const ManagedVTable *vt);
bool isEqualTo(Managed *other)
- { return internalClass->vtable->isEqualTo(this, other); }
+ { return internalClass()->vtable->isEqualTo(this, other); }
- static void destroy(Managed *that) { that->_data = 0; }
static bool isEqualTo(Managed *m, Managed *other);
ReturnedValue asReturnedValue() { return Value::fromManaged(this).asReturnedValue(); }
+ InternalClass *internalClass() const { return d()->internalClass; }
+ void setInternalClass(InternalClass *ic) { d()->internalClass = ic; }
- InternalClass *internalClass;
+ uchar subtype() const { return d()->subtype; }
+ void setSubtype(uchar subtype) const { d()->subtype = subtype; }
- union {
- uint _data;
- struct {
- uchar markBit : 1;
- uchar inUse : 1;
- uchar extensible : 1; // used by Object
- uchar _unused : 1;
- uchar needsActivation : 1; // used by FunctionObject
- uchar strictMode : 1; // used by FunctionObject
- uchar bindingKeyFlag : 1;
- uchar hasAccessorProperty : 1;
- uchar _type;
- mutable uchar subtype;
- uchar _flags;
- };
- };
+ bool inUse() const { return d()->inUse; }
+ bool markBit() const { return d()->markBit; }
+ static void destroy(Managed *) {}
private:
friend class MemoryManager;
friend struct Identifiers;
@@ -358,69 +387,6 @@ inline FunctionObject *managed_cast(Managed *m)
return m->asFunctionObject();
}
-
-Value *extractValuePointer(const ScopedValue &);
-template<typename T>
-Value *extractValuePointer(const Scoped<T> &);
-
-#define DEFINE_REF_METHODS(Class, Base) \
- Class##Ref(const QV4::ScopedValue &v) \
- { QV4::Value *val = extractValuePointer(v); ptr = QV4::value_cast<Class>(*val) ? val : 0; } \
- Class##Ref(const QV4::Scoped<Class> &v) { ptr = extractValuePointer(v); } \
- Class##Ref(QV4::TypedValue<Class> &v) { ptr = &v; } \
- Class##Ref(QV4::Value &v) { ptr = QV4::value_cast<Class>(v) ? &v : 0; } \
- Class##Ref &operator=(Class *t) { \
- if (sizeof(void *) == 4) \
- ptr->tag = QV4::Value::Managed_Type; \
- ptr->m = t; \
- return *this; \
- } \
- Class##Ref &operator=(QV4::Returned<Class> *t) { \
- if (sizeof(void *) == 4) \
- ptr->tag = QV4::Value::Managed_Type; \
- ptr->m = t->getPointer(); \
- return *this; \
- } \
- operator const Class *() const { return ptr ? static_cast<Class*>(ptr->managed()) : 0; } \
- const Class *operator->() const { return static_cast<Class*>(ptr->managed()); } \
- operator Class *() { return ptr ? static_cast<Class*>(ptr->managed()) : 0; } \
- Class *operator->() { return static_cast<Class*>(ptr->managed()); } \
- Class *getPointer() const { return static_cast<Class *>(ptr->managed()); } \
- operator QV4::Returned<Class> *() const { return ptr ? QV4::Returned<Class>::create(getPointer()) : 0; } \
- static Class##Ref null() { Class##Ref c; c.ptr = 0; return c; } \
-protected: \
- Class##Ref() {} \
-public: \
-
-#define DEFINE_REF(Class, Base) \
-struct Class##Ref : public Base##Ref \
-{ DEFINE_REF_METHODS(Class, Base) } \
-
-
-struct ManagedRef {
- // Important: Do NOT add a copy constructor to this class or any derived class
- // adding a copy constructor actually changes the calling convention, ie.
- // is not even binary compatible. Adding it would break assumptions made
- // in the jit'ed code.
- DEFINE_REF_METHODS(Managed, Managed);
-
- bool operator==(const ManagedRef &other) {
- if (ptr == other.ptr)
- return true;
- return ptr && other.ptr && ptr->m == other.ptr->m;
- }
- bool operator!=(const ManagedRef &other) {
- return !operator==(other);
- }
- bool operator!() const { return !ptr || !ptr->managed(); }
-
- bool isNull() const { return !ptr; }
- ReturnedValue asReturnedValue() const { return ptr ? ptr->val : Primitive::undefinedValue().asReturnedValue(); }
-
-public:
- Value *ptr;
-};
-
}
diff --git a/src/qml/jsruntime/qv4mathobject.cpp b/src/qml/jsruntime/qv4mathobject.cpp
index 16d76e6914..3b8100c3fb 100644
--- a/src/qml/jsruntime/qv4mathobject.cpp
+++ b/src/qml/jsruntime/qv4mathobject.cpp
@@ -55,39 +55,39 @@ DEFINE_OBJECT_VTABLE(MathObject);
static const double qt_PI = 2.0 * ::asin(1.0);
-MathObject::MathObject(InternalClass *ic)
- : Object(ic)
+MathObject::Data::Data(InternalClass *ic)
+ : Object::Data(ic)
{
Scope scope(ic->engine);
- ScopedObject protectThis(scope, this);
-
- defineReadonlyProperty(QStringLiteral("E"), Primitive::fromDouble(::exp(1.0)));
- defineReadonlyProperty(QStringLiteral("LN2"), Primitive::fromDouble(::log(2.0)));
- defineReadonlyProperty(QStringLiteral("LN10"), Primitive::fromDouble(::log(10.0)));
- defineReadonlyProperty(QStringLiteral("LOG2E"), Primitive::fromDouble(1.0/::log(2.0)));
- defineReadonlyProperty(QStringLiteral("LOG10E"), Primitive::fromDouble(1.0/::log(10.0)));
- defineReadonlyProperty(QStringLiteral("PI"), Primitive::fromDouble(qt_PI));
- defineReadonlyProperty(QStringLiteral("SQRT1_2"), Primitive::fromDouble(::sqrt(0.5)));
- defineReadonlyProperty(QStringLiteral("SQRT2"), Primitive::fromDouble(::sqrt(2.0)));
-
- defineDefaultProperty(QStringLiteral("abs"), method_abs, 1);
- defineDefaultProperty(QStringLiteral("acos"), method_acos, 1);
- defineDefaultProperty(QStringLiteral("asin"), method_asin, 0);
- defineDefaultProperty(QStringLiteral("atan"), method_atan, 1);
- defineDefaultProperty(QStringLiteral("atan2"), method_atan2, 2);
- defineDefaultProperty(QStringLiteral("ceil"), method_ceil, 1);
- defineDefaultProperty(QStringLiteral("cos"), method_cos, 1);
- defineDefaultProperty(QStringLiteral("exp"), method_exp, 1);
- defineDefaultProperty(QStringLiteral("floor"), method_floor, 1);
- defineDefaultProperty(QStringLiteral("log"), method_log, 1);
- defineDefaultProperty(QStringLiteral("max"), method_max, 2);
- defineDefaultProperty(QStringLiteral("min"), method_min, 2);
- defineDefaultProperty(QStringLiteral("pow"), method_pow, 2);
- defineDefaultProperty(QStringLiteral("random"), method_random, 0);
- defineDefaultProperty(QStringLiteral("round"), method_round, 1);
- defineDefaultProperty(QStringLiteral("sin"), method_sin, 1);
- defineDefaultProperty(QStringLiteral("sqrt"), method_sqrt, 1);
- defineDefaultProperty(QStringLiteral("tan"), method_tan, 1);
+ ScopedObject m(scope, this);
+
+ m->defineReadonlyProperty(QStringLiteral("E"), Primitive::fromDouble(::exp(1.0)));
+ m->defineReadonlyProperty(QStringLiteral("LN2"), Primitive::fromDouble(::log(2.0)));
+ m->defineReadonlyProperty(QStringLiteral("LN10"), Primitive::fromDouble(::log(10.0)));
+ m->defineReadonlyProperty(QStringLiteral("LOG2E"), Primitive::fromDouble(1.0/::log(2.0)));
+ m->defineReadonlyProperty(QStringLiteral("LOG10E"), Primitive::fromDouble(1.0/::log(10.0)));
+ m->defineReadonlyProperty(QStringLiteral("PI"), Primitive::fromDouble(qt_PI));
+ m->defineReadonlyProperty(QStringLiteral("SQRT1_2"), Primitive::fromDouble(::sqrt(0.5)));
+ m->defineReadonlyProperty(QStringLiteral("SQRT2"), Primitive::fromDouble(::sqrt(2.0)));
+
+ m->defineDefaultProperty(QStringLiteral("abs"), method_abs, 1);
+ m->defineDefaultProperty(QStringLiteral("acos"), method_acos, 1);
+ m->defineDefaultProperty(QStringLiteral("asin"), method_asin, 0);
+ m->defineDefaultProperty(QStringLiteral("atan"), method_atan, 1);
+ m->defineDefaultProperty(QStringLiteral("atan2"), method_atan2, 2);
+ m->defineDefaultProperty(QStringLiteral("ceil"), method_ceil, 1);
+ m->defineDefaultProperty(QStringLiteral("cos"), method_cos, 1);
+ m->defineDefaultProperty(QStringLiteral("exp"), method_exp, 1);
+ m->defineDefaultProperty(QStringLiteral("floor"), method_floor, 1);
+ m->defineDefaultProperty(QStringLiteral("log"), method_log, 1);
+ m->defineDefaultProperty(QStringLiteral("max"), method_max, 2);
+ m->defineDefaultProperty(QStringLiteral("min"), method_min, 2);
+ m->defineDefaultProperty(QStringLiteral("pow"), method_pow, 2);
+ m->defineDefaultProperty(QStringLiteral("random"), method_random, 0);
+ m->defineDefaultProperty(QStringLiteral("round"), method_round, 1);
+ m->defineDefaultProperty(QStringLiteral("sin"), method_sin, 1);
+ m->defineDefaultProperty(QStringLiteral("sqrt"), method_sqrt, 1);
+ m->defineDefaultProperty(QStringLiteral("tan"), method_tan, 1);
}
/* copies the sign from y to x and returns the result */
@@ -104,15 +104,15 @@ static double copySign(double x, double y)
ReturnedValue MathObject::method_abs(CallContext *context)
{
- if (!context->callData->argc)
+ if (!context->d()->callData->argc)
return Encode(qSNaN());
- if (context->callData->args[0].isInteger()) {
- int i = context->callData->args[0].integerValue();
+ if (context->d()->callData->args[0].isInteger()) {
+ int i = context->d()->callData->args[0].integerValue();
return Encode(i < 0 ? - i : i);
}
- double v = context->callData->args[0].toNumber();
+ double v = context->d()->callData->args[0].toNumber();
if (v == 0) // 0 | -0
return Encode(0);
@@ -121,7 +121,7 @@ ReturnedValue MathObject::method_abs(CallContext *context)
ReturnedValue MathObject::method_acos(CallContext *context)
{
- double v = context->callData->argc ? context->callData->args[0].toNumber() : 2;
+ double v = context->d()->callData->argc ? context->d()->callData->args[0].toNumber() : 2;
if (v > 1)
return Encode(qSNaN());
@@ -130,7 +130,7 @@ ReturnedValue MathObject::method_acos(CallContext *context)
ReturnedValue MathObject::method_asin(CallContext *context)
{
- double v = context->callData->argc ? context->callData->args[0].toNumber() : 2;
+ double v = context->d()->callData->argc ? context->d()->callData->args[0].toNumber() : 2;
if (v > 1)
return Encode(qSNaN());
else
@@ -139,7 +139,7 @@ ReturnedValue MathObject::method_asin(CallContext *context)
ReturnedValue MathObject::method_atan(CallContext *context)
{
- double v = context->callData->argc ? context->callData->args[0].toNumber() : qSNaN();
+ double v = context->d()->callData->argc ? context->d()->callData->args[0].toNumber() : qSNaN();
if (v == 0.0)
return Encode(v);
else
@@ -148,8 +148,8 @@ ReturnedValue MathObject::method_atan(CallContext *context)
ReturnedValue MathObject::method_atan2(CallContext *context)
{
- double v1 = context->callData->argc ? context->callData->args[0].toNumber() : qSNaN();
- double v2 = context->callData->argc > 1 ? context->callData->args[1].toNumber() : qSNaN();
+ double v1 = context->d()->callData->argc ? context->d()->callData->args[0].toNumber() : qSNaN();
+ double v2 = context->d()->callData->argc > 1 ? context->d()->callData->args[1].toNumber() : qSNaN();
if ((v1 < 0) && qIsFinite(v1) && qIsInf(v2) && (copySign(1.0, v2) == 1.0))
return Encode(copySign(0, -1.0));
@@ -166,7 +166,7 @@ ReturnedValue MathObject::method_atan2(CallContext *context)
ReturnedValue MathObject::method_ceil(CallContext *context)
{
- double v = context->callData->argc ? context->callData->args[0].toNumber() : qSNaN();
+ double v = context->d()->callData->argc ? context->d()->callData->args[0].toNumber() : qSNaN();
if (v < 0.0 && v > -1.0)
return Encode(copySign(0, -1.0));
else
@@ -175,13 +175,13 @@ ReturnedValue MathObject::method_ceil(CallContext *context)
ReturnedValue MathObject::method_cos(CallContext *context)
{
- double v = context->callData->argc ? context->callData->args[0].toNumber() : qSNaN();
+ double v = context->d()->callData->argc ? context->d()->callData->args[0].toNumber() : qSNaN();
return Encode(::cos(v));
}
ReturnedValue MathObject::method_exp(CallContext *context)
{
- double v = context->callData->argc ? context->callData->args[0].toNumber() : qSNaN();
+ double v = context->d()->callData->argc ? context->d()->callData->args[0].toNumber() : qSNaN();
if (qIsInf(v)) {
if (copySign(1.0, v) == -1.0)
return Encode(0);
@@ -194,13 +194,13 @@ ReturnedValue MathObject::method_exp(CallContext *context)
ReturnedValue MathObject::method_floor(CallContext *context)
{
- double v = context->callData->argc ? context->callData->args[0].toNumber() : qSNaN();
+ double v = context->d()->callData->argc ? context->d()->callData->args[0].toNumber() : qSNaN();
return Encode(::floor(v));
}
ReturnedValue MathObject::method_log(CallContext *context)
{
- double v = context->callData->argc ? context->callData->args[0].toNumber() : qSNaN();
+ double v = context->d()->callData->argc ? context->d()->callData->args[0].toNumber() : qSNaN();
if (v < 0)
return Encode(qSNaN());
else
@@ -210,8 +210,8 @@ ReturnedValue MathObject::method_log(CallContext *context)
ReturnedValue MathObject::method_max(CallContext *context)
{
double mx = -qInf();
- for (int i = 0; i < context->callData->argc; ++i) {
- double x = context->callData->args[i].toNumber();
+ for (int i = 0; i < context->d()->callData->argc; ++i) {
+ double x = context->d()->callData->args[i].toNumber();
if (x > mx || std::isnan(x))
mx = x;
}
@@ -221,8 +221,8 @@ ReturnedValue MathObject::method_max(CallContext *context)
ReturnedValue MathObject::method_min(CallContext *context)
{
double mx = qInf();
- for (int i = 0; i < context->callData->argc; ++i) {
- double x = context->callData->args[i].toNumber();
+ for (int i = 0; i < context->d()->callData->argc; ++i) {
+ double x = context->d()->callData->args[i].toNumber();
if ((x == 0 && mx == x && copySign(1.0, x) == -1.0)
|| (x < mx) || std::isnan(x)) {
mx = x;
@@ -233,8 +233,8 @@ ReturnedValue MathObject::method_min(CallContext *context)
ReturnedValue MathObject::method_pow(CallContext *context)
{
- double x = context->callData->argc > 0 ? context->callData->args[0].toNumber() : qSNaN();
- double y = context->callData->argc > 1 ? context->callData->args[1].toNumber() : qSNaN();
+ double x = context->d()->callData->argc > 0 ? context->d()->callData->args[0].toNumber() : qSNaN();
+ double y = context->d()->callData->argc > 1 ? context->d()->callData->args[1].toNumber() : qSNaN();
if (std::isnan(y))
return Encode(qSNaN());
@@ -294,26 +294,26 @@ ReturnedValue MathObject::method_random(CallContext *context)
ReturnedValue MathObject::method_round(CallContext *context)
{
- double v = context->callData->argc ? context->callData->args[0].toNumber() : qSNaN();
+ double v = context->d()->callData->argc ? context->d()->callData->args[0].toNumber() : qSNaN();
v = copySign(::floor(v + 0.5), v);
return Encode(v);
}
ReturnedValue MathObject::method_sin(CallContext *context)
{
- double v = context->callData->argc ? context->callData->args[0].toNumber() : qSNaN();
+ double v = context->d()->callData->argc ? context->d()->callData->args[0].toNumber() : qSNaN();
return Encode(::sin(v));
}
ReturnedValue MathObject::method_sqrt(CallContext *context)
{
- double v = context->callData->argc ? context->callData->args[0].toNumber() : qSNaN();
+ double v = context->d()->callData->argc ? context->d()->callData->args[0].toNumber() : qSNaN();
return Encode(::sqrt(v));
}
ReturnedValue MathObject::method_tan(CallContext *context)
{
- double v = context->callData->argc ? context->callData->args[0].toNumber() : qSNaN();
+ double v = context->d()->callData->argc ? context->d()->callData->args[0].toNumber() : qSNaN();
if (v == 0.0)
return Encode(v);
else
diff --git a/src/qml/jsruntime/qv4mathobject_p.h b/src/qml/jsruntime/qv4mathobject_p.h
index 18a80c2ba0..65366aab86 100644
--- a/src/qml/jsruntime/qv4mathobject_p.h
+++ b/src/qml/jsruntime/qv4mathobject_p.h
@@ -49,9 +49,12 @@ namespace QV4 {
struct MathObject: Object
{
- V4_OBJECT
+ struct Data : Object::Data {
+ Data(InternalClass *ic);
+ };
+
+ V4_OBJECT(Object)
Q_MANAGED_TYPE(MathObject)
- MathObject(InternalClass *ic);
static ReturnedValue method_abs(CallContext *context);
static ReturnedValue method_acos(CallContext *context);
diff --git a/src/qml/jsruntime/qv4memberdata.cpp b/src/qml/jsruntime/qv4memberdata.cpp
index aeb4c38a8e..7eca47c3ce 100644
--- a/src/qml/jsruntime/qv4memberdata.cpp
+++ b/src/qml/jsruntime/qv4memberdata.cpp
@@ -44,29 +44,13 @@
using namespace QV4;
-const ManagedVTable MemberData::static_vtbl =
-{
- MemberData::IsExecutionContext,
- MemberData::IsString,
- MemberData::IsObject,
- MemberData::IsFunctionObject,
- MemberData::IsErrorObject,
- MemberData::IsArrayData,
- 0,
- MemberData::MyType,
- "MemberData",
- destroy,
- markObjects,
- isEqualTo
-};
-
-
+DEFINE_MANAGED_VTABLE(MemberData);
void MemberData::markObjects(Managed *that, ExecutionEngine *e)
{
MemberData *m = static_cast<MemberData *>(that);
- for (uint i = 0; i < m->size; ++i)
- m->data[i].mark(e);
+ for (uint i = 0; i < m->d()->size; ++i)
+ m->d()->data[i].mark(e);
}
void Members::ensureIndex(QV4::ExecutionEngine *e, uint idx)
@@ -74,13 +58,13 @@ void Members::ensureIndex(QV4::ExecutionEngine *e, uint idx)
uint s = size();
if (idx >= s) {
int newAlloc = qMax((uint)4, 2*idx);
- uint alloc = sizeof(MemberData) + (newAlloc)*sizeof(Value);
- MemberData *newMemberData = reinterpret_cast<MemberData *>(e->memoryManager->allocManaged(alloc));
+ uint alloc = sizeof(MemberData::Data) + (newAlloc)*sizeof(Value);
+ MemberData *newMemberData = static_cast<MemberData *>(e->memoryManager->allocManaged(alloc));
if (d())
- memcpy(newMemberData, d(), sizeof(MemberData) + s*sizeof(Value));
+ memcpy(newMemberData, d(), sizeof(MemberData::Data) + s*sizeof(Value));
else
new (newMemberData) MemberData(e->memberDataClass);
- newMemberData->size = newAlloc;
+ newMemberData->d()->size = newAlloc;
m = newMemberData;
}
}
diff --git a/src/qml/jsruntime/qv4memberdata_p.h b/src/qml/jsruntime/qv4memberdata_p.h
index 03aa75a365..cd8667adb7 100644
--- a/src/qml/jsruntime/qv4memberdata_p.h
+++ b/src/qml/jsruntime/qv4memberdata_p.h
@@ -50,23 +50,29 @@ namespace QV4 {
struct MemberData : Managed
{
- V4_MANAGED
- uint size;
- Value data[1];
+ struct Data : Managed::Data {
+ union {
+ uint size;
+ double _dummy;
+ };
+ Value data[1];
+ };
+ V4_MANAGED(Managed)
MemberData(QV4::InternalClass *ic) : Managed(ic) {}
- Value &operator[] (uint idx) { return data[idx]; }
+ Value &operator[] (uint idx) { return d()->data[idx]; }
static void markObjects(Managed *that, ExecutionEngine *e);
};
struct Members : Value
{
+ void reset() { m = 0; }
void ensureIndex(QV4::ExecutionEngine *e, uint idx);
- Value &operator[] (uint idx) const { return static_cast<MemberData *>(managed())->data[idx]; }
- inline uint size() const { return d() ? d()->size : 0; }
+ Value &operator[] (uint idx) const { return static_cast<MemberData *>(managed())->d()->data[idx]; }
+ inline uint size() const { return d() ? d()->d()->size : 0; }
inline MemberData *d() const { return static_cast<MemberData *>(managed()); }
- Value *data() const { return static_cast<MemberData *>(managed())->data; }
+ Value *data() const { return static_cast<MemberData *>(managed())->d()->data; }
void mark(ExecutionEngine *e) const {
MemberData *m = d();
diff --git a/src/qml/jsruntime/qv4mm.cpp b/src/qml/jsruntime/qv4mm.cpp
index ca2ccd33f7..3e7ac17078 100644
--- a/src/qml/jsruntime/qv4mm.cpp
+++ b/src/qml/jsruntime/qv4mm.cpp
@@ -57,6 +57,7 @@
#include <cstdlib>
#include <algorithm>
#include "qv4alloca_p.h"
+#include "qv4profiling_p.h"
#ifdef V4_USE_VALGRIND
#include <valgrind/valgrind.h>
@@ -102,6 +103,7 @@ struct MemoryManager::Data
struct LargeItem {
LargeItem *next;
+ size_t size;
void *data;
Managed *managed() {
@@ -149,8 +151,10 @@ struct MemoryManager::Data
~Data()
{
- for (QVector<Chunk>::iterator i = heapChunks.begin(), ei = heapChunks.end(); i != ei; ++i)
+ for (QVector<Chunk>::iterator i = heapChunks.begin(), ei = heapChunks.end(); i != ei; ++i) {
+ Q_V4_PROFILE_DEALLOC(engine, 0, i->memory.size(), Profiling::HeapPage);
i->memory.deallocate();
+ }
}
};
@@ -174,7 +178,7 @@ MemoryManager::MemoryManager()
#endif
}
-Managed *MemoryManager::alloc(std::size_t size)
+Managed *MemoryManager::allocData(std::size_t size)
{
if (m_d->aggressiveGC)
runGC();
@@ -190,9 +194,12 @@ Managed *MemoryManager::alloc(std::size_t size)
// doesn't fit into a small bucket
if (size >= MemoryManager::Data::MaxItemSize) {
// we use malloc for this
- MemoryManager::Data::LargeItem *item = static_cast<MemoryManager::Data::LargeItem *>(malloc(size + sizeof(MemoryManager::Data::LargeItem)));
+ MemoryManager::Data::LargeItem *item = static_cast<MemoryManager::Data::LargeItem *>(
+ malloc(Q_V4_PROFILE_ALLOC(m_d->engine, size + sizeof(MemoryManager::Data::LargeItem),
+ Profiling::LargeItem)));
memset(item, 0, size + sizeof(MemoryManager::Data::LargeItem));
item->next = m_d->largeItems;
+ item->size = size;
m_d->largeItems = item;
return item->managed();
}
@@ -218,7 +225,9 @@ Managed *MemoryManager::alloc(std::size_t size)
std::size_t allocSize = m_d->maxChunkSize*(size_t(1) << shift);
allocSize = roundUpToMultipleOf(WTF::pageSize(), allocSize);
Data::Chunk allocation;
- allocation.memory = PageAllocation::allocate(allocSize, OSAllocator::JSGCHeapPages);
+ allocation.memory = PageAllocation::allocate(
+ Q_V4_PROFILE_ALLOC(m_d->engine, allocSize, Profiling::HeapPage),
+ OSAllocator::JSGCHeapPages);
allocation.chunkSize = int(size);
m_d->heapChunks.append(allocation);
std::sort(m_d->heapChunks.begin(), m_d->heapChunks.end());
@@ -228,7 +237,6 @@ Managed *MemoryManager::alloc(std::size_t size)
Managed **last = &m_d->smallItems[pos];
while (chunk <= end) {
Managed *o = reinterpret_cast<Managed *>(chunk);
- o->_data = 0;
*last = o;
last = o->nextFreeRef();
chunk += size;
@@ -247,6 +255,7 @@ Managed *MemoryManager::alloc(std::size_t size)
#ifdef V4_USE_VALGRIND
VALGRIND_MEMPOOL_ALLOC(this, m, size);
#endif
+ Q_V4_PROFILE_ALLOC(m_d->engine, size, Profiling::SmallItem);
++m_d->allocCount[pos];
++m_d->totalAlloc;
@@ -308,8 +317,8 @@ void MemoryManager::mark()
// now that we marked all roots, start marking recursively and popping from the mark stack
while (m_d->engine->jsStackTop > markBase) {
Managed *m = m_d->engine->popForGC();
- Q_ASSERT (m->internalClass->vtable->markObjects);
- m->internalClass->vtable->markObjects(m, m_d->engine);
+ Q_ASSERT (m->internalClass()->vtable->markObjects);
+ m->internalClass()->vtable->markObjects(m, m_d->engine);
}
}
@@ -325,7 +334,7 @@ void MemoryManager::sweep(bool lastSweep)
continue;
}
if (Managed *m = weak->value.asManaged()) {
- if (!m->markBit) {
+ if (!m->markBit()) {
weak->value = Primitive::undefinedValue();
PersistentValuePrivate *n = weak->next;
weak->removeFromList();
@@ -338,7 +347,7 @@ void MemoryManager::sweep(bool lastSweep)
if (MultiplyWrappedQObjectMap *multiplyWrappedQObjects = m_d->engine->m_multiplyWrappedQObjects) {
for (MultiplyWrappedQObjectMap::Iterator it = multiplyWrappedQObjects->begin(); it != multiplyWrappedQObjects->end();) {
- if (!it.value()->markBit)
+ if (!it.value()->markBit())
it = multiplyWrappedQObjects->erase(it);
else
++it;
@@ -352,18 +361,19 @@ void MemoryManager::sweep(bool lastSweep)
Data::LargeItem **last = &m_d->largeItems;
while (i) {
Managed *m = i->managed();
- Q_ASSERT(m->inUse);
- if (m->markBit) {
- m->markBit = 0;
+ Q_ASSERT(m->inUse());
+ if (m->markBit()) {
+ m->d()->markBit = 0;
last = &i->next;
i = i->next;
continue;
}
- if (m->internalClass->vtable->destroy)
- m->internalClass->vtable->destroy(m);
+ if (m->internalClass()->vtable->destroy)
+ m->internalClass()->vtable->destroy(m);
*last = i->next;
- free(i);
+ free(Q_V4_PROFILE_DEALLOC(m_d->engine, i, i->size + sizeof(Data::LargeItem),
+ Profiling::LargeItem));
i = *last;
}
@@ -392,16 +402,16 @@ void MemoryManager::sweep(char *chunkStart, std::size_t chunkSize, size_t size)
Q_ASSERT((qintptr) chunk % 16 == 0);
- if (m->inUse) {
- if (m->markBit) {
- m->markBit = 0;
+ if (m->inUse()) {
+ if (m->markBit()) {
+ m->d()->markBit = 0;
} else {
// qDebug() << "-- collecting it." << m << *f << m->nextFree();
#ifdef V4_USE_VALGRIND
VALGRIND_ENABLE_ERROR_REPORTING;
#endif
- if (m->internalClass->vtable->destroy)
- m->internalClass->vtable->destroy(m);
+ if (m->internalClass()->vtable->destroy)
+ m->internalClass()->vtable->destroy(m);
memset(m, 0, size);
m->setNextFree(*f);
@@ -409,6 +419,7 @@ void MemoryManager::sweep(char *chunkStart, std::size_t chunkSize, size_t size)
VALGRIND_DISABLE_ERROR_REPORTING;
VALGRIND_MEMPOOL_FREE(this, m);
#endif
+ Q_V4_PROFILE_DEALLOC(m_d->engine, m, size, Profiling::SmallItem);
*f = m;
}
}
@@ -439,9 +450,7 @@ void MemoryManager::runGC()
mark();
sweep();
} else {
- int totalMem = 0;
- for (int i = 0; i < m_d->heapChunks.size(); ++i)
- totalMem += m_d->heapChunks.at(i).memory.size();
+ int totalMem = getAllocatedMem();
QTime t;
t.start();
@@ -467,22 +476,38 @@ void MemoryManager::runGC()
m_d->totalAlloc = 0;
}
-uint MemoryManager::getUsedMem()
+size_t MemoryManager::getUsedMem() const
{
- uint usedMem = 0;
- for (QVector<Data::Chunk>::iterator i = m_d->heapChunks.begin(), ei = m_d->heapChunks.end(); i != ei; ++i) {
+ size_t usedMem = 0;
+ for (QVector<Data::Chunk>::const_iterator i = m_d->heapChunks.begin(), ei = m_d->heapChunks.end(); i != ei; ++i) {
char *chunkStart = reinterpret_cast<char *>(i->memory.base());
char *chunkEnd = chunkStart + i->memory.size() - i->chunkSize;
for (char *chunk = chunkStart; chunk <= chunkEnd; chunk += i->chunkSize) {
Managed *m = reinterpret_cast<Managed *>(chunk);
Q_ASSERT((qintptr) chunk % 16 == 0);
- if (m->inUse)
+ if (m->inUse())
usedMem += i->chunkSize;
}
}
return usedMem;
}
+size_t MemoryManager::getAllocatedMem() const
+{
+ size_t total = 0;
+ for (int i = 0; i < m_d->heapChunks.size(); ++i)
+ total += m_d->heapChunks.at(i).memory.size();
+ return total;
+}
+
+size_t MemoryManager::getLargeItemsMem() const
+{
+ size_t total = 0;
+ for (const Data::LargeItem *i = m_d->largeItems; i != 0; i = i->next)
+ total += i->size;
+ return total;
+}
+
MemoryManager::~MemoryManager()
{
PersistentValuePrivate *persistent = m_persistentValues;
@@ -526,11 +551,6 @@ void MemoryManager::registerDeletable(GCDeletable *d)
m_d->deletable = d;
}
-ExecutionEngine *MemoryManager::engine() const
-{
- return m_d->engine;
-}
-
#ifdef DETAILED_MM_STATS
void MemoryManager::willAllocate(std::size_t size)
{
@@ -545,11 +565,11 @@ void MemoryManager::willAllocate(std::size_t size)
void MemoryManager::collectFromJSStack() const
{
- Value *v = engine()->jsStackBase;
- Value *top = engine()->jsStackTop;
+ Value *v = m_d->engine->jsStackBase;
+ Value *top = m_d->engine->jsStackTop;
while (v < top) {
Managed *m = v->asManaged();
- if (m && m->inUse)
+ if (m && m->inUse())
// Skip pointers to already freed objects, they are bogus as well
m->mark(m_d->engine);
++v;
diff --git a/src/qml/jsruntime/qv4mm_p.h b/src/qml/jsruntime/qv4mm_p.h
index 47020c12f0..f0025dc70e 100644
--- a/src/qml/jsruntime/qv4mm_p.h
+++ b/src/qml/jsruntime/qv4mm_p.h
@@ -99,10 +99,58 @@ public:
inline Managed *allocManaged(std::size_t size)
{
size = align(size);
- Managed *o = alloc(size);
+ Managed *o = allocData(size);
return o;
}
+ template <typename ManagedType>
+ ManagedType *alloc()
+ {
+ ManagedType *t = static_cast<ManagedType*>(allocManaged(sizeof(typename ManagedType::Data)));
+ (void)new (t->d()) typename ManagedType::Data();
+ return t;
+ }
+
+ template <typename ManagedType, typename Arg1>
+ ManagedType *alloc(Arg1 arg1)
+ {
+ ManagedType *t = static_cast<ManagedType*>(allocManaged(sizeof(typename ManagedType::Data)));
+ (void)new (t->d()) typename ManagedType::Data(arg1);
+ return t;
+ }
+
+ template <typename ManagedType, typename Arg1, typename Arg2>
+ ManagedType *alloc(Arg1 arg1, Arg2 arg2)
+ {
+ ManagedType *t = static_cast<ManagedType*>(allocManaged(sizeof(typename ManagedType::Data)));
+ (void)new (t->d()) typename ManagedType::Data(arg1, arg2);
+ return t;
+ }
+
+ template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3>
+ ManagedType *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3)
+ {
+ ManagedType *t = static_cast<ManagedType*>(allocManaged(sizeof(typename ManagedType::Data)));
+ (void)new (t->d()) typename ManagedType::Data(arg1, arg2, arg3);
+ return t;
+ }
+
+ template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+ ManagedType *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
+ {
+ ManagedType *t = static_cast<ManagedType*>(allocManaged(sizeof(typename ManagedType::Data)));
+ (void)new (t->d()) typename ManagedType::Data(arg1, arg2, arg3, arg4);
+ return t;
+ }
+
+ template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
+ ManagedType *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5)
+ {
+ ManagedType *t = static_cast<ManagedType*>(allocManaged(sizeof(typename ManagedType::Data)));
+ (void)new (t->d()) typename ManagedType::Data(arg1, arg2, arg3, arg4, arg5);
+ return t;
+ }
+
bool isGCBlocked() const;
void setGCBlocked(bool blockGC);
void runGC();
@@ -113,12 +161,14 @@ public:
void registerDeletable(GCDeletable *d);
+ size_t getUsedMem() const;
+ size_t getAllocatedMem() const;
+ size_t getLargeItemsMem() const;
+
protected:
/// expects size to be aligned
// TODO: try to inline
- Managed *alloc(std::size_t size);
-
- ExecutionEngine *engine() const;
+ Managed *allocData(std::size_t size);
#ifdef DETAILED_MM_STATS
void willAllocate(std::size_t size);
@@ -129,7 +179,6 @@ private:
void mark();
void sweep(bool lastSweep = false);
void sweep(char *chunkStart, std::size_t chunkSize, size_t size);
- uint getUsedMem();
protected:
QScopedPointer<Data> m_d;
diff --git a/src/qml/jsruntime/qv4numberobject.cpp b/src/qml/jsruntime/qv4numberobject.cpp
index c97e86f2cd..f1bac1109a 100644
--- a/src/qml/jsruntime/qv4numberobject.cpp
+++ b/src/qml/jsruntime/qv4numberobject.cpp
@@ -51,8 +51,8 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(NumberCtor);
DEFINE_OBJECT_VTABLE(NumberObject);
-NumberCtor::NumberCtor(ExecutionContext *scope)
- : FunctionObject(scope, QStringLiteral("Number"))
+NumberCtor::Data::Data(ExecutionContext *scope)
+ : FunctionObject::Data(scope, QStringLiteral("Number"))
{
setVTable(staticVTable());
}
@@ -71,7 +71,7 @@ ReturnedValue NumberCtor::call(Managed *, CallData *callData)
return Encode(dbl);
}
-void NumberPrototype::init(ExecutionEngine *engine, ObjectRef ctor)
+void NumberPrototype::init(ExecutionEngine *engine, Object *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
@@ -103,40 +103,40 @@ void NumberPrototype::init(ExecutionEngine *engine, ObjectRef ctor)
inline ReturnedValue thisNumberValue(ExecutionContext *ctx)
{
- if (ctx->callData->thisObject.isNumber())
- return ctx->callData->thisObject.asReturnedValue();
- NumberObject *n = ctx->callData->thisObject.asNumberObject();
+ if (ctx->d()->callData->thisObject.isNumber())
+ return ctx->d()->callData->thisObject.asReturnedValue();
+ NumberObject *n = ctx->d()->callData->thisObject.asNumberObject();
if (!n)
return ctx->throwTypeError();
- return n->value.asReturnedValue();
+ return n->value().asReturnedValue();
}
inline double thisNumber(ExecutionContext *ctx)
{
- if (ctx->callData->thisObject.isNumber())
- return ctx->callData->thisObject.asDouble();
- NumberObject *n = ctx->callData->thisObject.asNumberObject();
+ if (ctx->d()->callData->thisObject.isNumber())
+ return ctx->d()->callData->thisObject.asDouble();
+ NumberObject *n = ctx->d()->callData->thisObject.asNumberObject();
if (!n)
return ctx->throwTypeError();
- return n->value.asDouble();
+ return n->value().asDouble();
}
ReturnedValue NumberPrototype::method_toString(CallContext *ctx)
{
double num = thisNumber(ctx);
- if (ctx->engine->hasException)
+ if (ctx->d()->engine->hasException)
return Encode::undefined();
- if (ctx->callData->argc && !ctx->callData->args[0].isUndefined()) {
- int radix = ctx->callData->args[0].toInt32();
+ if (ctx->d()->callData->argc && !ctx->d()->callData->args[0].isUndefined()) {
+ int radix = ctx->d()->callData->args[0].toInt32();
if (radix < 2 || radix > 36)
return ctx->throwError(QString::fromLatin1("Number.prototype.toString: %0 is not a valid radix")
.arg(radix));
if (std::isnan(num)) {
- return ctx->engine->newString(QStringLiteral("NaN"))->asReturnedValue();
+ return ctx->d()->engine->newString(QStringLiteral("NaN"))->asReturnedValue();
} else if (qIsInf(num)) {
- return ctx->engine->newString(QLatin1String(num < 0 ? "-Infinity" : "Infinity"))->asReturnedValue();
+ return ctx->d()->engine->newString(QLatin1String(num < 0 ? "-Infinity" : "Infinity"))->asReturnedValue();
}
if (radix != 10) {
@@ -166,7 +166,7 @@ ReturnedValue NumberPrototype::method_toString(CallContext *ctx)
}
if (negative)
str.prepend(QLatin1Char('-'));
- return ctx->engine->newString(str)->asReturnedValue();
+ return ctx->d()->engine->newString(str)->asReturnedValue();
}
}
@@ -178,7 +178,7 @@ ReturnedValue NumberPrototype::method_toLocaleString(CallContext *ctx)
Scope scope(ctx);
ScopedValue v(scope, thisNumberValue(ctx));
ScopedString str(scope, v->toString(ctx));
- if (ctx->engine->hasException)
+ if (ctx->d()->engine->hasException)
return Encode::undefined();
return str.asReturnedValue();
}
@@ -191,19 +191,19 @@ ReturnedValue NumberPrototype::method_valueOf(CallContext *ctx)
ReturnedValue NumberPrototype::method_toFixed(CallContext *ctx)
{
double v = thisNumber(ctx);
- if (ctx->engine->hasException)
+ if (ctx->d()->engine->hasException)
return Encode::undefined();
double fdigits = 0;
- if (ctx->callData->argc > 0)
- fdigits = ctx->callData->args[0].toInteger();
+ if (ctx->d()->callData->argc > 0)
+ fdigits = ctx->d()->callData->args[0].toInteger();
if (std::isnan(fdigits))
fdigits = 0;
if (fdigits < 0 || fdigits > 20)
- return ctx->throwRangeError(ctx->callData->thisObject);
+ return ctx->throwRangeError(ctx->d()->callData->thisObject);
QString str;
if (std::isnan(v))
@@ -214,22 +214,22 @@ ReturnedValue NumberPrototype::method_toFixed(CallContext *ctx)
str = QString::number(v, 'f', int (fdigits));
else
return RuntimeHelpers::stringFromNumber(ctx, v)->asReturnedValue();
- return ctx->engine->newString(str)->asReturnedValue();
+ return ctx->d()->engine->newString(str)->asReturnedValue();
}
ReturnedValue NumberPrototype::method_toExponential(CallContext *ctx)
{
Scope scope(ctx);
double d = thisNumber(ctx);
- if (ctx->engine->hasException)
+ if (ctx->d()->engine->hasException)
return Encode::undefined();
int fdigits = -1;
- if (ctx->callData->argc && !ctx->callData->args[0].isUndefined()) {
- fdigits = ctx->callData->args[0].toInt32();
+ if (ctx->d()->callData->argc && !ctx->d()->callData->args[0].isUndefined()) {
+ fdigits = ctx->d()->callData->args[0].toInt32();
if (fdigits < 0 || fdigits > 20) {
- ScopedString error(scope, ctx->engine->newString(QStringLiteral("Number.prototype.toExponential: fractionDigits out of range")));
+ ScopedString error(scope, ctx->d()->engine->newString(QStringLiteral("Number.prototype.toExponential: fractionDigits out of range")));
return ctx->throwRangeError(error);
}
}
@@ -239,22 +239,22 @@ ReturnedValue NumberPrototype::method_toExponential(CallContext *ctx)
double_conversion::DoubleToStringConverter::EcmaScriptConverter().ToExponential(d, fdigits, &builder);
QString result = QString::fromLatin1(builder.Finalize());
- return ctx->engine->newString(result)->asReturnedValue();
+ return ctx->d()->engine->newString(result)->asReturnedValue();
}
ReturnedValue NumberPrototype::method_toPrecision(CallContext *ctx)
{
Scope scope(ctx);
ScopedValue v(scope, thisNumberValue(ctx));
- if (ctx->engine->hasException)
+ if (ctx->d()->engine->hasException)
return Encode::undefined();
- if (!ctx->callData->argc || ctx->callData->args[0].isUndefined())
+ if (!ctx->d()->callData->argc || ctx->d()->callData->args[0].isUndefined())
return RuntimeHelpers::toString(ctx, v);
- double precision = ctx->callData->args[0].toInt32();
+ double precision = ctx->d()->callData->args[0].toInt32();
if (precision < 1 || precision > 21) {
- ScopedString error(scope, ctx->engine->newString(QStringLiteral("Number.prototype.toPrecision: precision out of range")));
+ ScopedString error(scope, ctx->d()->engine->newString(QStringLiteral("Number.prototype.toPrecision: precision out of range")));
return ctx->throwRangeError(error);
}
@@ -263,5 +263,5 @@ ReturnedValue NumberPrototype::method_toPrecision(CallContext *ctx)
double_conversion::DoubleToStringConverter::EcmaScriptConverter().ToPrecision(v->asDouble(), precision, &builder);
QString result = QString::fromLatin1(builder.Finalize());
- return ctx->engine->newString(result)->asReturnedValue();
+ return ctx->d()->engine->newString(result)->asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4numberobject_p.h b/src/qml/jsruntime/qv4numberobject_p.h
index ccabcf6727..3e776f0f2f 100644
--- a/src/qml/jsruntime/qv4numberobject_p.h
+++ b/src/qml/jsruntime/qv4numberobject_p.h
@@ -51,8 +51,10 @@ namespace QV4 {
struct NumberCtor: FunctionObject
{
- V4_OBJECT
- NumberCtor(ExecutionContext *scope);
+ struct Data : FunctionObject::Data {
+ Data(ExecutionContext *scope);
+ };
+ V4_OBJECT(FunctionObject)
static ReturnedValue construct(Managed *that, CallData *callData);
static ReturnedValue call(Managed *, CallData *callData);
@@ -60,8 +62,7 @@ struct NumberCtor: FunctionObject
struct NumberPrototype: NumberObject
{
- NumberPrototype(InternalClass *ic): NumberObject(ic) {}
- void init(ExecutionEngine *engine, ObjectRef ctor);
+ void init(ExecutionEngine *engine, Object *ctor);
static ReturnedValue method_toString(CallContext *ctx);
static ReturnedValue method_toLocaleString(CallContext *ctx);
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index c8d360d511..e0f05a65f8 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -70,29 +70,16 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(Object);
-Object::Object(ExecutionEngine *engine)
- : Managed(engine->objectClass)
+Object::Data::Data(InternalClass *internalClass)
+ : Managed::Data(internalClass)
{
-}
-
-Object::Object(InternalClass *ic)
- : Managed(ic)
-{
- Q_ASSERT(internalClass->vtable && internalClass->vtable != &Managed::static_vtbl);
-
- Q_ASSERT(!memberData.d());
if (internalClass->size) {
- Scope scope(engine());
- ScopedObject protectThis(scope, this);
- memberData.ensureIndex(engine(), internalClass->size);
+ Scope scope(internalClass->engine);
+ ScopedObject o(scope, this);
+ o->memberData().ensureIndex(internalClass->engine, internalClass->size);
}
}
-Object::~Object()
-{
- _data = 0;
-}
-
bool Object::setPrototype(Object *proto)
{
Object *pp = proto;
@@ -101,20 +88,15 @@ bool Object::setPrototype(Object *proto)
return false;
pp = pp->prototype();
}
- internalClass = internalClass->changePrototype(proto);
+ setInternalClass(internalClass()->changePrototype(proto));
return true;
}
-void Object::destroy(Managed *that)
-{
- static_cast<Object *>(that)->~Object();
-}
-
void Object::put(ExecutionContext *ctx, const QString &name, const ValueRef value)
{
Scope scope(ctx);
- ScopedString n(scope, ctx->engine->newString(name));
- put(n, value);
+ ScopedString n(scope, ctx->d()->engine->newString(name));
+ put(n.getPointer(), value);
}
ReturnedValue Object::getValue(const ValueRef thisObject, const Property *p, PropertyAttributes attrs)
@@ -133,7 +115,7 @@ ReturnedValue Object::getValue(const ValueRef thisObject, const Property *p, Pro
void Object::putValue(Property *pd, PropertyAttributes attrs, const ValueRef value)
{
- if (internalClass->engine->hasException)
+ if (internalClass()->engine->hasException)
return;
if (attrs.isAccessor()) {
@@ -155,7 +137,7 @@ void Object::putValue(Property *pd, PropertyAttributes attrs, const ValueRef val
return;
reject:
- if (engine()->currentContext()->strictMode)
+ if (engine()->currentContext()->d()->strictMode)
engine()->currentContext()->throwTypeError();
}
@@ -164,7 +146,7 @@ void Object::defineDefaultProperty(const QString &name, ValueRef value)
ExecutionEngine *e = engine();
Scope scope(e);
ScopedString s(scope, e->newIdentifier(name));
- defineDefaultProperty(s, value);
+ defineDefaultProperty(s.getPointer(), value);
}
void Object::defineDefaultProperty(const QString &name, ReturnedValue (*code)(CallContext *), int argumentCount)
@@ -172,16 +154,16 @@ void Object::defineDefaultProperty(const QString &name, ReturnedValue (*code)(Ca
ExecutionEngine *e = engine();
Scope scope(e);
ScopedString s(scope, e->newIdentifier(name));
- Scoped<FunctionObject> function(scope, e->newBuiltinFunction(e->rootContext, s, code));
+ Scoped<FunctionObject> function(scope, BuiltinFunction::create(e->rootContext, s.getPointer(), code));
function->defineReadonlyProperty(e->id_length, Primitive::fromInt32(argumentCount));
- defineDefaultProperty(s, function);
+ defineDefaultProperty(s.getPointer(), function);
}
-void Object::defineDefaultProperty(const StringRef name, ReturnedValue (*code)(CallContext *), int argumentCount)
+void Object::defineDefaultProperty(String *name, ReturnedValue (*code)(CallContext *), int argumentCount)
{
ExecutionEngine *e = engine();
Scope scope(e);
- Scoped<FunctionObject> function(scope, e->newBuiltinFunction(e->rootContext, name, code));
+ Scoped<FunctionObject> function(scope, BuiltinFunction::create(e->rootContext, name, code));
function->defineReadonlyProperty(e->id_length, Primitive::fromInt32(argumentCount));
defineDefaultProperty(name, function);
}
@@ -191,16 +173,16 @@ void Object::defineAccessorProperty(const QString &name, ReturnedValue (*getter)
ExecutionEngine *e = engine();
Scope scope(e);
Scoped<String> s(scope, e->newIdentifier(name));
- defineAccessorProperty(s, getter, setter);
+ defineAccessorProperty(s.getPointer(), getter, setter);
}
-void Object::defineAccessorProperty(const StringRef name, ReturnedValue (*getter)(CallContext *), ReturnedValue (*setter)(CallContext *))
+void Object::defineAccessorProperty(String *name, ReturnedValue (*getter)(CallContext *), ReturnedValue (*setter)(CallContext *))
{
ExecutionEngine *v4 = engine();
QV4::Scope scope(v4);
ScopedProperty p(scope);
- p->setGetter(getter ? v4->newBuiltinFunction(v4->rootContext, name, getter)->getPointer() : 0);
- p->setSetter(setter ? v4->newBuiltinFunction(v4->rootContext, name, setter)->getPointer() : 0);
+ p->setGetter(getter ? ScopedFunctionObject(scope, BuiltinFunction::create(v4->rootContext, name, getter)).getPointer() : 0);
+ p->setSetter(setter ? ScopedFunctionObject(scope, BuiltinFunction::create(v4->rootContext, name, setter)).getPointer() : 0);
insertMember(name, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
}
@@ -209,10 +191,10 @@ void Object::defineReadonlyProperty(const QString &name, ValueRef value)
QV4::ExecutionEngine *e = engine();
Scope scope(e);
ScopedString s(scope, e->newIdentifier(name));
- defineReadonlyProperty(s, value);
+ defineReadonlyProperty(s.getPointer(), value);
}
-void Object::defineReadonlyProperty(const StringRef name, ValueRef value)
+void Object::defineReadonlyProperty(String *name, ValueRef value)
{
insertMember(name, value, Attr_ReadOnly);
}
@@ -221,45 +203,45 @@ void Object::markObjects(Managed *that, ExecutionEngine *e)
{
Object *o = static_cast<Object *>(that);
- o->memberData.mark(e);
- if (o->arrayData)
- o->arrayData->mark(e);
+ o->memberData().mark(e);
+ if (o->arrayData())
+ o->arrayData()->mark(e);
}
void Object::ensureMemberIndex(uint idx)
{
- memberData.ensureIndex(engine(), idx);
+ memberData().ensureIndex(engine(), idx);
}
-void Object::insertMember(const StringRef s, const Property &p, PropertyAttributes attributes)
+void Object::insertMember(String *s, const Property &p, PropertyAttributes attributes)
{
uint idx;
- InternalClass::addMember(this, s.getPointer(), attributes, &idx);
+ InternalClass::addMember(this, s, attributes, &idx);
- ensureMemberIndex(internalClass->size);
+ ensureMemberIndex(internalClass()->size);
if (attributes.isAccessor()) {
- hasAccessorProperty = 1;
+ setHasAccessorProperty();
Property *pp = propertyAt(idx);
pp->value = p.value;
pp->set = p.set;
} else {
- memberData[idx] = p.value;
+ memberData()[idx] = p.value;
}
}
// Section 8.12.1
-Property *Object::__getOwnProperty__(const StringRef name, PropertyAttributes *attrs)
+Property *Object::__getOwnProperty__(String *name, PropertyAttributes *attrs)
{
uint idx = name->asArrayIndex();
if (idx != UINT_MAX)
return __getOwnProperty__(idx, attrs);
- uint member = internalClass->find(name);
+ uint member = internalClass()->find(name);
if (member < UINT_MAX) {
if (attrs)
- *attrs = internalClass->propertyData[member];
+ *attrs = internalClass()->propertyData[member];
return propertyAt(member);
}
@@ -270,10 +252,10 @@ Property *Object::__getOwnProperty__(const StringRef name, PropertyAttributes *a
Property *Object::__getOwnProperty__(uint index, PropertyAttributes *attrs)
{
- Property *p = arrayData->getProperty(index);
+ Property *p = arrayData()->getProperty(index);
if (p) {
if (attrs)
- *attrs = arrayData->attributes(index);
+ *attrs = arrayData()->attributes(index);
return p;
}
if (isStringObject()) {
@@ -288,7 +270,7 @@ Property *Object::__getOwnProperty__(uint index, PropertyAttributes *attrs)
}
// Section 8.12.2
-Property *Object::__getPropertyDescriptor__(const StringRef name, PropertyAttributes *attrs) const
+Property *Object::__getPropertyDescriptor__(String *name, PropertyAttributes *attrs) const
{
uint idx = name->asArrayIndex();
if (idx != UINT_MAX)
@@ -297,10 +279,10 @@ Property *Object::__getPropertyDescriptor__(const StringRef name, PropertyAttrib
const Object *o = this;
while (o) {
- uint idx = o->internalClass->find(name.getPointer());
+ uint idx = o->internalClass()->find(name);
if (idx < UINT_MAX) {
if (attrs)
- *attrs = o->internalClass->propertyData[idx];
+ *attrs = o->internalClass()->propertyData[idx];
return o->propertyAt(idx);
}
@@ -315,10 +297,10 @@ Property *Object::__getPropertyDescriptor__(uint index, PropertyAttributes *attr
{
const Object *o = this;
while (o) {
- Property *p = o->arrayData->getProperty(index);
+ Property *p = o->arrayData()->getProperty(index);
if (p) {
if (attrs)
- *attrs = o->arrayData->attributes(index);
+ *attrs = o->arrayData()->attributes(index);
return p;
}
if (o->isStringObject()) {
@@ -336,7 +318,7 @@ Property *Object::__getPropertyDescriptor__(uint index, PropertyAttributes *attr
return 0;
}
-bool Object::hasProperty(const StringRef name) const
+bool Object::hasProperty(String *name) const
{
uint idx = name->asArrayIndex();
if (idx != UINT_MAX)
@@ -366,13 +348,13 @@ bool Object::hasProperty(uint index) const
return false;
}
-bool Object::hasOwnProperty(const StringRef name) const
+bool Object::hasOwnProperty(String *name) const
{
uint idx = name->asArrayIndex();
if (idx != UINT_MAX)
return hasOwnProperty(idx);
- if (internalClass->find(name) < UINT_MAX)
+ if (internalClass()->find(name) < UINT_MAX)
return true;
if (!query(name).isEmpty())
return true;
@@ -381,11 +363,11 @@ bool Object::hasOwnProperty(const StringRef name) const
bool Object::hasOwnProperty(uint index) const
{
- if (!arrayData->isEmpty(index))
+ if (!arrayData()->isEmpty(index))
return true;
if (isStringObject()) {
- String *s = static_cast<const StringObject *>(this)->value.asString();
- if (index < (uint)s->length())
+ String *s = static_cast<const StringObject *>(this)->d()->value.asString();
+ if (index < (uint)s->d()->length())
return true;
}
if (!queryIndexed(index).isEmpty())
@@ -403,7 +385,7 @@ ReturnedValue Object::call(Managed *m, CallData *)
return m->engine()->currentContext()->throwTypeError();
}
-ReturnedValue Object::get(Managed *m, const StringRef name, bool *hasProperty)
+ReturnedValue Object::get(Managed *m, String *name, bool *hasProperty)
{
return static_cast<Object *>(m)->internalGet(name, hasProperty);
}
@@ -413,7 +395,7 @@ ReturnedValue Object::getIndexed(Managed *m, uint index, bool *hasProperty)
return static_cast<Object *>(m)->internalGetIndexed(index, hasProperty);
}
-void Object::put(Managed *m, const StringRef name, const ValueRef value)
+void Object::put(Managed *m, String *name, const ValueRef value)
{
static_cast<Object *>(m)->internalPut(name, value);
}
@@ -423,16 +405,16 @@ void Object::putIndexed(Managed *m, uint index, const ValueRef value)
static_cast<Object *>(m)->internalPutIndexed(index, value);
}
-PropertyAttributes Object::query(const Managed *m, StringRef name)
+PropertyAttributes Object::query(const Managed *m, String *name)
{
uint idx = name->asArrayIndex();
if (idx != UINT_MAX)
return queryIndexed(m, idx);
const Object *o = static_cast<const Object *>(m);
- idx = o->internalClass->find(name.getPointer());
+ idx = o->internalClass()->find(name);
if (idx < UINT_MAX)
- return o->internalClass->propertyData[idx];
+ return o->internalClass()->propertyData[idx];
return Attr_Invalid;
}
@@ -440,18 +422,18 @@ PropertyAttributes Object::query(const Managed *m, StringRef name)
PropertyAttributes Object::queryIndexed(const Managed *m, uint index)
{
const Object *o = static_cast<const Object *>(m);
- if (o->arrayData->get(index) != Primitive::emptyValue().asReturnedValue())
- return o->arrayData->attributes(index);
+ if (o->arrayData()->get(index) != Primitive::emptyValue().asReturnedValue())
+ return o->arrayData()->attributes(index);
if (o->isStringObject()) {
- String *s = static_cast<const StringObject *>(o)->value.asString();
- if (index < (uint)s->length())
+ String *s = static_cast<const StringObject *>(o)->d()->value.asString();
+ if (index < (uint)s->d()->length())
return (Attr_NotWritable|Attr_NotConfigurable);
}
return Attr_Invalid;
}
-bool Object::deleteProperty(Managed *m, const StringRef name)
+bool Object::deleteProperty(Managed *m, String *name)
{
return static_cast<Object *>(m)->internalDeleteProperty(name);
}
@@ -497,46 +479,46 @@ void Object::setLookup(Managed *m, Lookup *l, const ValueRef value)
Scope scope(m->engine());
ScopedObject o(scope, static_cast<Object *>(m));
- InternalClass *c = o->internalClass;
+ InternalClass *c = o->internalClass();
uint idx = c->find(l->name);
if (!o->isArrayObject() || idx != ArrayObject::LengthPropertyIndex) {
- if (idx != UINT_MAX && o->internalClass->propertyData[idx].isData() && o->internalClass->propertyData[idx].isWritable()) {
- l->classList[0] = o->internalClass;
+ if (idx != UINT_MAX && o->internalClass()->propertyData[idx].isData() && o->internalClass()->propertyData[idx].isWritable()) {
+ l->classList[0] = o->internalClass();
l->index = idx;
l->setter = Lookup::setter0;
- o->memberData[idx] = *value;
+ o->memberData()[idx] = *value;
return;
}
if (idx != UINT_MAX) {
- o->putValue(o->propertyAt(idx), o->internalClass->propertyData[idx], value);
+ o->putValue(o->propertyAt(idx), o->internalClass()->propertyData[idx], value);
return;
}
}
ScopedString s(scope, l->name);
- o->put(s, value);
+ o->put(s.getPointer(), value);
- if (o->internalClass == c)
+ if (o->internalClass() == c)
return;
- idx = o->internalClass->find(l->name);
+ idx = o->internalClass()->find(l->name);
if (idx == UINT_MAX)
return;
l->classList[0] = c;
- l->classList[3] = o->internalClass;
+ l->classList[3] = o->internalClass();
l->index = idx;
if (!o->prototype()) {
l->setter = Lookup::setterInsert0;
return;
}
o = o->prototype();
- l->classList[1] = o->internalClass;
+ l->classList[1] = o->internalClass();
if (!o->prototype()) {
l->setter = Lookup::setterInsert1;
return;
}
o = o->prototype();
- l->classList[2] = o->internalClass;
+ l->classList[2] = o->internalClass();
if (!o->prototype()) {
l->setter = Lookup::setterInsert2;
return;
@@ -544,13 +526,13 @@ void Object::setLookup(Managed *m, Lookup *l, const ValueRef value)
l->setter = Lookup::setterGeneric;
}
-void Object::advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, Property *pd, PropertyAttributes *attrs)
+void Object::advanceIterator(Managed *m, ObjectIterator *it, String *&name, uint *index, Property *pd, PropertyAttributes *attrs)
{
Object *o = static_cast<Object *>(m);
name = (String *)0;
*index = UINT_MAX;
- if (o->arrayData) {
+ if (o->arrayData()) {
if (!it->arrayIndex)
it->arrayNode = o->sparseBegin();
@@ -559,9 +541,9 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uin
while (it->arrayNode != o->sparseEnd()) {
int k = it->arrayNode->key();
uint pidx = it->arrayNode->value;
- Property *p = reinterpret_cast<Property *>(o->arrayData->data + pidx);
+ Property *p = reinterpret_cast<Property *>(o->arrayData()->arrayData() + pidx);
it->arrayNode = it->arrayNode->nextNode();
- PropertyAttributes a = o->arrayData->attributes(k);
+ PropertyAttributes a = o->arrayData()->attributes(k);
if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) {
it->arrayIndex = k + 1;
*index = k;
@@ -574,9 +556,9 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uin
it->arrayIndex = UINT_MAX;
}
// dense arrays
- while (it->arrayIndex < o->arrayData->length()) {
- Value *val = o->arrayData->data + it->arrayIndex;
- PropertyAttributes a = o->arrayData->attributes(it->arrayIndex);
+ while (it->arrayIndex < o->arrayData()->length()) {
+ Value *val = o->arrayData()->arrayData() + it->arrayIndex;
+ PropertyAttributes a = o->arrayData()->attributes(it->arrayIndex);
++it->arrayIndex;
if (!val->isEmpty()
&& (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable())) {
@@ -588,8 +570,8 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uin
}
}
- while (it->memberIndex < o->internalClass->size) {
- String *n = o->internalClass->nameMap.at(it->memberIndex);
+ while (it->memberIndex < o->internalClass()->size) {
+ String *n = o->internalClass()->nameMap.at(it->memberIndex);
if (!n) {
// accessor properties have a dummy entry with n == 0
++it->memberIndex;
@@ -597,7 +579,7 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uin
}
Property *p = o->propertyAt(it->memberIndex);
- PropertyAttributes a = o->internalClass->propertyData[it->memberIndex];
+ PropertyAttributes a = o->internalClass()->propertyData[it->memberIndex];
++it->memberIndex;
if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) {
name = n;
@@ -611,7 +593,7 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uin
}
// Section 8.12.3
-ReturnedValue Object::internalGet(const StringRef name, bool *hasProperty)
+ReturnedValue Object::internalGet(String *name, bool *hasProperty)
{
uint idx = name->asArrayIndex();
if (idx != UINT_MAX)
@@ -621,11 +603,11 @@ ReturnedValue Object::internalGet(const StringRef name, bool *hasProperty)
Object *o = this;
while (o) {
- uint idx = o->internalClass->find(name.getPointer());
+ uint idx = o->internalClass()->find(name);
if (idx < UINT_MAX) {
if (hasProperty)
*hasProperty = true;
- return getValue(o->propertyAt(idx), o->internalClass->propertyData.at(idx));
+ return getValue(o->propertyAt(idx), o->internalClass()->propertyData.at(idx));
}
o = o->prototype();
@@ -642,10 +624,10 @@ ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty)
PropertyAttributes attrs;
Object *o = this;
while (o) {
- Property *p = o->arrayData->getProperty(index);
+ Property *p = o->arrayData()->getProperty(index);
if (p) {
pd = p;
- attrs = o->arrayData->attributes(index);
+ attrs = o->arrayData()->attributes(index);
break;
}
if (o->isStringObject()) {
@@ -671,9 +653,9 @@ ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty)
// Section 8.12.5
-void Object::internalPut(const StringRef name, const ValueRef value)
+void Object::internalPut(String *name, const ValueRef value)
{
- if (internalClass->engine->hasException)
+ if (internalClass()->engine->hasException)
return;
uint idx = name->asArrayIndex();
@@ -682,12 +664,12 @@ void Object::internalPut(const StringRef name, const ValueRef value)
name->makeIdentifier();
- uint member = internalClass->find(name.getPointer());
+ uint member = internalClass()->find(name);
Property *pd = 0;
PropertyAttributes attrs;
if (member < UINT_MAX) {
pd = propertyAt(member);
- attrs = internalClass->propertyData[member];
+ attrs = internalClass()->propertyData[member];
}
// clause 1
@@ -713,7 +695,7 @@ void Object::internalPut(const StringRef name, const ValueRef value)
}
return;
} else if (!prototype()) {
- if (!extensible)
+ if (!isExtensible())
goto reject;
} else {
// clause 4
@@ -721,10 +703,10 @@ void Object::internalPut(const StringRef name, const ValueRef value)
if (attrs.isAccessor()) {
if (!pd->setter())
goto reject;
- } else if (!extensible || !attrs.isWritable()) {
+ } else if (!isExtensible() || !attrs.isWritable()) {
goto reject;
}
- } else if (!extensible) {
+ } else if (!isExtensible()) {
goto reject;
}
}
@@ -747,7 +729,7 @@ void Object::internalPut(const StringRef name, const ValueRef value)
return;
reject:
- if (engine()->currentContext()->strictMode) {
+ if (engine()->currentContext()->d()->strictMode) {
QString message = QStringLiteral("Cannot assign to read-only property \"");
message += name->toQString();
message += QLatin1Char('\"');
@@ -757,14 +739,14 @@ void Object::internalPut(const StringRef name, const ValueRef value)
void Object::internalPutIndexed(uint index, const ValueRef value)
{
- if (internalClass->engine->hasException)
+ if (internalClass()->engine->hasException)
return;
PropertyAttributes attrs;
- Property *pd = arrayData->getProperty(index);
+ Property *pd = arrayData()->getProperty(index);
if (pd)
- attrs = arrayData->attributes(index);
+ attrs = arrayData()->attributes(index);
if (!pd && isStringObject()) {
pd = static_cast<StringObject *>(this)->getIndex(index);
@@ -785,7 +767,7 @@ void Object::internalPutIndexed(uint index, const ValueRef value)
pd->value = *value;
return;
} else if (!prototype()) {
- if (!extensible)
+ if (!isExtensible())
goto reject;
} else {
// clause 4
@@ -793,10 +775,10 @@ void Object::internalPutIndexed(uint index, const ValueRef value)
if (attrs.isAccessor()) {
if (!pd->setter())
goto reject;
- } else if (!extensible || !attrs.isWritable()) {
+ } else if (!isExtensible() || !attrs.isWritable()) {
goto reject;
}
- } else if (!extensible) {
+ } else if (!isExtensible()) {
goto reject;
}
}
@@ -819,14 +801,14 @@ void Object::internalPutIndexed(uint index, const ValueRef value)
return;
reject:
- if (engine()->currentContext()->strictMode)
+ if (engine()->currentContext()->d()->strictMode)
engine()->currentContext()->throwTypeError();
}
// Section 8.12.7
-bool Object::internalDeleteProperty(const StringRef name)
+bool Object::internalDeleteProperty(String *name)
{
- if (internalClass->engine->hasException)
+ if (internalClass()->engine->hasException)
return false;
uint idx = name->asArrayIndex();
@@ -835,13 +817,13 @@ bool Object::internalDeleteProperty(const StringRef name)
name->makeIdentifier();
- uint memberIdx = internalClass->find(name);
+ uint memberIdx = internalClass()->find(name);
if (memberIdx != UINT_MAX) {
- if (internalClass->propertyData[memberIdx].isConfigurable()) {
- InternalClass::removeMember(this, name->identifier);
+ if (internalClass()->propertyData[memberIdx].isConfigurable()) {
+ InternalClass::removeMember(this, name->identifier());
return true;
}
- if (engine()->currentContext()->strictMode)
+ if (engine()->currentContext()->d()->strictMode)
engine()->currentContext()->throwTypeError();
return false;
}
@@ -851,19 +833,19 @@ bool Object::internalDeleteProperty(const StringRef name)
bool Object::internalDeleteIndexedProperty(uint index)
{
- if (internalClass->engine->hasException)
+ if (internalClass()->engine->hasException)
return false;
- if (!arrayData || arrayData->vtable()->del(this, index))
+ if (!arrayData() || arrayData()->vtable()->del(this, index))
return true;
- if (engine()->currentContext()->strictMode)
+ if (engine()->currentContext()->d()->strictMode)
engine()->currentContext()->throwTypeError();
return false;
}
// Section 8.12.9
-bool Object::__defineOwnProperty__(ExecutionContext *ctx, const StringRef name, const Property &p, PropertyAttributes attrs)
+bool Object::__defineOwnProperty__(ExecutionContext *ctx, String *name, const Property &p, PropertyAttributes attrs)
{
uint idx = name->asArrayIndex();
if (idx != UINT_MAX)
@@ -876,10 +858,10 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, const StringRef name,
PropertyAttributes *cattrs;
uint memberIndex;
- if (isArrayObject() && name->equals(ctx->engine->id_length)) {
- assert(ArrayObject::LengthPropertyIndex == internalClass->find(ctx->engine->id_length));
+ if (isArrayObject() && name->equals(ctx->d()->engine->id_length)) {
+ assert(ArrayObject::LengthPropertyIndex == internalClass()->find(ctx->d()->engine->id_length));
Property *lp = propertyAt(ArrayObject::LengthPropertyIndex);
- cattrs = internalClass->propertyData.constData() + ArrayObject::LengthPropertyIndex;
+ cattrs = internalClass()->propertyData.constData() + ArrayObject::LengthPropertyIndex;
if (attrs.isEmpty() || p.isSubset(attrs, *lp, *cattrs))
return true;
if (!cattrs->isWritable() || attrs.type() == PropertyAttributes::Accessor || attrs.isConfigurable() || attrs.isEnumerable())
@@ -900,18 +882,18 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, const StringRef name,
if (!succeeded)
goto reject;
if (attrs.isAccessor())
- hasAccessorProperty = 1;
+ setHasAccessorProperty();
return true;
}
// Clause 1
- memberIndex = internalClass->find(name.getPointer());
+ memberIndex = internalClass()->find(name);
current = (memberIndex < UINT_MAX) ? propertyAt(memberIndex) : 0;
- cattrs = internalClass->propertyData.constData() + memberIndex;
+ cattrs = internalClass()->propertyData.constData() + memberIndex;
if (!current) {
// clause 3
- if (!extensible)
+ if (!isExtensible())
goto reject;
// clause 4
Property pd;
@@ -923,7 +905,7 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, const StringRef name,
return __defineOwnProperty__(ctx, memberIndex, name, p, attrs);
reject:
- if (ctx->strictMode)
+ if (ctx->d()->strictMode)
ctx->throwTypeError();
return false;
}
@@ -931,7 +913,7 @@ reject:
bool Object::__defineOwnProperty__(ExecutionContext *ctx, uint index, const Property &p, PropertyAttributes attrs)
{
// 15.4.5.1, 4b
- if (isArrayObject() && index >= getLength() && !internalClass->propertyData[ArrayObject::LengthPropertyIndex].isWritable())
+ if (isArrayObject() && index >= getLength() && !internalClass()->propertyData[ArrayObject::LengthPropertyIndex].isWritable())
goto reject;
if (ArgumentsObject::isNonStrictArgumentsObject(this))
@@ -939,7 +921,7 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, uint index, const Prop
return defineOwnProperty2(ctx, index, p, attrs);
reject:
- if (ctx->strictMode)
+ if (ctx->d()->strictMode)
ctx->throwTypeError();
return false;
}
@@ -950,14 +932,14 @@ bool Object::defineOwnProperty2(ExecutionContext *ctx, uint index, const Propert
// Clause 1
{
- current = arrayData->getProperty(index);
+ current = arrayData()->getProperty(index);
if (!current && isStringObject())
current = static_cast<StringObject *>(this)->getIndex(index);
}
if (!current) {
// clause 3
- if (!extensible)
+ if (!isExtensible())
goto reject;
// clause 4
Property pp;
@@ -973,14 +955,14 @@ bool Object::defineOwnProperty2(ExecutionContext *ctx, uint index, const Propert
return true;
}
- return __defineOwnProperty__(ctx, index, StringRef::null(), p, attrs);
+ return __defineOwnProperty__(ctx, index, 0, p, attrs);
reject:
- if (ctx->strictMode)
+ if (ctx->d()->strictMode)
ctx->throwTypeError();
return false;
}
-bool Object::__defineOwnProperty__(ExecutionContext *ctx, uint index, const StringRef member, const Property &p, PropertyAttributes attrs)
+bool Object::__defineOwnProperty__(ExecutionContext *ctx, uint index, String *member, const Property &p, PropertyAttributes attrs)
{
// clause 5
if (attrs.isEmpty())
@@ -988,12 +970,12 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, uint index, const Stri
Property *current;
PropertyAttributes cattrs;
- if (!member.isNull()) {
+ if (member) {
current = propertyAt(index);
- cattrs = internalClass->propertyData[index];
+ cattrs = internalClass()->propertyData[index];
} else {
- current = arrayData->getProperty(index);
- cattrs = arrayData->attributes(index);
+ current = arrayData()->getProperty(index);
+ cattrs = arrayData()->attributes(index);
}
// clause 6
@@ -1021,11 +1003,11 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, uint index, const Stri
// 9b
cattrs.setType(PropertyAttributes::Accessor);
cattrs.clearWritable();
- if (member.isNull()) {
+ if (!member) {
// need to convert the array and the slot
initSparseArray();
setArrayAttributes(index, cattrs);
- current = arrayData->getProperty(index);
+ current = arrayData()->getProperty(index);
}
current->setGetter(0);
current->setSetter(0);
@@ -1033,10 +1015,10 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, uint index, const Stri
// 9c
cattrs.setType(PropertyAttributes::Data);
cattrs.setWritable(false);
- if (member.isNull()) {
+ if (!member) {
// need to convert the array and the slot
setArrayAttributes(index, cattrs);
- current = arrayData->getProperty(index);
+ current = arrayData()->getProperty(index);
}
current->value = Primitive::undefinedValue();
}
@@ -1058,16 +1040,16 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, uint index, const Stri
accept:
current->merge(cattrs, p, attrs);
- if (!member.isNull()) {
- InternalClass::changeMember(this, member.getPointer(), cattrs);
+ if (member) {
+ InternalClass::changeMember(this, member, cattrs);
} else {
setArrayAttributes(index, cattrs);
}
if (cattrs.isAccessor())
- hasAccessorProperty = 1;
+ setHasAccessorProperty();
return true;
reject:
- if (ctx->strictMode)
+ if (ctx->d()->strictMode)
ctx->throwTypeError();
return false;
}
@@ -1076,8 +1058,8 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, uint index, const Stri
bool Object::__defineOwnProperty__(ExecutionContext *ctx, const QString &name, const Property &p, PropertyAttributes attrs)
{
Scope scope(ctx);
- ScopedString s(scope, ctx->engine->newString(name));
- return __defineOwnProperty__(ctx, s, p, attrs);
+ ScopedString s(scope, ctx->d()->engine->newString(name));
+ return __defineOwnProperty__(ctx, s.getPointer(), p, attrs);
}
@@ -1086,7 +1068,7 @@ void Object::copyArrayData(Object *other)
Q_ASSERT(isArrayObject());
Scope scope(engine());
- if (other->protoHasArray() || other->hasAccessorProperty) {
+ if (other->protoHasArray() || other->hasAccessorProperty()) {
uint len = other->getLength();
Q_ASSERT(len);
@@ -1094,30 +1076,30 @@ void Object::copyArrayData(Object *other)
for (uint i = 0; i < len; ++i) {
arraySet(i, (v = other->getIndexed(i)));
}
- } else if (!other->arrayData) {
+ } else if (!other->arrayData()) {
;
- } else if (other->hasAccessorProperty && other->arrayData->attrs && other->arrayData->isSparse()){
+ } else if (other->hasAccessorProperty() && other->arrayData()->attrs() && other->arrayData()->isSparse()){
// do it the slow way
ScopedValue v(scope);
- for (const SparseArrayNode *it = static_cast<const SparseArrayData *>(other->arrayData)->sparse->begin();
- it != static_cast<const SparseArrayData *>(other->arrayData)->sparse->end(); it = it->nextNode()) {
- v = other->getValue(reinterpret_cast<Property *>(other->arrayData->data + it->value), other->arrayData->attrs[it->value]);
+ for (const SparseArrayNode *it = static_cast<const SparseArrayData *>(other->arrayData())->sparse()->begin();
+ it != static_cast<const SparseArrayData *>(other->arrayData())->sparse()->end(); it = it->nextNode()) {
+ v = other->getValue(reinterpret_cast<Property *>(other->arrayData()->arrayData() + it->value), other->arrayData()->attrs()[it->value]);
arraySet(it->key(), v);
}
} else {
- Q_ASSERT(!arrayData && other->arrayData);
- ArrayData::realloc(this, other->arrayData->type, 0, other->arrayData->alloc, other->arrayData->attrs);
+ Q_ASSERT(!arrayData() && other->arrayData());
+ ArrayData::realloc(this, other->arrayData()->type(), 0, other->arrayData()->alloc(), other->arrayData()->attrs());
if (other->arrayType() == ArrayData::Sparse) {
- SparseArrayData *od = static_cast<SparseArrayData *>(other->arrayData);
- SparseArrayData *dd = static_cast<SparseArrayData *>(arrayData);
- dd->sparse = new SparseArray(*od->sparse);
- dd->freeList = od->freeList;
+ SparseArrayData *od = static_cast<SparseArrayData *>(other->arrayData());
+ SparseArrayData *dd = static_cast<SparseArrayData *>(arrayData());
+ dd->setSparse(new SparseArray(*od->sparse()));
+ dd->freeList() = od->freeList();
} else {
- SimpleArrayData *d = static_cast<SimpleArrayData *>(arrayData);
- d->len = static_cast<SimpleArrayData *>(other->arrayData)->len;
- d->offset = 0;
+ SimpleArrayData *d = static_cast<SimpleArrayData *>(arrayData());
+ d->len() = static_cast<SimpleArrayData *>(other->arrayData())->len();
+ d->offset() = 0;
}
- memcpy(arrayData->data, other->arrayData->data, arrayData->alloc*sizeof(Value));
+ memcpy(arrayData()->arrayData(), other->arrayData()->arrayData(), arrayData()->alloc()*sizeof(Value));
}
setArrayLengthUnchecked(other->getLength());
}
@@ -1132,15 +1114,15 @@ uint Object::getLength(const Managed *m)
bool Object::setArrayLength(uint newLen)
{
Q_ASSERT(isArrayObject());
- if (!internalClass->propertyData[ArrayObject::LengthPropertyIndex].isWritable())
+ if (!internalClass()->propertyData[ArrayObject::LengthPropertyIndex].isWritable())
return false;
uint oldLen = getLength();
bool ok = true;
if (newLen < oldLen) {
- if (!arrayData) {
+ if (!arrayData()) {
Q_ASSERT(!newLen);
} else {
- uint l = arrayData->vtable()->truncate(this, newLen);
+ uint l = arrayData()->vtable()->truncate(this, newLen);
if (l != newLen)
ok = false;
newLen = l;
@@ -1164,30 +1146,23 @@ void Object::initSparseArray()
DEFINE_OBJECT_VTABLE(ArrayObject);
-ArrayObject::ArrayObject(ExecutionEngine *engine, const QStringList &list)
- : Object(engine->arrayClass)
+ArrayObject::Data::Data(ExecutionEngine *engine, const QStringList &list)
+ : Object::Data(engine->arrayClass)
{
- init(engine);
+ init();
Scope scope(engine);
- ScopedValue protectThis(scope, this);
+ ScopedObject a(scope, this);
// Converts a QStringList to JS.
// The result is a new Array object with length equal to the length
// of the QStringList, and the elements being the QStringList's
// elements converted to JS Strings.
int len = list.count();
- arrayReserve(len);
+ a->arrayReserve(len);
ScopedValue v(scope);
for (int ii = 0; ii < len; ++ii)
- arrayPut(ii, (v = engine->newString(list.at(ii))));
- setArrayLengthUnchecked(len);
-}
-
-void ArrayObject::init(ExecutionEngine *engine)
-{
- Q_UNUSED(engine);
-
- memberData[LengthPropertyIndex] = Primitive::fromInt32(0);
+ a->arrayPut(ii, (v = engine->newString(list.at(ii))));
+ a->setArrayLengthUnchecked(len);
}
ReturnedValue ArrayObject::getLookup(Managed *m, Lookup *l)
@@ -1196,7 +1171,7 @@ ReturnedValue ArrayObject::getLookup(Managed *m, Lookup *l)
// special case, as the property is on the object itself
l->getter = Lookup::arrayLengthGetter;
ArrayObject *a = static_cast<ArrayObject *>(m);
- return a->memberData[ArrayObject::LengthPropertyIndex].asReturnedValue();
+ return a->memberData()[ArrayObject::LengthPropertyIndex].asReturnedValue();
}
return Object::getLookup(m, l);
}
@@ -1204,16 +1179,16 @@ ReturnedValue ArrayObject::getLookup(Managed *m, Lookup *l)
uint ArrayObject::getLength(const Managed *m)
{
const ArrayObject *a = static_cast<const ArrayObject *>(m);
- if (a->memberData[ArrayObject::LengthPropertyIndex].isInteger())
- return a->memberData[ArrayObject::LengthPropertyIndex].integerValue();
- return Primitive::toUInt32(a->memberData[ArrayObject::LengthPropertyIndex].doubleValue());
+ if (a->memberData()[ArrayObject::LengthPropertyIndex].isInteger())
+ return a->memberData()[ArrayObject::LengthPropertyIndex].integerValue();
+ return Primitive::toUInt32(a->memberData()[ArrayObject::LengthPropertyIndex].doubleValue());
}
QStringList ArrayObject::toQStringList() const
{
QStringList result;
- QV4::ExecutionEngine *engine = internalClass->engine;
+ QV4::ExecutionEngine *engine = internalClass()->engine;
Scope scope(engine);
ScopedValue v(scope);
diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h
index 40f38ee347..67459d5e77 100644
--- a/src/qml/jsruntime/qv4object_p.h
+++ b/src/qml/jsruntime/qv4object_p.h
@@ -103,39 +103,49 @@ struct URIErrorPrototype;
struct Q_QML_EXPORT Object: Managed {
- V4_OBJECT
+ struct Data : Managed::Data {
+ Data(ExecutionEngine *engine)
+ : Managed::Data(engine->objectClass)
+ {
+ }
+ Data(InternalClass *internal = 0);
+
+ Members memberData;
+ ArrayData *arrayData;
+ };
+ V4_OBJECT(Object)
Q_MANAGED_TYPE(Object)
+
enum {
IsObject = true
};
- Members memberData;
- ArrayData *arrayData;
+ Members &memberData() { return d()->memberData; }
+ const Members &memberData() const { return d()->memberData; }
+ const ArrayData *arrayData() const { return d()->arrayData; }
+ ArrayData *arrayData() { return d()->arrayData; }
+ void setArrayData(ArrayData *a) { d()->arrayData = a; }
- Property *propertyAt(uint index) const { return reinterpret_cast<Property *>(memberData.data() + index); }
+ Property *propertyAt(uint index) const { return reinterpret_cast<Property *>(memberData().data() + index); }
- Object(ExecutionEngine *engine);
- Object(InternalClass *internalClass);
- ~Object();
-
- const ObjectVTable *vtable() const { return reinterpret_cast<const ObjectVTable *>(internalClass->vtable); }
- Object *prototype() const { return internalClass->prototype; }
+ const ObjectVTable *vtable() const { return reinterpret_cast<const ObjectVTable *>(internalClass()->vtable); }
+ Object *prototype() const { return internalClass()->prototype; }
bool setPrototype(Object *proto);
- Property *__getOwnProperty__(const StringRef name, PropertyAttributes *attrs = 0);
+ Property *__getOwnProperty__(String *name, PropertyAttributes *attrs = 0);
Property *__getOwnProperty__(uint index, PropertyAttributes *attrs = 0);
- Property *__getPropertyDescriptor__(const StringRef name, PropertyAttributes *attrs = 0) const;
+ Property *__getPropertyDescriptor__(String *name, PropertyAttributes *attrs = 0) const;
Property *__getPropertyDescriptor__(uint index, PropertyAttributes *attrs = 0) const;
- bool hasProperty(const StringRef name) const;
+ bool hasProperty(String *name) const;
bool hasProperty(uint index) const;
- bool hasOwnProperty(const StringRef name) const;
+ bool hasOwnProperty(String *name) const;
bool hasOwnProperty(uint index) const;
- bool __defineOwnProperty__(ExecutionContext *ctx, uint index, const StringRef member, const Property &p, PropertyAttributes attrs);
- bool __defineOwnProperty__(ExecutionContext *ctx, const StringRef name, const Property &p, PropertyAttributes attrs);
+ bool __defineOwnProperty__(ExecutionContext *ctx, uint index, String *member, const Property &p, PropertyAttributes attrs);
+ bool __defineOwnProperty__(ExecutionContext *ctx, String *name, const Property &p, PropertyAttributes attrs);
bool __defineOwnProperty__(ExecutionContext *ctx, uint index, const Property &p, PropertyAttributes attrs);
bool __defineOwnProperty__(ExecutionContext *ctx, const QString &name, const Property &p, PropertyAttributes attrs);
bool defineOwnProperty2(ExecutionContext *ctx, uint index, const Property &p, PropertyAttributes attrs);
@@ -155,24 +165,31 @@ struct Q_QML_EXPORT Object: Managed {
void putValue(Property *pd, PropertyAttributes attrs, const ValueRef value);
/* The spec default: Writable: true, Enumerable: false, Configurable: true */
- void defineDefaultProperty(const StringRef name, ValueRef value) {
+ void defineDefaultProperty(String *name, ValueRef value) {
insertMember(name, value, Attr_Data|Attr_NotEnumerable);
}
void defineDefaultProperty(const QString &name, ValueRef value);
void defineDefaultProperty(const QString &name, ReturnedValue (*code)(CallContext *), int argumentCount = 0);
- void defineDefaultProperty(const StringRef name, ReturnedValue (*code)(CallContext *), int argumentCount = 0);
+ void defineDefaultProperty(String *name, ReturnedValue (*code)(CallContext *), int argumentCount = 0);
void defineAccessorProperty(const QString &name, ReturnedValue (*getter)(CallContext *), ReturnedValue (*setter)(CallContext *));
- void defineAccessorProperty(const StringRef name, ReturnedValue (*getter)(CallContext *), ReturnedValue (*setter)(CallContext *));
+ void defineAccessorProperty(String *name, ReturnedValue (*getter)(CallContext *), ReturnedValue (*setter)(CallContext *));
/* Fixed: Writable: false, Enumerable: false, Configurable: false */
void defineReadonlyProperty(const QString &name, ValueRef value);
- void defineReadonlyProperty(const StringRef name, ValueRef value);
+ void defineReadonlyProperty(String *name, ValueRef value);
- void insertMember(const StringRef s, const ValueRef v, PropertyAttributes attributes = Attr_Data) {
- insertMember(s, Property(*v), attributes);
+ void insertMember(String *s, const ValueRef v, PropertyAttributes attributes = Attr_Data) {
+ Property p(*v);
+ insertMember(s, p, attributes);
}
- void insertMember(const StringRef s, const Property &p, PropertyAttributes attributes);
+ void insertMember(String *s, const Property &p, PropertyAttributes attributes);
+
+ inline ExecutionEngine *engine() const { return internalClass()->engine; }
- inline ExecutionEngine *engine() const { return internalClass->engine; }
+ inline bool hasAccessorProperty() const { return d()->hasAccessorProperty; }
+ inline void setHasAccessorProperty() { d()->hasAccessorProperty = true; }
+
+ bool isExtensible() const { return d()->extensible; }
+ void setExtensible(bool b) { d()->extensible = b; }
// Array handling
@@ -186,30 +203,30 @@ public:
void arraySet(uint index, ValueRef value);
bool arrayPut(uint index, ValueRef value) {
- return arrayData->vtable()->put(this, index, value);
+ return arrayData()->vtable()->put(this, index, value);
}
bool arrayPut(uint index, Value *values, uint n) {
- return arrayData->vtable()->putArray(this, index, values, n);
+ return arrayData()->vtable()->putArray(this, index, values, n);
}
void setArrayAttributes(uint i, PropertyAttributes a) {
- Q_ASSERT(arrayData);
- if (arrayData->attrs || a != Attr_Data) {
+ Q_ASSERT(arrayData());
+ if (arrayData()->attrs() || a != Attr_Data) {
ArrayData::ensureAttributes(this);
a.resolve();
- arrayData->vtable()->setAttribute(this, i, a);
+ arrayData()->vtable()->setAttribute(this, i, a);
}
}
void push_back(const ValueRef v);
ArrayData::Type arrayType() const {
- return arrayData ? arrayData->type : ArrayData::Simple;
+ return arrayData() ? arrayData()->type() : ArrayData::Simple;
}
// ### remove me
void setArrayType(ArrayData::Type t) {
Q_ASSERT(t != ArrayData::Simple && t != ArrayData::Sparse);
arrayCreate();
- arrayData->type = t;
+ arrayData()->setType(t);
}
inline void arrayReserve(uint n) {
@@ -217,7 +234,7 @@ public:
}
void arrayCreate() {
- if (!arrayData)
+ if (!arrayData())
ArrayData::realloc(this, ArrayData::Simple, 0, 0, false);
#ifdef CHECK_SPARSE_ARRAYS
initSparseArray();
@@ -225,34 +242,34 @@ public:
}
void initSparseArray();
- SparseArrayNode *sparseBegin() { return arrayType() == ArrayData::Sparse ? static_cast<SparseArrayData *>(arrayData)->sparse->begin() : 0; }
- SparseArrayNode *sparseEnd() { return arrayType() == ArrayData::Sparse ? static_cast<SparseArrayData *>(arrayData)->sparse->end() : 0; }
+ SparseArrayNode *sparseBegin() { return arrayType() == ArrayData::Sparse ? static_cast<SparseArrayData *>(arrayData())->sparse()->begin() : 0; }
+ SparseArrayNode *sparseEnd() { return arrayType() == ArrayData::Sparse ? static_cast<SparseArrayData *>(arrayData())->sparse()->end() : 0; }
inline bool protoHasArray() {
Scope scope(engine());
Scoped<Object> p(scope, this);
while ((p = p->prototype()))
- if (p->arrayData)
+ if (p->arrayData())
return true;
return false;
}
void ensureMemberIndex(uint idx);
- inline ReturnedValue get(const StringRef name, bool *hasProperty = 0)
+ inline ReturnedValue get(String *name, bool *hasProperty = 0)
{ return vtable()->get(this, name, hasProperty); }
inline ReturnedValue getIndexed(uint idx, bool *hasProperty = 0)
{ return vtable()->getIndexed(this, idx, hasProperty); }
- inline void put(const StringRef name, const ValueRef v)
+ inline void put(String *name, const ValueRef v)
{ vtable()->put(this, name, v); }
inline void putIndexed(uint idx, const ValueRef v)
{ vtable()->putIndexed(this, idx, v); }
- PropertyAttributes query(StringRef name) const
+ PropertyAttributes query(String *name) const
{ return vtable()->query(this, name); }
PropertyAttributes queryIndexed(uint index) const
{ return vtable()->queryIndexed(this, index); }
- bool deleteProperty(const StringRef name)
+ bool deleteProperty(String *name)
{ return vtable()->deleteProperty(this, name); }
bool deleteIndexedProperty(uint index)
{ return vtable()->deleteIndexedProperty(this, index); }
@@ -260,7 +277,7 @@ public:
{ return vtable()->getLookup(this, l); }
void setLookup(Lookup *l, const ValueRef v)
{ vtable()->setLookup(this, l, v); }
- void advanceIterator(ObjectIterator *it, StringRef name, uint *index, Property *p, PropertyAttributes *attributes)
+ void advanceIterator(ObjectIterator *it, String *&name, uint *index, Property *p, PropertyAttributes *attributes)
{ vtable()->advanceIterator(this, it, name, index, p, attributes); }
uint getLength() const { return vtable()->getLength(this); }
@@ -269,29 +286,28 @@ public:
inline ReturnedValue call(CallData *d)
{ return vtable()->call(this, d); }
protected:
- static void destroy(Managed *that);
static void markObjects(Managed *that, ExecutionEngine *e);
static ReturnedValue construct(Managed *m, CallData *);
static ReturnedValue call(Managed *m, CallData *);
- static ReturnedValue get(Managed *m, const StringRef name, bool *hasProperty);
+ static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
- static void put(Managed *m, const StringRef name, const ValueRef value);
+ static void put(Managed *m, String *name, const ValueRef value);
static void putIndexed(Managed *m, uint index, const ValueRef value);
- static PropertyAttributes query(const Managed *m, StringRef name);
+ static PropertyAttributes query(const Managed *m, String *name);
static PropertyAttributes queryIndexed(const Managed *m, uint index);
- static bool deleteProperty(Managed *m, const StringRef name);
+ static bool deleteProperty(Managed *m, String *name);
static bool deleteIndexedProperty(Managed *m, uint index);
static ReturnedValue getLookup(Managed *m, Lookup *l);
static void setLookup(Managed *m, Lookup *l, const ValueRef v);
- static void advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, Property *p, PropertyAttributes *attributes);
+ static void advanceIterator(Managed *m, ObjectIterator *it, String *&name, uint *index, Property *p, PropertyAttributes *attributes);
static uint getLength(const Managed *m);
private:
- ReturnedValue internalGet(const StringRef name, bool *hasProperty);
+ ReturnedValue internalGet(String *name, bool *hasProperty);
ReturnedValue internalGetIndexed(uint index, bool *hasProperty);
- void internalPut(const StringRef name, const ValueRef value);
+ void internalPut(String *name, const ValueRef value);
void internalPutIndexed(uint index, const ValueRef value);
- bool internalDeleteProperty(const StringRef name);
+ bool internalDeleteProperty(String *name);
bool internalDeleteIndexedProperty(uint index);
friend struct ObjectIterator;
@@ -299,48 +315,62 @@ private:
};
struct BooleanObject: Object {
- V4_OBJECT
+ struct Data : Object::Data {
+ Data(ExecutionEngine *engine, const ValueRef val)
+ : Object::Data(engine->booleanClass)
+ {
+ value = val;
+ }
+ Data(InternalClass *ic)
+ : Object::Data(ic)
+ {
+ Q_ASSERT(internalClass->vtable == staticVTable());
+ value = Encode(false);
+ }
+ Value value;
+ };
+ V4_OBJECT(Object)
Q_MANAGED_TYPE(BooleanObject)
- Value value;
- BooleanObject(ExecutionEngine *engine, const ValueRef val)
- : Object(engine->booleanClass) {
- value = val;
- }
-protected:
- BooleanObject(InternalClass *ic)
- : Object(ic) {
- Q_ASSERT(internalClass->vtable == staticVTable());
- value = Encode(false);
- }
+
+ Value value() const { return d()->value; }
+
};
struct NumberObject: Object {
- V4_OBJECT
+ struct Data : Object::Data {
+ Data(ExecutionEngine *engine, const ValueRef val)
+ : Object::Data(engine->numberClass) {
+ value = val;
+ }
+ Data(InternalClass *ic)
+ : Object::Data(ic) {
+ Q_ASSERT(internalClass->vtable == staticVTable());
+ value = Encode((int)0);
+ }
+ Value value;
+ };
+ V4_OBJECT(Object)
Q_MANAGED_TYPE(NumberObject)
- Value value;
- NumberObject(ExecutionEngine *engine, const ValueRef val)
- : Object(engine->numberClass) {
- value = val;
- }
-protected:
- NumberObject(InternalClass *ic)
- : Object(ic) {
- Q_ASSERT(internalClass->vtable == staticVTable());
- value = Encode((int)0);
- }
+
+ Value value() const { return d()->value; }
+
};
struct ArrayObject: Object {
- V4_OBJECT
+ struct Data : Object::Data {
+ Data(ExecutionEngine *engine) : Object::Data(engine->arrayClass) { init(); }
+ Data(ExecutionEngine *engine, const QStringList &list);
+ Data(InternalClass *ic) : Object::Data(ic) { init(); }
+ void init()
+ { memberData[LengthPropertyIndex] = Primitive::fromInt32(0); }
+ };
+
+ V4_OBJECT(Object)
Q_MANAGED_TYPE(ArrayObject)
enum {
LengthPropertyIndex = 0
};
- ArrayObject(ExecutionEngine *engine) : Object(engine->arrayClass) { init(engine); }
- ArrayObject(ExecutionEngine *engine, const QStringList &list);
- ArrayObject(InternalClass *ic) : Object(ic) { init(ic->engine); }
-
void init(ExecutionEngine *engine);
static ReturnedValue getLookup(Managed *m, Lookup *l);
@@ -353,7 +383,7 @@ struct ArrayObject: Object {
inline void Object::setArrayLengthUnchecked(uint l)
{
if (isArrayObject())
- memberData[ArrayObject::LengthPropertyIndex] = Primitive::fromUInt32(l);
+ memberData()[ArrayObject::LengthPropertyIndex] = Primitive::fromUInt32(l);
}
inline void Object::push_back(const ValueRef v)
@@ -371,12 +401,12 @@ inline void Object::arraySet(uint index, const Property &p, PropertyAttributes a
// ### Clean up
arrayCreate();
if (attributes.isAccessor()) {
- hasAccessorProperty = 1;
+ setHasAccessorProperty();
initSparseArray();
- } else if (index > 0x1000 && index > 2*arrayData->alloc) {
+ } else if (index > 0x1000 && index > 2*arrayData()->alloc()) {
initSparseArray();
} else {
- arrayData->vtable()->reallocate(this, index + 1, false);
+ arrayData()->vtable()->reallocate(this, index + 1, false);
}
setArrayAttributes(index, attributes);
Property *pd = ArrayData::insert(this, index, attributes.isAccessor());
@@ -391,7 +421,7 @@ inline void Object::arraySet(uint index, const Property &p, PropertyAttributes a
inline void Object::arraySet(uint index, ValueRef value)
{
arrayCreate();
- if (index > 0x1000 && index > 2*arrayData->alloc) {
+ if (index > 0x1000 && index > 2*arrayData()->alloc()) {
initSparseArray();
}
Property *pd = ArrayData::insert(this, index);
@@ -418,23 +448,6 @@ inline ReturnedValue value_convert<Object>(ExecutionEngine *e, const Value &v)
}
#endif
-struct ObjectRef : public ManagedRef
-{
- DEFINE_REF_METHODS(Object, Managed)
-
- static ObjectRef fromValuePointer(Value *s) {
- ObjectRef r;
- r.ptr = s;
- if (sizeof(void *) == 8)
- r.ptr->val = 0;
- else
- *r.ptr = Value::fromManaged(0);
- return r;
- }
-};
-
-DEFINE_REF(ArrayObject, Object);
-
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4objectiterator.cpp b/src/qml/jsruntime/qv4objectiterator.cpp
index e5f693c323..216700fe69 100644
--- a/src/qml/jsruntime/qv4objectiterator.cpp
+++ b/src/qml/jsruntime/qv4objectiterator.cpp
@@ -46,63 +46,71 @@
using namespace QV4;
-ObjectIterator::ObjectIterator(Value *scratch1, Value *scratch2, const ObjectRef o, uint flags)
- : object(ObjectRef::fromValuePointer(scratch1))
- , current(ObjectRef::fromValuePointer(scratch2))
+ObjectIterator::ObjectIterator(Value *scratch1, Value *scratch2, Object *o, uint flags)
+ : object(scratch1)
+ , current(scratch2)
, arrayNode(0)
, arrayIndex(0)
, memberIndex(0)
, flags(flags)
{
- object = o.getPointer();
- current = o.getPointer();
-
- if (!!object && object->asArgumentsObject()) {
+ object->o = o;
+ current->o = o;
+#if QT_POINTER_SIZE == 4
+ object->tag = QV4::Value::Managed_Type;
+ current->tag = QV4::Value::Managed_Type;
+#endif
+
+ if (object->as<ArgumentsObject>()) {
Scope scope(object->engine());
Scoped<ArgumentsObject> (scope, object->asReturnedValue())->fullyCreate();
}
}
-ObjectIterator::ObjectIterator(Scope &scope, const ObjectRef o, uint flags)
- : object(ObjectRef::fromValuePointer(scope.alloc(1)))
- , current(ObjectRef::fromValuePointer(scope.alloc(1)))
+ObjectIterator::ObjectIterator(Scope &scope, Object *o, uint flags)
+ : object(scope.alloc(1))
+ , current(scope.alloc(1))
, arrayNode(0)
, arrayIndex(0)
, memberIndex(0)
, flags(flags)
{
- object = o;
- current = o;
-
- if (!!object && object->asArgumentsObject()) {
+ object->o = o;
+ current->o = o;
+#if QT_POINTER_SIZE == 4
+ object->tag = QV4::Value::Managed_Type;
+ current->tag = QV4::Value::Managed_Type;
+#endif
+
+ if (object->as<ArgumentsObject>()) {
Scope scope(object->engine());
Scoped<ArgumentsObject> (scope, object->asReturnedValue())->fullyCreate();
}
}
-void ObjectIterator::next(StringRef name, uint *index, Property *pd, PropertyAttributes *attrs)
+void ObjectIterator::next(String *&name, uint *index, Property *pd, PropertyAttributes *attrs)
{
name = (String *)0;
*index = UINT_MAX;
- if (!object) {
+ if (!object->asObject()) {
*attrs = PropertyAttributes();
return;
}
while (1) {
- if (!current)
+ if (!current->asObject())
break;
while (1) {
- current->advanceIterator(this, name, index, pd, attrs);
+ current->asObject()->advanceIterator(this, name, index, pd, attrs);
if (attrs->isEmpty())
break;
// check the property is not already defined earlier in the proto chain
- if (current != object) {
- Object *o = object;
+ if (current->asObject() != object->asObject()) {
+ Object *o = object->asObject();
bool shadowed = false;
- while (o != current) {
+ while (o != current->asObject()) {
if ((!!name && o->hasOwnProperty(name)) ||
(*index != UINT_MAX && o->hasOwnProperty(*index))) {
shadowed = true;
@@ -117,9 +125,9 @@ void ObjectIterator::next(StringRef name, uint *index, Property *pd, PropertyAtt
}
if (flags & WithProtoChain)
- current = current->prototype();
+ current->o = current->objectValue()->prototype();
else
- current = (Object *)0;
+ current->o = (Object *)0;
arrayIndex = 0;
memberIndex = 0;
@@ -129,7 +137,7 @@ void ObjectIterator::next(StringRef name, uint *index, Property *pd, PropertyAtt
ReturnedValue ObjectIterator::nextPropertyName(ValueRef value)
{
- if (!object)
+ if (!object->asObject())
return Encode::null();
PropertyAttributes attrs;
@@ -137,11 +145,13 @@ ReturnedValue ObjectIterator::nextPropertyName(ValueRef value)
uint index;
Scope scope(object->engine());
ScopedString name(scope);
- next(name, &index, &p, &attrs);
+ String *n;
+ next(n, &index, &p, &attrs);
+ name = n;
if (attrs.isEmpty())
return Encode::null();
- value = object->getValue(&p, attrs);
+ value = object->objectValue()->getValue(&p, attrs);
if (!!name)
return name->asReturnedValue();
@@ -151,7 +161,7 @@ ReturnedValue ObjectIterator::nextPropertyName(ValueRef value)
ReturnedValue ObjectIterator::nextPropertyNameAsString(ValueRef value)
{
- if (!object)
+ if (!object->asObject())
return Encode::null();
PropertyAttributes attrs;
@@ -159,11 +169,13 @@ ReturnedValue ObjectIterator::nextPropertyNameAsString(ValueRef value)
uint index;
Scope scope(object->engine());
ScopedString name(scope);
- next(name, &index, &p, &attrs);
+ String *n;
+ next(n, &index, &p, &attrs);
+ name = n;
if (attrs.isEmpty())
return Encode::null();
- value = object->getValue(&p, attrs);
+ value = object->objectValue()->getValue(&p, attrs);
if (!!name)
return name->asReturnedValue();
@@ -173,7 +185,7 @@ ReturnedValue ObjectIterator::nextPropertyNameAsString(ValueRef value)
ReturnedValue ObjectIterator::nextPropertyNameAsString()
{
- if (!object)
+ if (!object->asObject())
return Encode::null();
PropertyAttributes attrs;
@@ -181,7 +193,9 @@ ReturnedValue ObjectIterator::nextPropertyNameAsString()
uint index;
Scope scope(object->engine());
ScopedString name(scope);
- next(name, &index, &p, &attrs);
+ String *n;
+ next(n, &index, &p, &attrs);
+ name = n;
if (attrs.isEmpty())
return Encode::null();
@@ -197,7 +211,7 @@ DEFINE_OBJECT_VTABLE(ForEachIteratorObject);
void ForEachIteratorObject::markObjects(Managed *that, ExecutionEngine *e)
{
ForEachIteratorObject *o = static_cast<ForEachIteratorObject *>(that);
- o->workArea[0].mark(e);
- o->workArea[1].mark(e);
+ o->d()->workArea[0].mark(e);
+ o->d()->workArea[1].mark(e);
Object::markObjects(that, e);
}
diff --git a/src/qml/jsruntime/qv4objectiterator_p.h b/src/qml/jsruntime/qv4objectiterator_p.h
index c87f284288..f20ad17b4a 100644
--- a/src/qml/jsruntime/qv4objectiterator_p.h
+++ b/src/qml/jsruntime/qv4objectiterator_p.h
@@ -67,37 +67,38 @@ struct Q_QML_EXPORT ObjectIterator
WithProtoChain = 0x2,
};
- ObjectRef object;
- ObjectRef current;
+ Value *object;
+ Value *current;
SparseArrayNode *arrayNode;
uint arrayIndex;
uint memberIndex;
uint flags;
- ObjectIterator(Value *scratch1, Value *scratch2, const ObjectRef o, uint flags);
- ObjectIterator(Scope &scope, const ObjectRef o, uint flags);
- void next(StringRef name, uint *index, Property *pd, PropertyAttributes *attributes = 0);
+ ObjectIterator(Value *scratch1, Value *scratch2, Object *o, uint flags);
+ ObjectIterator(Scope &scope, Object *o, uint flags);
+ void next(String *&name, uint *index, Property *pd, PropertyAttributes *attributes = 0);
ReturnedValue nextPropertyName(ValueRef value);
ReturnedValue nextPropertyNameAsString(ValueRef value);
ReturnedValue nextPropertyNameAsString();
};
struct ForEachIteratorObject: Object {
- V4_OBJECT
+ struct Data : Object::Data {
+ Data(ExecutionContext *ctx, Object *o)
+ : Object::Data(ctx->engine())
+ , it(workArea, workArea + 1, o, ObjectIterator::EnumerableOnly|ObjectIterator::WithProtoChain) {
+ setVTable(staticVTable());
+ }
+ ObjectIterator it;
+ Value workArea[2];
+ };
+ V4_OBJECT(Object)
Q_MANAGED_TYPE(ForeachIteratorObject)
- ObjectIterator it;
- ForEachIteratorObject(ExecutionContext *ctx, const ObjectRef o)
- : Object(ctx->engine), it(workArea, workArea + 1,
- o, ObjectIterator::EnumerableOnly|ObjectIterator::WithProtoChain) {
- setVTable(staticVTable());
- }
- ReturnedValue nextPropertyName() { return it.nextPropertyNameAsString(); }
+ ReturnedValue nextPropertyName() { return d()->it.nextPropertyNameAsString(); }
protected:
static void markObjects(Managed *that, ExecutionEngine *e);
-
- Value workArea[2];
};
diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp
index 5c824bdfbd..6b8a19c7e6 100644
--- a/src/qml/jsruntime/qv4objectproto.cpp
+++ b/src/qml/jsruntime/qv4objectproto.cpp
@@ -74,8 +74,8 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(ObjectCtor);
-ObjectCtor::ObjectCtor(ExecutionContext *scope)
- : FunctionObject(scope, QStringLiteral("Object"))
+ObjectCtor::Data::Data(ExecutionContext *scope)
+ : FunctionObject::Data(scope, QStringLiteral("Object"))
{
setVTable(staticVTable());
}
@@ -102,7 +102,7 @@ ReturnedValue ObjectCtor::call(Managed *m, CallData *callData)
return RuntimeHelpers::toObject(m->engine()->currentContext(), ValueRef(&callData->args[0]));
}
-void ObjectPrototype::init(ExecutionEngine *v4, ObjectRef ctor)
+void ObjectPrototype::init(ExecutionEngine *v4, Object *ctor)
{
Scope scope(v4);
ScopedObject o(scope, this);
@@ -133,10 +133,9 @@ void ObjectPrototype::init(ExecutionEngine *v4, ObjectRef ctor)
defineDefaultProperty(QStringLiteral("__defineGetter__"), method_defineGetter, 2);
defineDefaultProperty(QStringLiteral("__defineSetter__"), method_defineSetter, 2);
- Scoped<String> id_proto(scope, v4->id___proto__);
- Property p(v4->newBuiltinFunction(v4->rootContext, id_proto, method_get_proto)->getPointer(),
- v4->newBuiltinFunction(v4->rootContext, id_proto, method_set_proto)->getPointer());
- insertMember(StringRef(v4->id___proto__), p, Attr_Accessor|Attr_NotEnumerable);
+ Property p(ScopedFunctionObject(scope, BuiltinFunction::create(v4->rootContext, v4->id___proto__, method_get_proto)).getPointer(),
+ ScopedFunctionObject(scope, BuiltinFunction::create(v4->rootContext, v4->id___proto__, method_set_proto)).getPointer());
+ insertMember(v4->id___proto__, p, Attr_Accessor|Attr_NotEnumerable);
}
ReturnedValue ObjectPrototype::method_getPrototypeOf(CallContext *ctx)
@@ -165,7 +164,7 @@ ReturnedValue ObjectPrototype::method_getOwnPropertyDescriptor(CallContext *ctx)
if (scope.hasException())
return Encode::undefined();
PropertyAttributes attrs;
- Property *desc = O->__getOwnProperty__(name, &attrs);
+ Property *desc = O->__getOwnProperty__(name.getPointer(), &attrs);
return fromPropertyDescriptor(ctx, desc, attrs);
}
@@ -176,7 +175,7 @@ ReturnedValue ObjectPrototype::method_getOwnPropertyNames(CallContext *context)
if (!O)
return context->throwTypeError();
- ScopedArrayObject array(scope, getOwnPropertyNames(context->engine, context->callData->args[0]));
+ ScopedArrayObject array(scope, getOwnPropertyNames(context->d()->engine, context->d()->callData->args[0]));
return array.asReturnedValue();
}
@@ -187,11 +186,11 @@ ReturnedValue ObjectPrototype::method_create(CallContext *ctx)
if (!O->isObject() && !O->isNull())
return ctx->throwTypeError();
- Scoped<Object> newObject(scope, ctx->engine->newObject());
+ Scoped<Object> newObject(scope, ctx->d()->engine->newObject());
newObject->setPrototype(O->asObject());
- if (ctx->callData->argc > 1 && !ctx->callData->args[1].isUndefined()) {
- ctx->callData->args[0] = newObject.asReturnedValue();
+ if (ctx->d()->callData->argc > 1 && !ctx->d()->callData->args[1].isUndefined()) {
+ ctx->d()->callData->args[0] = newObject.asReturnedValue();
return method_defineProperties(ctx);
}
@@ -216,7 +215,7 @@ ReturnedValue ObjectPrototype::method_defineProperty(CallContext *ctx)
if (scope.engine->hasException)
return Encode::undefined();
- if (!O->__defineOwnProperty__(ctx, name, pd, attrs))
+ if (!O->__defineOwnProperty__(ctx, name.getPointer(), pd, attrs))
return ctx->throwTypeError();
return O.asReturnedValue();
@@ -240,7 +239,9 @@ ReturnedValue ObjectPrototype::method_defineProperties(CallContext *ctx)
uint index;
PropertyAttributes attrs;
Property pd;
- it.next(name, &index, &pd, &attrs);
+ String *nm;
+ it.next(nm, &index, &pd, &attrs);
+ name = nm;
if (attrs.isEmpty())
break;
Property n;
@@ -251,7 +252,7 @@ ReturnedValue ObjectPrototype::method_defineProperties(CallContext *ctx)
return Encode::undefined();
bool ok;
if (name)
- ok = O->__defineOwnProperty__(ctx, name, n, nattrs);
+ ok = O->__defineOwnProperty__(ctx, name.getPointer(), n, nattrs);
else
ok = O->__defineOwnProperty__(ctx, index, n, nattrs);
if (!ok)
@@ -268,15 +269,15 @@ ReturnedValue ObjectPrototype::method_seal(CallContext *ctx)
if (!o)
return ctx->throwTypeError();
- o->extensible = false;
+ o->setExtensible(false);
- o->internalClass = o->internalClass->sealed();
+ o->setInternalClass(o->internalClass()->sealed());
- if (o->arrayData) {
+ if (o->arrayData()) {
ArrayData::ensureAttributes(o.getPointer());
- for (uint i = 0; i < o->arrayData->alloc; ++i) {
- if (!o->arrayData->isEmpty(i))
- o->arrayData->attrs[i].setConfigurable(false);
+ for (uint i = 0; i < o->arrayData()->alloc(); ++i) {
+ if (!o->arrayData()->isEmpty(i))
+ o->arrayData()->attrs()[i].setConfigurable(false);
}
}
@@ -293,17 +294,17 @@ ReturnedValue ObjectPrototype::method_freeze(CallContext *ctx)
if (ArgumentsObject::isNonStrictArgumentsObject(o.getPointer()))
Scoped<ArgumentsObject>(scope, o)->fullyCreate();
- o->extensible = false;
+ o->setExtensible(false);
- o->internalClass = o->internalClass->frozen();
+ o->setInternalClass(o->internalClass()->frozen());
- if (o->arrayData) {
+ if (o->arrayData()) {
ArrayData::ensureAttributes(o.getPointer());
- for (uint i = 0; i < o->arrayData->alloc; ++i) {
- if (!o->arrayData->isEmpty(i))
- o->arrayData->attrs[i].setConfigurable(false);
- if (o->arrayData->attrs[i].isData())
- o->arrayData->attrs[i].setWritable(false);
+ for (uint i = 0; i < o->arrayData()->alloc(); ++i) {
+ if (!o->arrayData()->isEmpty(i))
+ o->arrayData()->attrs()[i].setConfigurable(false);
+ if (o->arrayData()->attrs()[i].isData())
+ o->arrayData()->attrs()[i].setWritable(false);
}
}
return o.asReturnedValue();
@@ -316,7 +317,7 @@ ReturnedValue ObjectPrototype::method_preventExtensions(CallContext *ctx)
if (!o)
return ctx->throwTypeError();
- o->extensible = false;
+ o->setExtensible(false);
return o.asReturnedValue();
}
@@ -327,22 +328,22 @@ ReturnedValue ObjectPrototype::method_isSealed(CallContext *ctx)
if (!o)
return ctx->throwTypeError();
- if (o->extensible)
+ if (o->isExtensible())
return Encode(false);
- if (o->internalClass != o->internalClass->sealed())
+ if (o->internalClass() != o->internalClass()->sealed())
return Encode(false);
- if (!o->arrayData || !o->arrayData->length())
+ if (!o->arrayData() || !o->arrayData()->length())
return Encode(true);
- if (o->arrayData->length() && !o->arrayData->attrs)
+ if (o->arrayData()->length() && !o->arrayData()->attrs())
return Encode(false);
- for (uint i = 0; i < o->arrayData->alloc; ++i) {
+ for (uint i = 0; i < o->arrayData()->alloc(); ++i) {
// ### Fix for sparse arrays
- if (!o->arrayData->isEmpty(i))
- if (o->arrayData->attributes(i).isConfigurable())
+ if (!o->arrayData()->isEmpty(i))
+ if (o->arrayData()->attributes(i).isConfigurable())
return Encode(false);
}
@@ -356,22 +357,22 @@ ReturnedValue ObjectPrototype::method_isFrozen(CallContext *ctx)
if (!o)
return ctx->throwTypeError();
- if (o->extensible)
+ if (o->isExtensible())
return Encode(false);
- if (o->internalClass != o->internalClass->frozen())
+ if (o->internalClass() != o->internalClass()->frozen())
return Encode(false);
- if (!o->arrayData->length())
+ if (!o->arrayData()->length())
return Encode(true);
- if (o->arrayData->length() && !o->arrayData->attrs)
+ if (o->arrayData()->length() && !o->arrayData()->attrs())
return Encode(false);
- for (uint i = 0; i < o->arrayData->alloc; ++i) {
+ for (uint i = 0; i < o->arrayData()->alloc(); ++i) {
// ### Fix for sparse arrays
- if (!o->arrayData->isEmpty(i))
- if (o->arrayData->attributes(i).isConfigurable() || o->arrayData->attributes(i).isWritable())
+ if (!o->arrayData()->isEmpty(i))
+ if (o->arrayData()->attributes(i).isConfigurable() || o->arrayData()->attributes(i).isWritable())
return Encode(false);
}
@@ -385,7 +386,7 @@ ReturnedValue ObjectPrototype::method_isExtensible(CallContext *ctx)
if (!o)
return ctx->throwTypeError();
- return Encode((bool)o->extensible);
+ return Encode((bool)o->isExtensible());
}
ReturnedValue ObjectPrototype::method_keys(CallContext *ctx)
@@ -395,7 +396,7 @@ ReturnedValue ObjectPrototype::method_keys(CallContext *ctx)
if (!o)
return ctx->throwTypeError();
- Scoped<ArrayObject> a(scope, ctx->engine->newArrayObject());
+ Scoped<ArrayObject> a(scope, ctx->d()->engine->newArrayObject());
ObjectIterator it(scope, o, ObjectIterator::EnumerableOnly);
ScopedValue name(scope);
@@ -412,24 +413,24 @@ ReturnedValue ObjectPrototype::method_keys(CallContext *ctx)
ReturnedValue ObjectPrototype::method_toString(CallContext *ctx)
{
Scope scope(ctx);
- if (ctx->callData->thisObject.isUndefined()) {
- return ctx->engine->newString(QStringLiteral("[object Undefined]"))->asReturnedValue();
- } else if (ctx->callData->thisObject.isNull()) {
- return ctx->engine->newString(QStringLiteral("[object Null]"))->asReturnedValue();
+ if (ctx->d()->callData->thisObject.isUndefined()) {
+ return ctx->d()->engine->newString(QStringLiteral("[object Undefined]"))->asReturnedValue();
+ } else if (ctx->d()->callData->thisObject.isNull()) {
+ return ctx->d()->engine->newString(QStringLiteral("[object Null]"))->asReturnedValue();
} else {
- ScopedObject obj(scope, RuntimeHelpers::toObject(ctx, ValueRef(&ctx->callData->thisObject)));
+ ScopedObject obj(scope, RuntimeHelpers::toObject(ctx, ValueRef(&ctx->d()->callData->thisObject)));
QString className = obj->className();
- return ctx->engine->newString(QString::fromLatin1("[object %1]").arg(className))->asReturnedValue();
+ return ctx->d()->engine->newString(QString::fromLatin1("[object %1]").arg(className))->asReturnedValue();
}
}
ReturnedValue ObjectPrototype::method_toLocaleString(CallContext *ctx)
{
Scope scope(ctx);
- ScopedObject o(scope, ctx->callData->thisObject.toObject(ctx));
+ ScopedObject o(scope, ctx->d()->callData->thisObject.toObject(ctx));
if (!o)
return Encode::undefined();
- Scoped<FunctionObject> f(scope, o->get(ctx->engine->id_toString));
+ Scoped<FunctionObject> f(scope, o->get(ctx->d()->engine->id_toString));
if (!f)
return ctx->throwTypeError();
ScopedCallData callData(scope, 0);
@@ -440,8 +441,8 @@ ReturnedValue ObjectPrototype::method_toLocaleString(CallContext *ctx)
ReturnedValue ObjectPrototype::method_valueOf(CallContext *ctx)
{
Scope scope(ctx);
- ScopedValue v(scope, ctx->callData->thisObject.toObject(ctx));
- if (ctx->engine->hasException)
+ ScopedValue v(scope, ctx->d()->callData->thisObject.toObject(ctx));
+ if (ctx->d()->engine->hasException)
return Encode::undefined();
return v.asReturnedValue();
}
@@ -452,12 +453,12 @@ ReturnedValue ObjectPrototype::method_hasOwnProperty(CallContext *ctx)
Scoped<String> P(scope, ctx->argument(0), Scoped<String>::Convert);
if (scope.engine->hasException)
return Encode::undefined();
- Scoped<Object> O(scope, ctx->callData->thisObject, Scoped<Object>::Convert);
+ Scoped<Object> O(scope, ctx->d()->callData->thisObject, Scoped<Object>::Convert);
if (scope.engine->hasException)
return Encode::undefined();
- bool r = O->hasOwnProperty(P);
+ bool r = O->hasOwnProperty(P.getPointer());
if (!r)
- r = !O->query(P).isEmpty();
+ r = !O->query(P.getPointer()).isEmpty();
return Encode(r);
}
@@ -468,7 +469,7 @@ ReturnedValue ObjectPrototype::method_isPrototypeOf(CallContext *ctx)
if (!V)
return Encode(false);
- Scoped<Object> O(scope, ctx->callData->thisObject, Scoped<Object>::Convert);
+ Scoped<Object> O(scope, ctx->d()->callData->thisObject, Scoped<Object>::Convert);
if (scope.engine->hasException)
return Encode::undefined();
Scoped<Object> proto(scope, V->prototype());
@@ -487,17 +488,17 @@ ReturnedValue ObjectPrototype::method_propertyIsEnumerable(CallContext *ctx)
if (scope.engine->hasException)
return Encode::undefined();
- Scoped<Object> o(scope, ctx->callData->thisObject, Scoped<Object>::Convert);
+ Scoped<Object> o(scope, ctx->d()->callData->thisObject, Scoped<Object>::Convert);
if (scope.engine->hasException)
return Encode::undefined();
PropertyAttributes attrs;
- o->__getOwnProperty__(p, &attrs);
+ o->__getOwnProperty__(p.getPointer(), &attrs);
return Encode(attrs.isEnumerable());
}
ReturnedValue ObjectPrototype::method_defineGetter(CallContext *ctx)
{
- if (ctx->callData->argc < 2)
+ if (ctx->d()->callData->argc < 2)
return ctx->throwTypeError();
Scope scope(ctx);
@@ -509,23 +510,23 @@ ReturnedValue ObjectPrototype::method_defineGetter(CallContext *ctx)
if (scope.engine->hasException)
return Encode::undefined();
- Scoped<Object> o(scope, ctx->callData->thisObject);
+ Scoped<Object> o(scope, ctx->d()->callData->thisObject);
if (!o) {
- if (!ctx->callData->thisObject.isUndefined())
+ if (!ctx->d()->callData->thisObject.isUndefined())
return Encode::undefined();
- o = ctx->engine->globalObject;
+ o = ctx->d()->engine->globalObject;
}
Property pd;
pd.value = f;
pd.set = Primitive::emptyValue();
- o->__defineOwnProperty__(ctx, prop, pd, Attr_Accessor);
+ o->__defineOwnProperty__(ctx, prop.getPointer(), pd, Attr_Accessor);
return Encode::undefined();
}
ReturnedValue ObjectPrototype::method_defineSetter(CallContext *ctx)
{
- if (ctx->callData->argc < 2)
+ if (ctx->d()->callData->argc < 2)
return ctx->throwTypeError();
Scope scope(ctx);
@@ -537,24 +538,24 @@ ReturnedValue ObjectPrototype::method_defineSetter(CallContext *ctx)
if (scope.engine->hasException)
return Encode::undefined();
- Scoped<Object> o(scope, ctx->callData->thisObject);
+ Scoped<Object> o(scope, ctx->d()->callData->thisObject);
if (!o) {
- if (!ctx->callData->thisObject.isUndefined())
+ if (!ctx->d()->callData->thisObject.isUndefined())
return Encode::undefined();
- o = ctx->engine->globalObject;
+ o = ctx->d()->engine->globalObject;
}
Property pd;
pd.value = Primitive::emptyValue();
pd.set = f;
- o->__defineOwnProperty__(ctx, prop, pd, Attr_Accessor);
+ o->__defineOwnProperty__(ctx, prop.getPointer(), pd, Attr_Accessor);
return Encode::undefined();
}
ReturnedValue ObjectPrototype::method_get_proto(CallContext *ctx)
{
Scope scope(ctx);
- ScopedObject o(scope, ctx->callData->thisObject.asObject());
+ ScopedObject o(scope, ctx->d()->callData->thisObject.asObject());
if (!o)
return ctx->throwTypeError();
@@ -564,21 +565,21 @@ ReturnedValue ObjectPrototype::method_get_proto(CallContext *ctx)
ReturnedValue ObjectPrototype::method_set_proto(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Object> o(scope, ctx->callData->thisObject);
- if (!o || !ctx->callData->argc)
+ Scoped<Object> o(scope, ctx->d()->callData->thisObject);
+ if (!o || !ctx->d()->callData->argc)
return ctx->throwTypeError();
- if (ctx->callData->args[0].isNull()) {
+ if (ctx->d()->callData->args[0].isNull()) {
o->setPrototype(0);
return Encode::undefined();
}
- Scoped<Object> p(scope, ctx->callData->args[0]);
+ Scoped<Object> p(scope, ctx->d()->callData->args[0]);
bool ok = false;
if (!!p) {
if (o->prototype() == p.getPointer()) {
ok = true;
- } else if (o->extensible) {
+ } else if (o->isExtensible()) {
ok = o->setPrototype(p.getPointer());
}
}
@@ -601,14 +602,14 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionContext *ctx, const ValueRef
desc->set = Primitive::emptyValue();
ScopedValue tmp(scope);
- if (o->hasProperty(ctx->engine->id_enumerable))
- attrs->setEnumerable((tmp = o->get(ctx->engine->id_enumerable))->toBoolean());
+ if (o->hasProperty(ctx->d()->engine->id_enumerable))
+ attrs->setEnumerable((tmp = o->get(ctx->d()->engine->id_enumerable))->toBoolean());
- if (o->hasProperty(ctx->engine->id_configurable))
- attrs->setConfigurable((tmp = o->get(ctx->engine->id_configurable))->toBoolean());
+ if (o->hasProperty(ctx->d()->engine->id_configurable))
+ attrs->setConfigurable((tmp = o->get(ctx->d()->engine->id_configurable))->toBoolean());
- if (o->hasProperty(ctx->engine->id_get)) {
- ScopedValue get(scope, o->get(ctx->engine->id_get));
+ if (o->hasProperty(ctx->d()->engine->id_get)) {
+ ScopedValue get(scope, o->get(ctx->d()->engine->id_get));
FunctionObject *f = get->asFunctionObject();
if (f || get->isUndefined()) {
desc->value = get;
@@ -619,8 +620,8 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionContext *ctx, const ValueRef
attrs->setType(PropertyAttributes::Accessor);
}
- if (o->hasProperty(ctx->engine->id_set)) {
- ScopedValue set(scope, o->get(ctx->engine->id_set));
+ if (o->hasProperty(ctx->d()->engine->id_set)) {
+ ScopedValue set(scope, o->get(ctx->d()->engine->id_set));
FunctionObject *f = set->asFunctionObject();
if (f || set->isUndefined()) {
desc->set = set;
@@ -631,22 +632,22 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionContext *ctx, const ValueRef
attrs->setType(PropertyAttributes::Accessor);
}
- if (o->hasProperty(ctx->engine->id_writable)) {
+ if (o->hasProperty(ctx->d()->engine->id_writable)) {
if (attrs->isAccessor()) {
ctx->throwTypeError();
return;
}
- attrs->setWritable((tmp = o->get(ctx->engine->id_writable))->toBoolean());
+ attrs->setWritable((tmp = o->get(ctx->d()->engine->id_writable))->toBoolean());
// writable forces it to be a data descriptor
desc->value = Primitive::undefinedValue();
}
- if (o->hasProperty(ctx->engine->id_value)) {
+ if (o->hasProperty(ctx->d()->engine->id_value)) {
if (attrs->isAccessor()) {
ctx->throwTypeError();
return;
}
- desc->value = o->get(ctx->engine->id_value);
+ desc->value = o->get(ctx->d()->engine->id_value);
attrs->setType(PropertyAttributes::Data);
}
@@ -660,7 +661,7 @@ ReturnedValue ObjectPrototype::fromPropertyDescriptor(ExecutionContext *ctx, con
if (!desc)
return Encode::undefined();
- ExecutionEngine *engine = ctx->engine;
+ ExecutionEngine *engine = ctx->d()->engine;
Scope scope(engine);
// Let obj be the result of creating a new object as if by the expression new Object() where Object
// is the standard built-in constructor with that name.
@@ -671,24 +672,24 @@ ReturnedValue ObjectPrototype::fromPropertyDescriptor(ExecutionContext *ctx, con
if (attrs.isData()) {
pd.value = desc->value;
s = engine->newString(QStringLiteral("value"));
- o->__defineOwnProperty__(ctx, s, pd, Attr_Data);
+ o->__defineOwnProperty__(ctx, s.getPointer(), pd, Attr_Data);
pd.value = Primitive::fromBoolean(attrs.isWritable());
s = engine->newString(QStringLiteral("writable"));
- o->__defineOwnProperty__(ctx, s, pd, Attr_Data);
+ o->__defineOwnProperty__(ctx, s.getPointer(), pd, Attr_Data);
} else {
pd.value = desc->getter() ? desc->getter()->asReturnedValue() : Encode::undefined();
s = engine->newString(QStringLiteral("get"));
- o->__defineOwnProperty__(ctx, s, pd, Attr_Data);
+ o->__defineOwnProperty__(ctx, s.getPointer(), pd, Attr_Data);
pd.value = desc->setter() ? desc->setter()->asReturnedValue() : Encode::undefined();
s = engine->newString(QStringLiteral("set"));
- o->__defineOwnProperty__(ctx, s, pd, Attr_Data);
+ o->__defineOwnProperty__(ctx, s.getPointer(), pd, Attr_Data);
}
pd.value = Primitive::fromBoolean(attrs.isEnumerable());
s = engine->newString(QStringLiteral("enumerable"));
- o->__defineOwnProperty__(ctx, s, pd, Attr_Data);
+ o->__defineOwnProperty__(ctx, s.getPointer(), pd, Attr_Data);
pd.value = Primitive::fromBoolean(attrs.isConfigurable());
s = engine->newString(QStringLiteral("configurable"));
- o->__defineOwnProperty__(ctx, s, pd, Attr_Data);
+ o->__defineOwnProperty__(ctx, s.getPointer(), pd, Attr_Data);
return o.asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4objectproto_p.h b/src/qml/jsruntime/qv4objectproto_p.h
index 2b9974be06..c34b367223 100644
--- a/src/qml/jsruntime/qv4objectproto_p.h
+++ b/src/qml/jsruntime/qv4objectproto_p.h
@@ -51,8 +51,10 @@ namespace QV4 {
struct ObjectCtor: FunctionObject
{
- V4_OBJECT
- ObjectCtor(ExecutionContext *scope);
+ struct Data : FunctionObject::Data {
+ Data(ExecutionContext *scope);
+ };
+ V4_OBJECT(FunctionObject)
static ReturnedValue construct(Managed *that, CallData *callData);
static ReturnedValue call(Managed *that, CallData *callData);
@@ -60,9 +62,7 @@ struct ObjectCtor: FunctionObject
struct ObjectPrototype: Object
{
- ObjectPrototype(InternalClass *ic) : Object(ic) {}
-
- void init(ExecutionEngine *engine, ObjectRef ctor);
+ void init(ExecutionEngine *engine, Object *ctor);
static ReturnedValue method_getPrototypeOf(CallContext *ctx);
static ReturnedValue method_getOwnPropertyDescriptor(CallContext *ctx);
diff --git a/src/qml/jsruntime/qv4persistent_p.h b/src/qml/jsruntime/qv4persistent_p.h
index 21f37f3d96..7b0f80e06a 100644
--- a/src/qml/jsruntime/qv4persistent_p.h
+++ b/src/qml/jsruntime/qv4persistent_p.h
@@ -84,13 +84,11 @@ public:
PersistentValue(ReturnedValue val);
template<typename T>
PersistentValue(Returned<T> *obj);
- PersistentValue(const ManagedRef obj);
PersistentValue &operator=(const ValueRef other);
PersistentValue &operator=(const ScopedValue &other);
PersistentValue &operator =(ReturnedValue other);
template<typename T>
PersistentValue &operator=(Returned<T> *obj);
- PersistentValue &operator=(const ManagedRef obj);
~PersistentValue();
ReturnedValue value() const {
diff --git a/src/qml/jsruntime/qv4profiling.cpp b/src/qml/jsruntime/qv4profiling.cpp
index 8a0cc56448..b70e9de1a0 100644
--- a/src/qml/jsruntime/qv4profiling.cpp
+++ b/src/qml/jsruntime/qv4profiling.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qv4profiling_p.h"
+#include "qv4mm_p.h"
QT_BEGIN_NAMESPACE
@@ -60,10 +61,12 @@ FunctionCallProperties FunctionCall::resolve() const
}
-Profiler::Profiler() : enabled(false)
+Profiler::Profiler(QV4::ExecutionEngine *engine) : enabled(false), m_engine(engine)
{
static int metatype = qRegisterMetaType<QList<QV4::Profiling::FunctionCallProperties> >();
+ static int metatype2 = qRegisterMetaType<QList<QV4::Profiling::MemoryAllocationProperties> >();
Q_UNUSED(metatype);
+ Q_UNUSED(metatype2);
m_timer.start();
}
@@ -87,13 +90,29 @@ void Profiler::reportData()
FunctionCallProperties props = call.resolve();
resolved.insert(std::upper_bound(resolved.begin(), resolved.end(), props, comp), props);
}
- emit dataReady(resolved);
+ emit dataReady(resolved, m_memory_data);
}
void Profiler::startProfiling()
{
if (!enabled) {
m_data.clear();
+ m_memory_data.clear();
+
+ qint64 timestamp = m_timer.nsecsElapsed();
+ MemoryAllocationProperties heap = {timestamp,
+ (qint64)m_engine->memoryManager->getAllocatedMem(),
+ HeapPage};
+ m_memory_data.append(heap);
+ MemoryAllocationProperties small = {timestamp,
+ (qint64)m_engine->memoryManager->getUsedMem(),
+ SmallItem};
+ m_memory_data.append(small);
+ MemoryAllocationProperties large = {timestamp,
+ (qint64)m_engine->memoryManager->getLargeItemsMem(),
+ LargeItem};
+ m_memory_data.append(large);
+
enabled = true;
}
}
diff --git a/src/qml/jsruntime/qv4profiling_p.h b/src/qml/jsruntime/qv4profiling_p.h
index 6869b3134d..b9ddac0309 100644
--- a/src/qml/jsruntime/qv4profiling_p.h
+++ b/src/qml/jsruntime/qv4profiling_p.h
@@ -54,6 +54,12 @@ namespace QV4 {
namespace Profiling {
+enum MemoryType {
+ HeapPage,
+ LargeItem,
+ SmallItem
+};
+
struct FunctionCallProperties {
qint64 start;
qint64 end;
@@ -63,6 +69,12 @@ struct FunctionCallProperties {
int column;
};
+struct MemoryAllocationProperties {
+ qint64 timestamp;
+ qint64 size;
+ MemoryType type;
+};
+
class FunctionCall {
public:
@@ -101,6 +113,14 @@ private:
qint64 m_end;
};
+#define Q_V4_PROFILE_ALLOC(engine, size, type)\
+ (engine->profiler && engine->profiler->enabled ?\
+ engine->profiler->trackAlloc(size, type) : size)
+
+#define Q_V4_PROFILE_DEALLOC(engine, pointer, size, type) \
+ (engine->profiler && engine->profiler->enabled ?\
+ engine->profiler->trackDealloc(pointer, size, type) : pointer)
+
#define Q_V4_PROFILE(engine, ctx, function)\
((engine->profiler && engine->profiler->enabled) ?\
Profiling::FunctionCallProfiler::profileCall(engine->profiler, ctx, function) :\
@@ -110,7 +130,21 @@ class Q_QML_EXPORT Profiler : public QObject {
Q_OBJECT
Q_DISABLE_COPY(Profiler)
public:
- Profiler();
+ Profiler(QV4::ExecutionEngine *engine);
+
+ size_t trackAlloc(size_t size, MemoryType type)
+ {
+ MemoryAllocationProperties allocation = {m_timer.nsecsElapsed(), (qint64)size, type};
+ m_memory_data.append(allocation);
+ return size;
+ }
+
+ void *trackDealloc(void *pointer, size_t size, MemoryType type)
+ {
+ MemoryAllocationProperties allocation = {m_timer.nsecsElapsed(), -(qint64)size, type};
+ m_memory_data.append(allocation);
+ return pointer;
+ }
bool enabled;
@@ -121,11 +155,14 @@ public slots:
void setTimer(const QElapsedTimer &timer) { m_timer = timer; }
signals:
- void dataReady(const QList<QV4::Profiling::FunctionCallProperties> &);
+ void dataReady(const QList<QV4::Profiling::FunctionCallProperties> &,
+ const QList<QV4::Profiling::MemoryAllocationProperties> &);
private:
+ QV4::ExecutionEngine *m_engine;
QElapsedTimer m_timer;
QVector<FunctionCall> m_data;
+ QList<MemoryAllocationProperties> m_memory_data;
friend class FunctionCallProfiler;
};
@@ -160,10 +197,12 @@ public:
} // namespace Profiling
} // namespace QV4
+Q_DECLARE_TYPEINFO(QV4::Profiling::MemoryAllocationProperties, Q_MOVABLE_TYPE);
Q_DECLARE_TYPEINFO(QV4::Profiling::FunctionCallProperties, Q_MOVABLE_TYPE);
Q_DECLARE_TYPEINFO(QV4::Profiling::FunctionCall, Q_MOVABLE_TYPE);
QT_END_NAMESPACE
Q_DECLARE_METATYPE(QList<QV4::Profiling::FunctionCallProperties>)
+Q_DECLARE_METATYPE(QList<QV4::Profiling::MemoryAllocationProperties>)
#endif // QV4PROFILING_H
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index d64f821a38..e12b8f1756 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -87,7 +87,7 @@ QT_BEGIN_NAMESPACE
using namespace QV4;
-static QPair<QObject *, int> extractQtMethod(QV4::FunctionObjectRef function)
+static QPair<QObject *, int> extractQtMethod(QV4::FunctionObject *function)
{
QV4::ExecutionEngine *v4 = function->engine();
if (v4) {
@@ -239,14 +239,11 @@ static QV4::ReturnedValue LoadProperty(QV8Engine *engine, QObject *object,
}
}
-QObjectWrapper::QObjectWrapper(ExecutionEngine *engine, QObject *object)
- : Object(engine)
- , m_object(object)
+QObjectWrapper::Data::Data(ExecutionEngine *engine, QObject *object)
+ : Object::Data(engine)
+ , object(object)
{
setVTable(staticVTable());
-
- Scope scope(engine);
- ScopedObject protectThis(scope, this);
}
void QObjectWrapper::initializeBindings(ExecutionEngine *engine)
@@ -259,21 +256,21 @@ QQmlPropertyData *QObjectWrapper::findProperty(ExecutionEngine *engine, QQmlCont
{
Q_UNUSED(revisionMode);
- QQmlData *ddata = QQmlData::get(m_object, false);
+ QQmlData *ddata = QQmlData::get(d()->object, false);
if (!ddata)
return 0;
QQmlPropertyData *result = 0;
if (ddata && ddata->propertyCache)
- result = ddata->propertyCache->property(name, m_object, qmlContext);
+ result = ddata->propertyCache->property(name, d()->object, qmlContext);
else
- result = QQmlPropertyCache::property(engine->v8Engine->engine(), m_object, name, qmlContext, *local);
+ result = QQmlPropertyCache::property(engine->v8Engine->engine(), d()->object, name, qmlContext, *local);
return result;
}
ReturnedValue QObjectWrapper::getQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlContext, String *n, QObjectWrapper::RevisionMode revisionMode,
bool *hasProperty, bool includeImports)
{
- if (QQmlData::wasDeleted(m_object)) {
+ if (QQmlData::wasDeleted(d()->object)) {
if (hasProperty)
*hasProperty = false;
return QV4::Encode::undefined();
@@ -284,14 +281,14 @@ ReturnedValue QObjectWrapper::getQmlProperty(ExecutionContext *ctx, QQmlContextD
if (name->equals(scope.engine->id_destroy) || name->equals(scope.engine->id_toString)) {
int index = name->equals(scope.engine->id_destroy) ? QV4::QObjectMethod::DestroyMethod : QV4::QObjectMethod::ToStringMethod;
- QV4::ScopedValue method(scope, QV4::QObjectMethod::create(ctx->engine->rootContext, m_object, index));
+ QV4::ScopedValue method(scope, QV4::QObjectMethod::create(ctx->d()->engine->rootContext, d()->object, index));
if (hasProperty)
*hasProperty = true;
return method.asReturnedValue();
}
QQmlPropertyData local;
- QQmlPropertyData *result = findProperty(ctx->engine, qmlContext, name.getPointer(), revisionMode, &local);
+ QQmlPropertyData *result = findProperty(ctx->d()->engine, qmlContext, name.getPointer(), revisionMode, &local);
if (!result) {
if (includeImports && name->startsWithUpper()) {
@@ -306,18 +303,18 @@ ReturnedValue QObjectWrapper::getQmlProperty(ExecutionContext *ctx, QQmlContextD
if (r.scriptIndex != -1) {
return QV4::Encode::undefined();
} else if (r.type) {
- return QmlTypeWrapper::create(ctx->engine->v8Engine, m_object, r.type, QmlTypeWrapper::ExcludeEnums);
+ return QmlTypeWrapper::create(ctx->d()->engine->v8Engine, d()->object, r.type, QmlTypeWrapper::ExcludeEnums);
} else if (r.importNamespace) {
- return QmlTypeWrapper::create(ctx->engine->v8Engine, m_object, qmlContext->imports, r.importNamespace, QmlTypeWrapper::ExcludeEnums);
+ return QmlTypeWrapper::create(ctx->d()->engine->v8Engine, d()->object, qmlContext->imports, r.importNamespace, QmlTypeWrapper::ExcludeEnums);
}
Q_ASSERT(!"Unreachable");
}
}
}
- return QV4::Object::get(this, name, hasProperty);
+ return QV4::Object::get(this, name.getPointer(), hasProperty);
}
- QQmlData *ddata = QQmlData::get(m_object, false);
+ QQmlData *ddata = QQmlData::get(d()->object, false);
if (revisionMode == QV4::QObjectWrapper::CheckRevision && result->hasRevision()) {
if (ddata && ddata->propertyCache && !ddata->propertyCache->isAllowedInRevision(result)) {
@@ -330,7 +327,7 @@ ReturnedValue QObjectWrapper::getQmlProperty(ExecutionContext *ctx, QQmlContextD
if (hasProperty)
*hasProperty = true;
- return getProperty(m_object, ctx, result);
+ return getProperty(d()->object, ctx, result);
}
ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx, QQmlPropertyData *property, bool captureRequired)
@@ -345,23 +342,23 @@ ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx
Q_ASSERT(vmemo);
return vmemo->vmeMethod(property->coreIndex);
} else if (property->isV4Function()) {
- QV4::Scoped<QV4::Object> qmlcontextobject(scope, ctx->engine->qmlContextObject());
- return QV4::QObjectMethod::create(ctx->engine->rootContext, object, property->coreIndex, qmlcontextobject);
+ QV4::Scoped<QV4::Object> qmlcontextobject(scope, ctx->d()->engine->qmlContextObject());
+ return QV4::QObjectMethod::create(ctx->d()->engine->rootContext, object, property->coreIndex, qmlcontextobject);
} else if (property->isSignalHandler()) {
- QV4::Scoped<QV4::QmlSignalHandler> handler(scope, new (ctx->engine->memoryManager) QV4::QmlSignalHandler(ctx->engine, object, property->coreIndex));
+ QV4::Scoped<QV4::QmlSignalHandler> handler(scope, scope.engine->memoryManager->alloc<QV4::QmlSignalHandler>(ctx->d()->engine, object, property->coreIndex));
- QV4::ScopedString connect(scope, ctx->engine->newIdentifier(QStringLiteral("connect")));
- QV4::ScopedString disconnect(scope, ctx->engine->newIdentifier(QStringLiteral("disconnect")));
- handler->put(connect, QV4::ScopedValue(scope, ctx->engine->functionClass->prototype->get(connect)));
- handler->put(disconnect, QV4::ScopedValue(scope, ctx->engine->functionClass->prototype->get(disconnect)));
+ QV4::ScopedString connect(scope, ctx->d()->engine->newIdentifier(QStringLiteral("connect")));
+ QV4::ScopedString disconnect(scope, ctx->d()->engine->newIdentifier(QStringLiteral("disconnect")));
+ handler->put(connect.getPointer(), QV4::ScopedValue(scope, ctx->d()->engine->functionClass->prototype->get(connect.getPointer())));
+ handler->put(disconnect.getPointer(), QV4::ScopedValue(scope, ctx->d()->engine->functionClass->prototype->get(disconnect.getPointer())));
return handler.asReturnedValue();
} else {
- return QV4::QObjectMethod::create(ctx->engine->rootContext, object, property->coreIndex);
+ return QV4::QObjectMethod::create(ctx->d()->engine->rootContext, object, property->coreIndex);
}
}
- QQmlEnginePrivate *ep = ctx->engine->v8Engine->engine() ? QQmlEnginePrivate::get(ctx->engine->v8Engine->engine()) : 0;
+ QQmlEnginePrivate *ep = ctx->d()->engine->v8Engine->engine() ? QQmlEnginePrivate::get(ctx->d()->engine->v8Engine->engine()) : 0;
if (property->hasAccessors()) {
QQmlNotifier *n = 0;
@@ -370,7 +367,7 @@ ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx
if (ep && ep->propertyCapture && property->accessors->notifier)
nptr = &n;
- QV4::ScopedValue rv(scope, LoadProperty<ReadAccessor::Accessor>(ctx->engine->v8Engine, object, *property, nptr));
+ QV4::ScopedValue rv(scope, LoadProperty<ReadAccessor::Accessor>(ctx->d()->engine->v8Engine, object, *property, nptr));
if (captureRequired) {
if (property->accessors->notifier) {
@@ -392,9 +389,9 @@ ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx
Q_ASSERT(vmemo);
return vmemo->vmeProperty(property->coreIndex);
} else if (property->isDirect()) {
- return LoadProperty<ReadAccessor::Direct>(ctx->engine->v8Engine, object, *property, 0);
+ return LoadProperty<ReadAccessor::Direct>(ctx->d()->engine->v8Engine, object, *property, 0);
} else {
- return LoadProperty<ReadAccessor::Indirect>(ctx->engine->v8Engine, object, *property, 0);
+ return LoadProperty<ReadAccessor::Indirect>(ctx->d()->engine->v8Engine, object, *property, 0);
}
}
@@ -413,7 +410,7 @@ ReturnedValue QObjectWrapper::getQmlProperty(ExecutionContext *ctx, QQmlContextD
return QV4::Encode::null();
}
- QV4::Scoped<QObjectWrapper> wrapper(scope, wrap(ctx->engine, object));
+ QV4::Scoped<QObjectWrapper> wrapper(scope, wrap(ctx->d()->engine, object));
if (!wrapper) {
if (hasProperty)
*hasProperty = false;
@@ -431,7 +428,7 @@ bool QObjectWrapper::setQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlC
QQmlPropertyData local;
QQmlPropertyData *result = 0;
{
- result = QQmlPropertyCache::property(ctx->engine->v8Engine->engine(), object, name, qmlContext, local);
+ result = QQmlPropertyCache::property(ctx->d()->engine->v8Engine->engine(), object, name, qmlContext, local);
}
if (!result)
@@ -460,7 +457,7 @@ void QObjectWrapper::setProperty(QObject *object, ExecutionContext *ctx, QQmlPro
QV4::Scope scope(ctx);
QV4::ScopedFunctionObject f(scope, value);
if (f) {
- if (!f->bindingKeyFlag) {
+ if (!f->bindingKeyFlag()) {
if (!property->isVarProperty() && property->propType != qMetaTypeId<QJSValue>()) {
// assigning a JS function to a non var or QJSValue property or is not allowed.
QString error = QLatin1String("Cannot assign JavaScript function to ");
@@ -473,7 +470,7 @@ void QObjectWrapper::setProperty(QObject *object, ExecutionContext *ctx, QQmlPro
}
} else {
// binding assignment.
- QQmlContextData *callingQmlContext = QV4::QmlContextWrapper::callingContext(ctx->engine);
+ QQmlContextData *callingQmlContext = QV4::QmlContextWrapper::callingContext(ctx->d()->engine);
QV4::Scoped<QQmlBindingFunction> bindingFunction(scope, f);
bindingFunction->initBindingLocation();
@@ -513,7 +510,7 @@ void QObjectWrapper::setProperty(QObject *object, ExecutionContext *ctx, QQmlPro
} else if (value->isUndefined() && property->propType == QMetaType::QJsonValue) {
PROPERTY_STORE(QJsonValue, QJsonValue(QJsonValue::Undefined));
} else if (!newBinding && property->propType == qMetaTypeId<QJSValue>()) {
- PROPERTY_STORE(QJSValue, new QJSValuePrivate(ctx->engine, value));
+ PROPERTY_STORE(QJSValue, new QJSValuePrivate(ctx->d()->engine, value));
} else if (value->isUndefined()) {
QString error = QLatin1String("Cannot assign [undefined] to ");
if (!QMetaType::typeName(property->propType))
@@ -541,11 +538,11 @@ void QObjectWrapper::setProperty(QObject *object, ExecutionContext *ctx, QQmlPro
} else {
QVariant v;
if (property->isQList())
- v = ctx->engine->v8Engine->toVariant(value, qMetaTypeId<QList<QObject *> >());
+ v = ctx->d()->engine->v8Engine->toVariant(value, qMetaTypeId<QList<QObject *> >());
else
- v = ctx->engine->v8Engine->toVariant(value, property->propType);
+ v = ctx->d()->engine->v8Engine->toVariant(value, property->propType);
- QQmlContextData *callingQmlContext = QV4::QmlContextWrapper::callingContext(ctx->engine);
+ QQmlContextData *callingQmlContext = QV4::QmlContextWrapper::callingContext(ctx->d()->engine);
if (!QQmlPropertyPrivate::write(object, *property, v, callingQmlContext)) {
const char *valueType = 0;
if (v.userType() == QVariant::Invalid) valueType = "null";
@@ -634,9 +631,9 @@ ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx
void QObjectWrapper::setProperty(ExecutionContext *ctx, int propertyIndex, const ValueRef value)
{
- if (QQmlData::wasDeleted(m_object))
+ if (QQmlData::wasDeleted(d()->object))
return;
- QQmlData *ddata = QQmlData::get(m_object, /*create*/false);
+ QQmlData *ddata = QQmlData::get(d()->object, /*create*/false);
if (!ddata)
return;
@@ -644,7 +641,7 @@ void QObjectWrapper::setProperty(ExecutionContext *ctx, int propertyIndex, const
Q_ASSERT(cache);
QQmlPropertyData *property = cache->property(propertyIndex);
Q_ASSERT(property); // We resolved this property earlier, so it better exist!
- return setProperty(m_object, ctx, property, value);
+ return setProperty(d()->object, ctx, property, value);
}
bool QObjectWrapper::isEqualTo(Managed *a, Managed *b)
@@ -661,28 +658,28 @@ ReturnedValue QObjectWrapper::create(ExecutionEngine *engine, QObject *object)
QQmlEngine *qmlEngine = engine->v8Engine->engine();
if (qmlEngine)
QQmlData::ensurePropertyCache(qmlEngine, object);
- return (new (engine->memoryManager) QV4::QObjectWrapper(engine, object))->asReturnedValue();
+ return (engine->memoryManager->alloc<QV4::QObjectWrapper>(engine, object))->asReturnedValue();
}
-QV4::ReturnedValue QObjectWrapper::get(Managed *m, const StringRef name, bool *hasProperty)
+QV4::ReturnedValue QObjectWrapper::get(Managed *m, String *name, bool *hasProperty)
{
QObjectWrapper *that = static_cast<QObjectWrapper*>(m);
ExecutionEngine *v4 = m->engine();
QQmlContextData *qmlContext = QV4::QmlContextWrapper::callingContext(v4);
- return that->getQmlProperty(v4->currentContext(), qmlContext, name.getPointer(), IgnoreRevision, hasProperty, /*includeImports*/ true);
+ return that->getQmlProperty(v4->currentContext(), qmlContext, name, IgnoreRevision, hasProperty, /*includeImports*/ true);
}
-void QObjectWrapper::put(Managed *m, const StringRef name, const ValueRef value)
+void QObjectWrapper::put(Managed *m, String *name, const ValueRef value)
{
QObjectWrapper *that = static_cast<QObjectWrapper*>(m);
ExecutionEngine *v4 = m->engine();
- if (v4->hasException || QQmlData::wasDeleted(that->m_object))
+ if (v4->hasException || QQmlData::wasDeleted(that->d()->object))
return;
QQmlContextData *qmlContext = QV4::QmlContextWrapper::callingContext(v4);
- if (!setQmlProperty(v4->currentContext(), qmlContext, that->m_object, name.getPointer(), QV4::QObjectWrapper::IgnoreRevision, value)) {
- QQmlData *ddata = QQmlData::get(that->m_object);
+ if (!setQmlProperty(v4->currentContext(), qmlContext, that->d()->object, name, QV4::QObjectWrapper::IgnoreRevision, value)) {
+ QQmlData *ddata = QQmlData::get(that->d()->object);
// Types created by QML are not extensible at run-time, but for other QObjects we can store them
// as regular JavaScript properties, like on JavaScript objects.
if (ddata && ddata->context) {
@@ -695,7 +692,7 @@ void QObjectWrapper::put(Managed *m, const StringRef name, const ValueRef value)
}
}
-PropertyAttributes QObjectWrapper::query(const Managed *m, StringRef name)
+PropertyAttributes QObjectWrapper::query(const Managed *m, String *name)
{
const QObjectWrapper *that = static_cast<const QObjectWrapper*>(m);
ExecutionEngine *engine = that->engine();
@@ -708,27 +705,36 @@ PropertyAttributes QObjectWrapper::query(const Managed *m, StringRef name)
return QV4::Object::query(m, name);
}
-void QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, Property *p, PropertyAttributes *attributes)
+void QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, String *&name, uint *index, Property *p, PropertyAttributes *attributes)
{
+ // Used to block access to QObject::destroyed() and QObject::deleteLater() from QML
+ static const int destroyedIdx1 = QObject::staticMetaObject.indexOfSignal("destroyed(QObject*)");
+ static const int destroyedIdx2 = QObject::staticMetaObject.indexOfSignal("destroyed()");
+ static const int deleteLaterIdx = QObject::staticMetaObject.indexOfSlot("deleteLater()");
+
name = (String *)0;
*index = UINT_MAX;
QObjectWrapper *that = static_cast<QObjectWrapper*>(m);
- if (that->m_object) {
- const QMetaObject *mo = that->m_object->metaObject();
+ if (that->d()->object) {
+ const QMetaObject *mo = that->d()->object->metaObject();
const int propertyCount = mo->propertyCount();
if (it->arrayIndex < static_cast<uint>(propertyCount)) {
- name = that->engine()->newString(QString::fromUtf8(mo->property(it->arrayIndex).name()));
+ name = that->engine()->newString(QString::fromUtf8(mo->property(it->arrayIndex).name()))->getPointer();
++it->arrayIndex;
*attributes = QV4::Attr_Data;
p->value = that->get(name);
return;
}
const int methodCount = mo->methodCount();
- if (it->arrayIndex < static_cast<uint>(propertyCount + methodCount)) {
- name = that->engine()->newString(QString::fromUtf8(mo->method(it->arrayIndex - propertyCount).name()));
+ while (it->arrayIndex < static_cast<uint>(propertyCount + methodCount)) {
+ const int index = it->arrayIndex - propertyCount;
+ const QMetaMethod method = mo->method(index);
++it->arrayIndex;
+ if (method.access() == QMetaMethod::Private || index == deleteLaterIdx || index == destroyedIdx1 || index == destroyedIdx2)
+ continue;
+ name = that->engine()->newString(QString::fromUtf8(method.name()))->getPointer();
*attributes = QV4::Attr_Data;
p->value = that->get(name);
return;
@@ -857,10 +863,10 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase
ReturnedValue QObjectWrapper::method_connect(CallContext *ctx)
{
- if (ctx->callData->argc == 0)
+ if (ctx->d()->callData->argc == 0)
V4THROW_ERROR("Function.prototype.connect: no arguments given");
- QPair<QObject *, int> signalInfo = extractQtSignal(ctx->callData->thisObject);
+ QPair<QObject *, int> signalInfo = extractQtSignal(ctx->d()->callData->thisObject);
QObject *signalObject = signalInfo.first;
int signalIndex = signalInfo.second; // in method range, not signal range!
@@ -877,11 +883,11 @@ ReturnedValue QObjectWrapper::method_connect(CallContext *ctx)
QV4::ScopedFunctionObject f(scope);
QV4::ScopedValue thisObject (scope, QV4::Encode::undefined());
- if (ctx->callData->argc == 1) {
- f = ctx->callData->args[0];
- } else if (ctx->callData->argc >= 2) {
- thisObject = ctx->callData->args[0];
- f = ctx->callData->args[1];
+ if (ctx->d()->callData->argc == 1) {
+ f = ctx->d()->callData->args[0];
+ } else if (ctx->d()->callData->argc >= 2) {
+ thisObject = ctx->d()->callData->args[0];
+ f = ctx->d()->callData->args[1];
}
if (!f)
@@ -908,12 +914,12 @@ ReturnedValue QObjectWrapper::method_connect(CallContext *ctx)
ReturnedValue QObjectWrapper::method_disconnect(CallContext *ctx)
{
- if (ctx->callData->argc == 0)
+ if (ctx->d()->callData->argc == 0)
V4THROW_ERROR("Function.prototype.disconnect: no arguments given");
QV4::Scope scope(ctx);
- QPair<QObject *, int> signalInfo = extractQtSignal(ctx->callData->thisObject);
+ QPair<QObject *, int> signalInfo = extractQtSignal(ctx->d()->callData->thisObject);
QObject *signalObject = signalInfo.first;
int signalIndex = signalInfo.second;
@@ -929,11 +935,11 @@ ReturnedValue QObjectWrapper::method_disconnect(CallContext *ctx)
QV4::ScopedFunctionObject functionValue(scope);
QV4::ScopedValue functionThisValue(scope, QV4::Encode::undefined());
- if (ctx->callData->argc == 1) {
- functionValue = ctx->callData->args[0];
- } else if (ctx->callData->argc >= 2) {
- functionThisValue = ctx->callData->args[0];
- functionValue = ctx->callData->args[1];
+ if (ctx->d()->callData->argc == 1) {
+ functionValue = ctx->d()->callData->args[0];
+ } else if (ctx->d()->callData->argc >= 2) {
+ functionThisValue = ctx->d()->callData->args[0];
+ functionValue = ctx->d()->callData->args[1];
}
if (!functionValue)
@@ -945,7 +951,7 @@ ReturnedValue QObjectWrapper::method_disconnect(CallContext *ctx)
QPair<QObject *, int> functionData = extractQtMethod(functionValue);
void *a[] = {
- ctx->engine,
+ ctx->d()->engine,
functionValue.ptr,
functionThisValue.ptr,
functionData.first,
@@ -975,7 +981,7 @@ void QObjectWrapper::markObjects(Managed *that, QV4::ExecutionEngine *e)
{
QObjectWrapper *This = static_cast<QObjectWrapper*>(that);
- if (QObject *o = This->m_object.data()) {
+ if (QObject *o = This->d()->object.data()) {
QQmlVMEMetaObject *vme = QQmlVMEMetaObject::get(o);
if (vme)
vme->mark(e);
@@ -1017,9 +1023,9 @@ namespace {
void QObjectWrapper::destroy(Managed *that)
{
QObjectWrapper *This = static_cast<QObjectWrapper*>(that);
- QPointer<QObject> object = This->m_object;
+ QPointer<QObject> object = This->d()->object;
ExecutionEngine *engine = This->engine();
- This->~QObjectWrapper();
+ This->d()->~Data();
This = 0;
if (!object)
return;
@@ -1728,7 +1734,7 @@ QV4::ReturnedValue CallArgument::toValue(QV8Engine *engine)
} else if (type == -1 || type == qMetaTypeId<QVariant>()) {
QVariant value = *qvariantPtr;
QV4::ScopedValue rv(scope, engine->fromVariant(value));
- QV4::QObjectWrapperRef qobjectWrapper = rv;
+ QV4::Scoped<QV4::QObjectWrapper> qobjectWrapper(scope, rv);
if (!!qobjectWrapper) {
if (QObject *object = qobjectWrapper->object())
QQmlData::get(object, true)->setImplicitDestructible();
@@ -1741,28 +1747,28 @@ QV4::ReturnedValue CallArgument::toValue(QV8Engine *engine)
ReturnedValue QObjectMethod::create(ExecutionContext *scope, QObject *object, int index, const ValueRef qmlGlobal)
{
- return (new (scope->engine->memoryManager) QObjectMethod(scope, object, index, qmlGlobal))->asReturnedValue();
+ return (scope->d()->engine->memoryManager->alloc<QObjectMethod>(scope, object, index, qmlGlobal))->asReturnedValue();
}
-QObjectMethod::QObjectMethod(ExecutionContext *scope, QObject *object, int index, const ValueRef qmlGlobal)
- : FunctionObject(scope)
- , m_object(object)
- , m_index(index)
+QObjectMethod::Data::Data(ExecutionContext *scope, QObject *object, int index, const ValueRef qmlGlobal)
+ : FunctionObject::Data(scope)
+ , object(object)
+ , index(index)
+ , qmlGlobal(qmlGlobal)
{
setVTable(staticVTable());
subtype = WrappedQtMethod;
- m_qmlGlobal = qmlGlobal;
}
QV4::ReturnedValue QObjectMethod::method_toString(QV4::ExecutionContext *ctx)
{
QString result;
- if (m_object) {
- QString objectName = m_object->objectName();
+ if (d()->object) {
+ QString objectName = d()->object->objectName();
- result += QString::fromUtf8(m_object->metaObject()->className());
+ result += QString::fromUtf8(d()->object->metaObject()->className());
result += QLatin1String("(0x");
- result += QString::number((quintptr)m_object.data(),16);
+ result += QString::number((quintptr)d()->object.data(),16);
if (!objectName.isEmpty()) {
result += QLatin1String(", \"");
@@ -1775,14 +1781,14 @@ QV4::ReturnedValue QObjectMethod::method_toString(QV4::ExecutionContext *ctx)
result = QLatin1String("null");
}
- return ctx->engine->newString(result)->asReturnedValue();
+ return ctx->d()->engine->newString(result)->asReturnedValue();
}
QV4::ReturnedValue QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, const ValueRef args, int argc)
{
- if (!m_object)
+ if (!d()->object)
return Encode::undefined();
- if (QQmlData::keepAliveDuringGarbageCollection(m_object))
+ if (QQmlData::keepAliveDuringGarbageCollection(d()->object))
return ctx->throwError(QStringLiteral("Invalid attempt to destroy() an indestructible object"));
int delay = 0;
@@ -1790,9 +1796,9 @@ QV4::ReturnedValue QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, con
delay = args[0].toUInt32();
if (delay > 0)
- QTimer::singleShot(delay, m_object, SLOT(deleteLater()));
+ QTimer::singleShot(delay, d()->object, SLOT(deleteLater()));
else
- m_object->deleteLater();
+ d()->object->deleteLater();
return Encode::undefined();
}
@@ -1806,12 +1812,12 @@ ReturnedValue QObjectMethod::call(Managed *m, CallData *callData)
ReturnedValue QObjectMethod::callInternal(CallData *callData)
{
ExecutionContext *context = engine()->currentContext();
- if (m_index == DestroyMethod)
+ if (d()->index == DestroyMethod)
return method_destroy(context, callData->args, callData->argc);
- else if (m_index == ToStringMethod)
+ else if (d()->index == ToStringMethod)
return method_toString(context);
- QObject *object = m_object.data();
+ QObject *object = d()->object.data();
if (!object)
return Encode::undefined();
@@ -1819,7 +1825,7 @@ ReturnedValue QObjectMethod::callInternal(CallData *callData)
if (!ddata)
return Encode::undefined();
- QV8Engine *v8Engine = context->engine->v8Engine;
+ QV8Engine *v8Engine = context->d()->engine->v8Engine;
QV4::ExecutionEngine *v4 = QV8Engine::getV4(v8Engine);
QV4::Scope scope(v4);
@@ -1827,16 +1833,16 @@ ReturnedValue QObjectMethod::callInternal(CallData *callData)
if (QQmlData *ddata = static_cast<QQmlData *>(QObjectPrivate::get(object)->declarativeData)) {
if (ddata->propertyCache) {
- QQmlPropertyData *d = ddata->propertyCache->method(m_index);
- if (!d)
+ QQmlPropertyData *data = ddata->propertyCache->method(d()->index);
+ if (!data)
return QV4::Encode::undefined();
- method = *d;
+ method = *data;
}
}
if (method.coreIndex == -1) {
const QMetaObject *mo = object->metaObject();
- const QMetaMethod moMethod = mo->method(m_index);
+ const QMetaMethod moMethod = mo->method(d()->index);
method.load(moMethod);
if (method.coreIndex == -1)
@@ -1845,7 +1851,7 @@ ReturnedValue QObjectMethod::callInternal(CallData *callData)
// Look for overloaded methods
QByteArray methodName = moMethod.name();
const int methodOffset = mo->methodOffset();
- for (int ii = m_index - 1; ii >= methodOffset; --ii) {
+ for (int ii = d()->index - 1; ii >= methodOffset; --ii) {
if (methodName == mo->method(ii).name()) {
method.setFlags(method.getFlags() | QQmlPropertyData::IsOverload);
method.overrideIndexIsProperty = 0;
@@ -1858,7 +1864,7 @@ ReturnedValue QObjectMethod::callInternal(CallData *callData)
if (method.isV4Function()) {
QV4::ScopedValue rv(scope, QV4::Primitive::undefinedValue());
- QV4::ScopedValue qmlGlobal(scope, m_qmlGlobal.value());
+ QV4::ScopedValue qmlGlobal(scope, d()->qmlGlobal.value());
QQmlV4Function func(callData, rv, qmlGlobal,
QmlContextWrapper::getContext(qmlGlobal),
v8Engine);
@@ -1879,10 +1885,10 @@ ReturnedValue QObjectMethod::callInternal(CallData *callData)
DEFINE_OBJECT_VTABLE(QObjectMethod);
-QmlSignalHandler::QmlSignalHandler(ExecutionEngine *engine, QObject *object, int signalIndex)
- : Object(engine)
- , m_object(object)
- , m_signalIndex(signalIndex)
+QmlSignalHandler::Data::Data(ExecutionEngine *engine, QObject *object, int signalIndex)
+ : Object::Data(engine)
+ , object(object)
+ , signalIndex(signalIndex)
{
setVTable(staticVTable());
}
diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h
index 0af01c5614..a774917713 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper_p.h
+++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h
@@ -77,13 +77,17 @@ struct QObjectSlotDispatcher;
struct Q_QML_EXPORT QObjectWrapper : public QV4::Object
{
- V4_OBJECT
+ struct Data : QV4::Object::Data {
+ Data(ExecutionEngine *engine, QObject *object);
+ QPointer<QObject> object;
+ };
+ V4_OBJECT(QV4::Object)
enum RevisionMode { IgnoreRevision, CheckRevision };
static void initializeBindings(ExecutionEngine *engine);
- QObject *object() const { return m_object.data(); }
+ QObject *object() const { return d()->object.data(); }
ReturnedValue getQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, bool *hasProperty = 0, bool includeImports = false);
static ReturnedValue getQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlContext, QObject *object, String *name, RevisionMode revisionMode, bool *hasProperty = 0);
@@ -106,16 +110,12 @@ private:
static ReturnedValue create(ExecutionEngine *engine, QObject *object);
- QObjectWrapper(ExecutionEngine *engine, QObject *object);
-
QQmlPropertyData *findProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, QQmlPropertyData *local) const;
- QPointer<QObject> m_object;
-
- static ReturnedValue get(Managed *m, const StringRef name, bool *hasProperty);
- static void put(Managed *m, const StringRef name, const ValueRef value);
- static PropertyAttributes query(const Managed *, StringRef name);
- static void advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, Property *p, PropertyAttributes *attributes);
+ static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
+ static void put(Managed *m, String *name, const ValueRef value);
+ static PropertyAttributes query(const Managed *, String *name);
+ static void advanceIterator(Managed *m, ObjectIterator *it, String *&name, uint *index, Property *p, PropertyAttributes *attributes);
static void markObjects(Managed *that, QV4::ExecutionEngine *e);
static void destroy(Managed *that);
@@ -125,51 +125,52 @@ private:
struct QObjectMethod : public QV4::FunctionObject
{
- V4_OBJECT
+ struct Data : QV4::FunctionObject::Data {
+ Data(QV4::ExecutionContext *scope, QObject *object, int index, const ValueRef qmlGlobal);
+ QPointer<QObject> object;
+ int index;
+ QV4::PersistentValue qmlGlobal;
+ };
+ V4_OBJECT(QV4::FunctionObject)
enum { DestroyMethod = -1, ToStringMethod = -2 };
static ReturnedValue create(QV4::ExecutionContext *scope, QObject *object, int index, const ValueRef qmlGlobal = Primitive::undefinedValue());
- int methodIndex() const { return m_index; }
- QObject *object() const { return m_object.data(); }
-
-private:
- QObjectMethod(QV4::ExecutionContext *scope, QObject *object, int index, const ValueRef qmlGlobal);
+ int methodIndex() const { return d()->index; }
+ QObject *object() const { return d()->object.data(); }
QV4::ReturnedValue method_toString(QV4::ExecutionContext *ctx);
QV4::ReturnedValue method_destroy(QV4::ExecutionContext *ctx, const ValueRef args, int argc);
- QPointer<QObject> m_object;
- int m_index;
- QV4::PersistentValue m_qmlGlobal;
-
static ReturnedValue call(Managed *, CallData *callData);
ReturnedValue callInternal(CallData *callData);
static void destroy(Managed *that)
{
- static_cast<QObjectMethod *>(that)->~QObjectMethod();
+ static_cast<QObjectMethod *>(that)->d()->~Data();
}
};
struct QmlSignalHandler : public QV4::Object
{
- V4_OBJECT
+ struct Data : QV4::Object::Data {
+ Data(ExecutionEngine *engine, QObject *object, int signalIndex);
+ QPointer<QObject> object;
+ int signalIndex;
+ };
+ V4_OBJECT(QV4::Object)
- QmlSignalHandler(ExecutionEngine *engine, QObject *object, int signalIndex);
- int signalIndex() const { return m_signalIndex; }
- QObject *object() const { return m_object.data(); }
+ int signalIndex() const { return d()->signalIndex; }
+ QObject *object() const { return d()->object.data(); }
private:
- QPointer<QObject> m_object;
- int m_signalIndex;
static void destroy(Managed *that)
{
- static_cast<QmlSignalHandler *>(that)->~QmlSignalHandler();
+ static_cast<QmlSignalHandler *>(that)->d()->~Data();
}
};
@@ -195,8 +196,6 @@ private Q_SLOTS:
void removeDestroyedObject(QObject*);
};
-DEFINE_REF(QObjectWrapper, Object);
-
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4regexp.cpp b/src/qml/jsruntime/qv4regexp.cpp
index e5490cffd1..e2de584e31 100644
--- a/src/qml/jsruntime/qv4regexp.cpp
+++ b/src/qml/jsruntime/qv4regexp.cpp
@@ -42,6 +42,7 @@
#include "qv4regexp_p.h"
#include "qv4engine_p.h"
#include "qv4scopedvalue_p.h"
+#include "qv4mm_p.h"
using namespace QV4;
@@ -49,7 +50,7 @@ RegExpCache::~RegExpCache()
{
for (RegExpCache::Iterator it = begin(), e = end();
it != e; ++it)
- it.value()->m_cache = 0;
+ it.value()->d()->cache = 0;
clear();
}
@@ -63,11 +64,11 @@ uint RegExp::match(const QString &string, int start, uint *matchOffsets)
WTF::String s(string);
#if ENABLE(YARR_JIT)
- if (!m_jitCode.isFallBack() && m_jitCode.has16BitCode())
- return m_jitCode.execute(s.characters16(), start, s.length(), (int*)matchOffsets).start;
+ if (!jitCode().isFallBack() && jitCode().has16BitCode())
+ return jitCode().execute(s.characters16(), start, s.length(), (int*)matchOffsets).start;
#endif
- return JSC::Yarr::interpret(m_byteCode.get(), s.characters16(), string.length(), start, matchOffsets);
+ return JSC::Yarr::interpret(byteCode().get(), s.characters16(), string.length(), start, matchOffsets);
}
RegExp* RegExp::create(ExecutionEngine* engine, const QString& pattern, bool ignoreCase, bool multiline)
@@ -80,53 +81,49 @@ RegExp* RegExp::create(ExecutionEngine* engine, const QString& pattern, bool ign
return result;
}
- RegExp *result = new (engine->memoryManager) RegExp(engine, pattern, ignoreCase, multiline);
+ RegExp *result = engine->memoryManager->alloc<RegExp>(engine, pattern, ignoreCase, multiline);
if (!cache)
cache = engine->regExpCache = new RegExpCache;
- result->m_cache = cache;
+ result->d()->cache = cache;
cache->insert(key, result);
return result;
}
-RegExp::RegExp(ExecutionEngine* engine, const QString &pattern, bool ignoreCase, bool multiline)
- : Managed(engine->regExpValueClass)
- , m_pattern(pattern)
- , m_cache(0)
- , m_subPatternCount(0)
- , m_ignoreCase(ignoreCase)
- , m_multiLine(multiline)
+RegExp::Data::Data(ExecutionEngine* engine, const QString &pattern, bool ignoreCase, bool multiline)
+ : Managed::Data(engine->regExpValueClass)
+ , pattern(pattern)
+ , ignoreCase(ignoreCase)
+ , multiLine(multiline)
{
- if (!engine)
- return;
+ setVTable(staticVTable());
const char* error = 0;
JSC::Yarr::YarrPattern yarrPattern(WTF::String(pattern), ignoreCase, multiline, &error);
if (error)
return;
- m_subPatternCount = yarrPattern.m_numSubpatterns;
- m_byteCode = JSC::Yarr::byteCompile(yarrPattern, engine->bumperPointerAllocator);
+ subPatternCount = yarrPattern.m_numSubpatterns;
+ byteCode = JSC::Yarr::byteCompile(yarrPattern, engine->bumperPointerAllocator);
#if ENABLE(YARR_JIT)
if (!yarrPattern.m_containsBackreferences && engine->iselFactory->jitCompileRegexps()) {
JSC::JSGlobalData dummy(engine->regExpAllocator);
- JSC::Yarr::jitCompile(yarrPattern, JSC::Yarr::Char16, &dummy, m_jitCode);
+ JSC::Yarr::jitCompile(yarrPattern, JSC::Yarr::Char16, &dummy, jitCode);
}
#endif
}
-RegExp::~RegExp()
+RegExp::Data::~Data()
{
- if (m_cache) {
+ if (cache) {
RegExpCacheKey key(this);
- m_cache->remove(key);
+ cache->remove(key);
}
- _data = 0;
}
void RegExp::destroy(Managed *that)
{
- static_cast<RegExp*>(that)->~RegExp();
+ static_cast<RegExp*>(that)->d()->~Data();
}
void RegExp::markObjects(Managed *that, ExecutionEngine *e)
diff --git a/src/qml/jsruntime/qv4regexp_p.h b/src/qml/jsruntime/qv4regexp_p.h
index 1bcc2c6f5a..e1d3a9ef90 100644
--- a/src/qml/jsruntime/qv4regexp_p.h
+++ b/src/qml/jsruntime/qv4regexp_p.h
@@ -62,6 +62,50 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
struct ExecutionEngine;
+struct RegExpCacheKey;
+
+struct RegExp : public Managed
+{
+ struct Data : Managed::Data {
+ Data(ExecutionEngine* engine, const QString& pattern, bool ignoreCase, bool multiline);
+ ~Data();
+ QString pattern;
+ OwnPtr<JSC::Yarr::BytecodePattern> byteCode;
+#if ENABLE(YARR_JIT)
+ JSC::Yarr::YarrCodeBlock jitCode;
+#endif
+ RegExpCache *cache;
+ int subPatternCount;
+ bool ignoreCase;
+ bool multiLine;
+ };
+ V4_MANAGED(Managed)
+ Q_MANAGED_TYPE(RegExp)
+
+
+ QString pattern() const { return d()->pattern; }
+ OwnPtr<JSC::Yarr::BytecodePattern> &byteCode() { return d()->byteCode; }
+#if ENABLE(YARR_JIT)
+ JSC::Yarr::YarrCodeBlock jitCode() const { return d()->jitCode; }
+#endif
+ RegExpCache *cache() const { return d()->cache; }
+ int subPatternCount() const { return d()->subPatternCount; }
+ bool ignoreCase() const { return d()->ignoreCase; }
+ bool multiLine() const { return d()->multiLine; }
+
+ static RegExp* create(ExecutionEngine* engine, const QString& pattern, bool ignoreCase = false, bool multiline = false);
+
+ bool isValid() const { return d()->byteCode.get(); }
+
+ uint match(const QString& string, int start, uint *matchOffsets);
+
+ int captureCount() const { return subPatternCount() + 1; }
+
+ static void destroy(Managed *that);
+ static void markObjects(Managed *that, QV4::ExecutionEngine *e);
+
+ friend class RegExpCache;
+};
struct RegExpCacheKey
{
@@ -70,7 +114,7 @@ struct RegExpCacheKey
, ignoreCase(ignoreCase)
, multiLine(multiLine)
{ }
- explicit inline RegExpCacheKey(const RegExp *re);
+ explicit inline RegExpCacheKey(const RegExp::Data *re);
bool operator==(const RegExpCacheKey &other) const
{ return pattern == other.pattern && ignoreCase == other.ignoreCase && multiLine == other.multiLine; }
@@ -82,6 +126,12 @@ struct RegExpCacheKey
uint multiLine : 1;
};
+inline RegExpCacheKey::RegExpCacheKey(const RegExp::Data *re)
+ : pattern(re->pattern)
+ , ignoreCase(re->ignoreCase)
+ , multiLine(re->multiLine)
+{}
+
inline uint qHash(const RegExpCacheKey& key, uint seed = 0) Q_DECL_NOTHROW
{ return qHash(key.pattern, seed); }
@@ -91,49 +141,6 @@ public:
~RegExpCache();
};
-class RegExp : public Managed
-{
- V4_MANAGED
- Q_MANAGED_TYPE(RegExp)
-public:
- static RegExp* create(ExecutionEngine* engine, const QString& pattern, bool ignoreCase = false, bool multiline = false);
- ~RegExp();
-
- QString pattern() const { return m_pattern; }
-
- bool isValid() const { return m_byteCode.get(); }
-
- uint match(const QString& string, int start, uint *matchOffsets);
-
- bool ignoreCase() const { return m_ignoreCase; }
- bool multiLine() const { return m_multiLine; }
- int captureCount() const { return m_subPatternCount + 1; }
-
-protected:
- static void destroy(Managed *that);
- static void markObjects(Managed *that, QV4::ExecutionEngine *e);
-
-private:
- friend class RegExpCache;
- Q_DISABLE_COPY(RegExp);
- RegExp(ExecutionEngine* engine, const QString& pattern, bool ignoreCase, bool multiline);
-
- const QString m_pattern;
- OwnPtr<JSC::Yarr::BytecodePattern> m_byteCode;
-#if ENABLE(YARR_JIT)
- JSC::Yarr::YarrCodeBlock m_jitCode;
-#endif
- RegExpCache *m_cache;
- int m_subPatternCount;
- const bool m_ignoreCase;
- const bool m_multiLine;
-};
-
-inline RegExpCacheKey::RegExpCacheKey(const RegExp *re)
- : pattern(re->pattern())
- , ignoreCase(re->ignoreCase())
- , multiLine(re->multiLine())
-{}
}
diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp
index 956d1c594e..6a592ee792 100644
--- a/src/qml/jsruntime/qv4regexpobject.cpp
+++ b/src/qml/jsruntime/qv4regexpobject.cpp
@@ -70,32 +70,43 @@ Q_CORE_EXPORT QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyn
using namespace QV4;
DEFINE_OBJECT_VTABLE(RegExpObject);
+DEFINE_OBJECT_VTABLE(RegExpPrototype);
-RegExpObject::RegExpObject(InternalClass *ic)
- : Object(ic)
- , value(RegExp::create(ic->engine, QString(), false, false))
- , global(false)
+RegExpObject::Data::Data(InternalClass *ic)
+ : Object::Data(ic)
{
- Q_ASSERT(internalClass->vtable == staticVTable());
- init(ic->engine);
+ setVTable(staticVTable());
+
+ Scope scope(ic->engine);
+ Scoped<RegExpObject> o(scope, this);
+ o->d()->value = reinterpret_cast<RegExp *>(RegExp::create(ic->engine, QString(), false, false));
+ o->d()->global = false;
+ o->init(ic->engine);
}
-RegExpObject::RegExpObject(ExecutionEngine *engine, RegExpRef value, bool global)
- : Object(engine->regExpClass)
+RegExpObject::Data::Data(ExecutionEngine *engine, RegExp *value, bool global)
+ : Object::Data(engine->regExpClass)
, value(value)
, global(global)
{
- init(engine);
+ setVTable(staticVTable());
+
+ Scope scope(engine);
+ Scoped<RegExpObject> o(scope, this);
+ o->init(engine);
}
// Converts a QRegExp to a JS RegExp.
// The conversion is not 100% exact since ECMA regexp and QRegExp
// have different semantics/flags, but we try to do our best.
-RegExpObject::RegExpObject(ExecutionEngine *engine, const QRegExp &re)
- : Object(engine->regExpClass)
- , value(0)
- , global(false)
+RegExpObject::Data::Data(ExecutionEngine *engine, const QRegExp &re)
+ : Object::Data(engine->regExpClass)
{
+ setVTable(staticVTable());
+
+ value = 0;
+ global = false;
+
// Convert the pattern to a ECMAScript pattern.
QString pattern = QT_PREPEND_NAMESPACE(qt_regexp_toCanonical)(re.pattern(), re.patternSyntax());
if (re.isMinimal()) {
@@ -134,27 +145,25 @@ RegExpObject::RegExpObject(ExecutionEngine *engine, const QRegExp &re)
}
Scope scope(engine);
- ScopedObject protectThis(scope, this);
+ Scoped<RegExpObject> o(scope, this);
- value = RegExp::create(engine, pattern, re.caseSensitivity() == Qt::CaseInsensitive, false);
+ o->d()->value = reinterpret_cast<RegExp *>(RegExp::create(engine, pattern, re.caseSensitivity() == Qt::CaseInsensitive, false));
- init(engine);
+ o->init(engine);
}
void RegExpObject::init(ExecutionEngine *engine)
{
- setVTable(staticVTable());
-
Scope scope(engine);
ScopedObject protectThis(scope, this);
ScopedString lastIndex(scope, engine->newIdentifier(QStringLiteral("lastIndex")));
ScopedValue v(scope, Primitive::fromInt32(0));
- insertMember(lastIndex, v, Attr_NotEnumerable|Attr_NotConfigurable);
- if (!this->value)
+ insertMember(lastIndex.getPointer(), v, Attr_NotEnumerable|Attr_NotConfigurable);
+ if (!this->value())
return;
- QString p = this->value->pattern();
+ QString p = this->value()->pattern();
if (p.isEmpty()) {
p = QStringLiteral("(?:)");
} else {
@@ -163,29 +172,24 @@ void RegExpObject::init(ExecutionEngine *engine)
}
defineReadonlyProperty(QStringLiteral("source"), (v = engine->newString(p)));
- defineReadonlyProperty(QStringLiteral("global"), Primitive::fromBoolean(global));
- defineReadonlyProperty(QStringLiteral("ignoreCase"), Primitive::fromBoolean(this->value->ignoreCase()));
- defineReadonlyProperty(QStringLiteral("multiline"), Primitive::fromBoolean(this->value->multiLine()));
+ defineReadonlyProperty(QStringLiteral("global"), Primitive::fromBoolean(global()));
+ defineReadonlyProperty(QStringLiteral("ignoreCase"), Primitive::fromBoolean(this->value()->ignoreCase()));
+ defineReadonlyProperty(QStringLiteral("multiline"), Primitive::fromBoolean(this->value()->multiLine()));
}
-void RegExpObject::destroy(Managed *that)
-{
- static_cast<RegExpObject *>(that)->~RegExpObject();
-}
-
void RegExpObject::markObjects(Managed *that, ExecutionEngine *e)
{
RegExpObject *re = static_cast<RegExpObject*>(that);
- if (re->value)
- re->value->mark(e);
+ if (re->value())
+ re->value()->mark(e);
Object::markObjects(that, e);
}
Property *RegExpObject::lastIndexProperty(ExecutionContext *ctx)
{
Q_UNUSED(ctx);
- Q_ASSERT(0 == internalClass->find(ctx->engine->newIdentifier(QStringLiteral("lastIndex"))));
+ Q_ASSERT(0 == internalClass()->find(ctx->d()->engine->newIdentifier(QStringLiteral("lastIndex"))));
return propertyAt(0);
}
@@ -194,19 +198,19 @@ Property *RegExpObject::lastIndexProperty(ExecutionContext *ctx)
// have different semantics/flags, but we try to do our best.
QRegExp RegExpObject::toQRegExp() const
{
- Qt::CaseSensitivity caseSensitivity = value->ignoreCase() ? Qt::CaseInsensitive : Qt::CaseSensitive;
- return QRegExp(value->pattern(), caseSensitivity, QRegExp::RegExp2);
+ Qt::CaseSensitivity caseSensitivity = value()->ignoreCase() ? Qt::CaseInsensitive : Qt::CaseSensitive;
+ return QRegExp(value()->pattern(), caseSensitivity, QRegExp::RegExp2);
}
QString RegExpObject::toString() const
{
QString result = QLatin1Char('/') + source();
result += QLatin1Char('/');
- if (global)
+ if (global())
result += QLatin1Char('g');
- if (value->ignoreCase())
+ if (value()->ignoreCase())
result += QLatin1Char('i');
- if (value->multiLine())
+ if (value()->multiLine())
result += QLatin1Char('m');
return result;
}
@@ -215,35 +219,35 @@ QString RegExpObject::source() const
{
Scope scope(engine());
ScopedString source(scope, scope.engine->newIdentifier(QStringLiteral("source")));
- ScopedValue s(scope, const_cast<RegExpObject *>(this)->get(source));
+ ScopedValue s(scope, const_cast<RegExpObject *>(this)->get(source.getPointer()));
return s->toQString();
}
uint RegExpObject::flags() const
{
uint f = 0;
- if (global)
+ if (global())
f |= QV4::RegExpObject::RegExp_Global;
- if (value->ignoreCase())
+ if (value()->ignoreCase())
f |= QV4::RegExpObject::RegExp_IgnoreCase;
- if (value->multiLine())
+ if (value()->multiLine())
f |= QV4::RegExpObject::RegExp_Multiline;
return f;
}
DEFINE_OBJECT_VTABLE(RegExpCtor);
-RegExpCtor::RegExpCtor(ExecutionContext *scope)
- : FunctionObject(scope, QStringLiteral("RegExp"))
+RegExpCtor::Data::Data(ExecutionContext *scope)
+ : FunctionObject::Data(scope, QStringLiteral("RegExp"))
{
setVTable(staticVTable());
clearLastMatch();
}
-void RegExpCtor::clearLastMatch()
+void RegExpCtor::Data::clearLastMatch()
{
lastMatch = Primitive::nullValue();
- lastInput = engine()->id_empty;
+ lastInput = internalClass->engine->id_empty;
lastMatchStart = 0;
lastMatchEnd = 0;
}
@@ -260,8 +264,7 @@ ReturnedValue RegExpCtor::construct(Managed *m, CallData *callData)
if (!f->isUndefined())
return ctx->throwTypeError();
- Scoped<RegExp> newRe(scope, re->value);
- return Encode(ctx->engine->newRegExpObject(newRe, re->global));
+ return Encode(ctx->d()->engine->newRegExpObject(re->value(), re->global()));
}
QString pattern;
@@ -291,11 +294,11 @@ ReturnedValue RegExpCtor::construct(Managed *m, CallData *callData)
}
}
- Scoped<RegExp> regexp(scope, RegExp::create(ctx->engine, pattern, ignoreCase, multiLine));
+ RegExp *regexp = reinterpret_cast<RegExp *>(RegExp::create(ctx->d()->engine, pattern, ignoreCase, multiLine));
if (!regexp->isValid())
return ctx->throwSyntaxError(QStringLiteral("Invalid regular expression"));
- return Encode(ctx->engine->newRegExpObject(regexp, global));
+ return Encode(ctx->d()->engine->newRegExpObject(regexp, global));
}
ReturnedValue RegExpCtor::call(Managed *that, CallData *callData)
@@ -311,15 +314,16 @@ ReturnedValue RegExpCtor::call(Managed *that, CallData *callData)
void RegExpCtor::markObjects(Managed *that, ExecutionEngine *e)
{
RegExpCtor *This = static_cast<RegExpCtor*>(that);
- This->lastMatch.mark(e);
- This->lastInput.mark(e);
+ This->lastMatch().mark(e);
+ This->lastInput().mark(e);
FunctionObject::markObjects(that, e);
}
-void RegExpPrototype::init(ExecutionEngine *engine, ObjectRef ctor)
+void RegExpPrototype::init(ExecutionEngine *engine, Object *constructor)
{
Scope scope(engine);
ScopedObject o(scope);
+ ScopedObject ctor(scope, constructor);
ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(2));
@@ -355,7 +359,7 @@ void RegExpPrototype::init(ExecutionEngine *engine, ObjectRef ctor)
ReturnedValue RegExpPrototype::method_exec(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<RegExpObject> r(scope, ctx->callData->thisObject.as<RegExpObject>());
+ Scoped<RegExpObject> r(scope, ctx->d()->callData->thisObject.as<RegExpObject>());
if (!r)
return ctx->throwTypeError();
@@ -365,17 +369,17 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx)
return Encode::undefined();
QString s = arg->stringValue()->toQString();
- int offset = r->global ? r->lastIndexProperty(ctx)->value.toInt32() : 0;
+ int offset = r->global() ? r->lastIndexProperty(ctx)->value.toInt32() : 0;
if (offset < 0 || offset > s.length()) {
r->lastIndexProperty(ctx)->value = Primitive::fromInt32(0);
return Encode::null();
}
- uint* matchOffsets = (uint*)alloca(r->value->captureCount() * 2 * sizeof(uint));
- const int result = r->value->match(s, offset, matchOffsets);
+ uint* matchOffsets = (uint*)alloca(r->value()->captureCount() * 2 * sizeof(uint));
+ const int result = r->value()->match(s, offset, matchOffsets);
- Scoped<RegExpCtor> regExpCtor(scope, ctx->engine->regExpCtor);
- regExpCtor->clearLastMatch();
+ Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor);
+ regExpCtor->d()->clearLastMatch();
if (result == -1) {
r->lastIndexProperty(ctx)->value = Primitive::fromInt32(0);
@@ -383,26 +387,27 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx)
}
// fill in result data
- Scoped<ArrayObject> array(scope, ctx->engine->newArrayObject(ctx->engine->regExpExecArrayClass));
- int len = r->value->captureCount();
+ Scoped<ArrayObject> array(scope, ctx->d()->engine->newArrayObject(ctx->d()->engine->regExpExecArrayClass));
+ int len = r->value()->captureCount();
array->arrayReserve(len);
ScopedValue v(scope);
for (int i = 0; i < len; ++i) {
int start = matchOffsets[i * 2];
int end = matchOffsets[i * 2 + 1];
- v = (start != -1 && end != -1) ? ctx->engine->newString(s.mid(start, end - start))->asReturnedValue() : Encode::undefined();
+ v = (start != -1 && end != -1) ? ctx->d()->engine->newString(s.mid(start, end - start))->asReturnedValue() : Encode::undefined();
array->arrayPut(i, v);
}
array->setArrayLengthUnchecked(len);
- array->memberData[Index_ArrayIndex] = Primitive::fromInt32(result);
- array->memberData[Index_ArrayInput] = arg.asReturnedValue();
+ array->memberData()[Index_ArrayIndex] = Primitive::fromInt32(result);
+ array->memberData()[Index_ArrayInput] = arg.asReturnedValue();
- regExpCtor->lastMatch = array;
- regExpCtor->lastInput = arg->stringValue();
- regExpCtor->lastMatchStart = matchOffsets[0];
- regExpCtor->lastMatchEnd = matchOffsets[1];
+ RegExpCtor::Data *dd = regExpCtor->d();
+ dd->lastMatch = array;
+ dd->lastInput = arg->stringValue();
+ dd->lastMatchStart = matchOffsets[0];
+ dd->lastMatchEnd = matchOffsets[1];
- if (r->global)
+ if (r->global())
r->lastIndexProperty(ctx)->value = Primitive::fromInt32(matchOffsets[1]);
return array.asReturnedValue();
@@ -418,27 +423,27 @@ ReturnedValue RegExpPrototype::method_test(CallContext *ctx)
ReturnedValue RegExpPrototype::method_toString(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<RegExpObject> r(scope, ctx->callData->thisObject.as<RegExpObject>());
+ Scoped<RegExpObject> r(scope, ctx->d()->callData->thisObject.as<RegExpObject>());
if (!r)
return ctx->throwTypeError();
- return ctx->engine->newString(r->toString())->asReturnedValue();
+ return ctx->d()->engine->newString(r->toString())->asReturnedValue();
}
ReturnedValue RegExpPrototype::method_compile(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<RegExpObject> r(scope, ctx->callData->thisObject.as<RegExpObject>());
+ Scoped<RegExpObject> r(scope, ctx->d()->callData->thisObject.as<RegExpObject>());
if (!r)
return ctx->throwTypeError();
- ScopedCallData callData(scope, ctx->callData->argc);
- memcpy(callData->args, ctx->callData->args, ctx->callData->argc*sizeof(Value));
+ ScopedCallData callData(scope, ctx->d()->callData->argc);
+ memcpy(callData->args, ctx->d()->callData->args, ctx->d()->callData->argc*sizeof(Value));
- Scoped<RegExpObject> re(scope, ctx->engine->regExpCtor.asFunctionObject()->construct(callData));
+ Scoped<RegExpObject> re(scope, ctx->d()->engine->regExpCtor.asFunctionObject()->construct(callData));
- r->value = re->value;
- r->global = re->global;
+ r->d()->value = re->value();
+ r->d()->global = re->global();
return Encode::undefined();
}
@@ -446,42 +451,42 @@ template <int index>
ReturnedValue RegExpPrototype::method_get_lastMatch_n(CallContext *ctx)
{
Scope scope(ctx);
- ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->engine->regExpCtor.objectValue())->lastMatch);
+ ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor.objectValue())->lastMatch());
ScopedValue result(scope, lastMatch ? lastMatch->getIndexed(index) : Encode::undefined());
if (result->isUndefined())
- return ctx->engine->newString(QString())->asReturnedValue();
+ return ctx->d()->engine->newString(QString())->asReturnedValue();
return result.asReturnedValue();
}
ReturnedValue RegExpPrototype::method_get_lastParen(CallContext *ctx)
{
Scope scope(ctx);
- ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->engine->regExpCtor.objectValue())->lastMatch);
+ ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor.objectValue())->lastMatch());
ScopedValue result(scope, lastMatch ? lastMatch->getIndexed(lastMatch->getLength() - 1) : Encode::undefined());
if (result->isUndefined())
- return ctx->engine->newString(QString())->asReturnedValue();
+ return ctx->d()->engine->newString(QString())->asReturnedValue();
return result.asReturnedValue();
}
ReturnedValue RegExpPrototype::method_get_input(CallContext *ctx)
{
- return static_cast<RegExpCtor*>(ctx->engine->regExpCtor.objectValue())->lastInput.asReturnedValue();
+ return static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor.objectValue())->lastInput().asReturnedValue();
}
ReturnedValue RegExpPrototype::method_get_leftContext(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<RegExpCtor> regExpCtor(scope, ctx->engine->regExpCtor);
- QString lastInput = regExpCtor->lastInput->toQString();
- return ctx->engine->newString(lastInput.left(regExpCtor->lastMatchStart))->asReturnedValue();
+ Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor);
+ QString lastInput = regExpCtor->lastInput()->toQString();
+ return ctx->d()->engine->newString(lastInput.left(regExpCtor->lastMatchStart()))->asReturnedValue();
}
ReturnedValue RegExpPrototype::method_get_rightContext(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<RegExpCtor> regExpCtor(scope, ctx->engine->regExpCtor);
- QString lastInput = regExpCtor->lastInput->toQString();
- return ctx->engine->newString(lastInput.mid(regExpCtor->lastMatchEnd))->asReturnedValue();
+ Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor);
+ QString lastInput = regExpCtor->lastInput()->toQString();
+ return ctx->d()->engine->newString(lastInput.mid(regExpCtor->lastMatchEnd()))->asReturnedValue();
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h
index 1b408749d3..ac07707b2f 100644
--- a/src/qml/jsruntime/qv4regexpobject_p.h
+++ b/src/qml/jsruntime/qv4regexpobject_p.h
@@ -63,11 +63,18 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
-class RegExp;
-
struct RegExpObject: Object {
- V4_OBJECT
+ struct Data : Object::Data {
+ Data(ExecutionEngine *engine, RegExp *value, bool global);
+ Data(ExecutionEngine *engine, const QRegExp &re);
+ Data(InternalClass *ic);
+
+ RegExp *value;
+ bool global;
+ };
+ V4_OBJECT(Object)
Q_MANAGED_TYPE(RegExpObject)
+
// needs to be compatible with the flags in qv4jsir_p.h
enum Flags {
RegExp_Global = 0x01,
@@ -80,39 +87,37 @@ struct RegExpObject: Object {
Index_ArrayInput = Index_ArrayIndex + 1
};
- RegExp* value;
- Property *lastIndexProperty(ExecutionContext *ctx);
- bool global;
-
- RegExpObject(ExecutionEngine *engine, RegExpRef value, bool global);
- RegExpObject(ExecutionEngine *engine, const QRegExp &re);
- ~RegExpObject() {}
+ RegExp *value() const { return d()->value; }
+ bool global() const { return d()->global; }
void init(ExecutionEngine *engine);
+ Property *lastIndexProperty(ExecutionContext *ctx);
QRegExp toQRegExp() const;
QString toString() const;
QString source() const;
uint flags() const;
protected:
- RegExpObject(InternalClass *ic);
- static void destroy(Managed *that);
static void markObjects(Managed *that, ExecutionEngine *e);
};
-DEFINE_REF(RegExp, Object);
-
struct RegExpCtor: FunctionObject
{
- V4_OBJECT
- RegExpCtor(ExecutionContext *scope);
+ struct Data : FunctionObject::Data {
+ Data(ExecutionContext *scope);
+ Value lastMatch;
+ StringValue lastInput;
+ int lastMatchStart;
+ int lastMatchEnd;
+ void clearLastMatch();
+ };
+ V4_OBJECT(FunctionObject)
- Value lastMatch;
- StringValue lastInput;
- int lastMatchStart;
- int lastMatchEnd;
- void clearLastMatch();
+ Value lastMatch() { return d()->lastMatch; }
+ StringValue lastInput() { return d()->lastInput; }
+ int lastMatchStart() { return d()->lastMatchStart; }
+ int lastMatchEnd() { return d()->lastMatchEnd; }
static ReturnedValue construct(Managed *m, CallData *callData);
static ReturnedValue call(Managed *that, CallData *callData);
@@ -121,8 +126,16 @@ struct RegExpCtor: FunctionObject
struct RegExpPrototype: RegExpObject
{
- RegExpPrototype(InternalClass *ic): RegExpObject(ic) {}
- void init(ExecutionEngine *engine, ObjectRef ctor);
+ struct Data : RegExpObject::Data
+ {
+ Data(InternalClass *ic): RegExpObject::Data(ic)
+ {
+ setVTable(staticVTable());
+ }
+ };
+ V4_OBJECT(RegExpObject)
+
+ void init(ExecutionEngine *engine, Object *ctor);
static ReturnedValue method_exec(CallContext *ctx);
static ReturnedValue method_test(CallContext *ctx);
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index e44d1a07a6..7ea8dbd0aa 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -265,10 +265,9 @@ void RuntimeHelpers::numberToString(QString *result, double num, int radix)
ReturnedValue Runtime::closure(ExecutionContext *ctx, int functionId)
{
- QV4::Function *clos = ctx->compilationUnit->runtimeFunctions[functionId];
+ QV4::Function *clos = ctx->d()->compilationUnit->runtimeFunctions[functionId];
Q_ASSERT(clos);
- FunctionObject *f = FunctionObject::createScriptFunction(ctx, clos);
- return f->asReturnedValue();
+ return FunctionObject::createScriptFunction(ctx, clos)->asReturnedValue();
}
ReturnedValue Runtime::deleteElement(ExecutionContext *ctx, const ValueRef base, const ValueRef index)
@@ -283,10 +282,10 @@ ReturnedValue Runtime::deleteElement(ExecutionContext *ctx, const ValueRef base,
}
ScopedString name(scope, index->toString(ctx));
- return Runtime::deleteMember(ctx, base, name);
+ return Runtime::deleteMember(ctx, base, name.getPointer());
}
-ReturnedValue Runtime::deleteMember(ExecutionContext *ctx, const ValueRef base, const StringRef name)
+ReturnedValue Runtime::deleteMember(ExecutionContext *ctx, const ValueRef base, String *name)
{
Scope scope(ctx);
ScopedObject obj(scope, base->toObject(ctx));
@@ -295,7 +294,7 @@ ReturnedValue Runtime::deleteMember(ExecutionContext *ctx, const ValueRef base,
return Encode(obj->deleteProperty(name));
}
-ReturnedValue Runtime::deleteName(ExecutionContext *ctx, const StringRef name)
+ReturnedValue Runtime::deleteName(ExecutionContext *ctx, String *name)
{
Scope scope(ctx);
return Encode(ctx->deleteProperty(name));
@@ -310,8 +309,8 @@ QV4::ReturnedValue Runtime::instanceof(ExecutionContext *ctx, const ValueRef lef
if (!f)
return ctx->throwTypeError();
- if (f->subtype == FunctionObject::BoundFunction)
- f = static_cast<BoundFunction *>(f)->target;
+ if (f->subtype() == FunctionObject::BoundFunction)
+ f = static_cast<BoundFunction *>(f)->target();
Object *v = left->asObject();
if (!v)
@@ -341,7 +340,7 @@ QV4::ReturnedValue Runtime::in(ExecutionContext *ctx, const ValueRef left, const
ScopedString s(scope, left->toString(ctx));
if (scope.hasException())
return Encode::undefined();
- bool r = right->objectValue()->hasProperty(s);
+ bool r = right->objectValue()->hasProperty(s.getPointer());
return Encode(r);
}
@@ -370,7 +369,7 @@ Returned<String> *RuntimeHelpers::stringFromNumber(ExecutionContext *ctx, double
{
QString qstr;
RuntimeHelpers::numberToString(&qstr, number, 10);
- return ctx->engine->newString(qstr);
+ return ctx->engine()->newString(qstr);
}
ReturnedValue RuntimeHelpers::objectDefaultValue(Object *object, int typeHint)
@@ -382,7 +381,7 @@ ReturnedValue RuntimeHelpers::objectDefaultValue(Object *object, int typeHint)
typeHint = NUMBER_HINT;
}
- ExecutionEngine *engine = object->internalClass->engine;
+ ExecutionEngine *engine = object->internalClass()->engine;
if (engine->hasException)
return Encode::undefined();
@@ -428,13 +427,13 @@ Returned<Object> *RuntimeHelpers::convertToObject(ExecutionContext *ctx, const V
ctx->throwTypeError();
return 0;
case Value::Boolean_Type:
- return ctx->engine->newBooleanObject(value);
+ return ctx->engine()->newBooleanObject(value);
case Value::Managed_Type:
Q_ASSERT(value->isString());
- return ctx->engine->newStringObject(value);
+ return ctx->engine()->newStringObject(value);
case Value::Integer_Type:
default: // double
- return ctx->engine->newNumberObject(value);
+ return ctx->engine()->newNumberObject(value);
}
}
@@ -444,14 +443,14 @@ Returned<String> *RuntimeHelpers::convertToString(ExecutionContext *ctx, const V
case Value::Empty_Type:
Q_ASSERT(!"empty Value encountered");
case Value::Undefined_Type:
- return ctx->engine->id_undefined.ret();
+ return ctx->engine()->id_undefined.ret();
case Value::Null_Type:
- return ctx->engine->id_null.ret();
+ return ctx->engine()->id_null.ret();
case Value::Boolean_Type:
if (value->booleanValue())
- return ctx->engine->id_true.ret();
+ return ctx->engine()->id_true.ret();
else
- return ctx->engine->id_false.ret();
+ return ctx->engine()->id_false.ret();
case Value::Managed_Type:
if (value->isString())
return value->stringValue()->asReturned<String>();
@@ -475,14 +474,14 @@ static Returned<String> *convert_to_string_add(ExecutionContext *ctx, const Valu
case Value::Empty_Type:
Q_ASSERT(!"empty Value encountered");
case Value::Undefined_Type:
- return ctx->engine->id_undefined.ret();
+ return ctx->engine()->id_undefined.ret();
case Value::Null_Type:
- return ctx->engine->id_null.ret();
+ return ctx->engine()->id_null.ret();
case Value::Boolean_Type:
if (value->booleanValue())
- return ctx->engine->id_true.ret();
+ return ctx->engine()->id_true.ret();
else
- return ctx->engine->id_false.ret();
+ return ctx->engine()->id_false.ret();
case Value::Managed_Type:
if (value->isString())
return value->stringValue()->asReturned<String>();
@@ -511,11 +510,11 @@ QV4::ReturnedValue RuntimeHelpers::addHelper(ExecutionContext *ctx, const ValueR
pright = convert_to_string_add(ctx, pright);
if (scope.engine->hasException)
return Encode::undefined();
- if (!pleft->stringValue()->length())
+ if (!pleft->stringValue()->d()->length())
return pright->asReturnedValue();
- if (!pright->stringValue()->length())
+ if (!pright->stringValue()->d()->length())
return pleft->asReturnedValue();
- return (new (ctx->engine->memoryManager) String(ctx->engine, pleft->stringValue(), pright->stringValue()))->asReturnedValue();
+ return (ctx->engine()->memoryManager->alloc<String>(ctx->d()->engine, pleft->stringValue(), pright->stringValue()))->asReturnedValue();
}
double x = RuntimeHelpers::toNumber(pleft);
double y = RuntimeHelpers::toNumber(pright);
@@ -527,11 +526,11 @@ QV4::ReturnedValue Runtime::addString(QV4::ExecutionContext *ctx, const QV4::Val
Q_ASSERT(left->isString() || right->isString());
if (left->isString() && right->isString()) {
- if (!left->stringValue()->length())
+ if (!left->stringValue()->d()->length())
return right->asReturnedValue();
- if (!right->stringValue()->length())
+ if (!right->stringValue()->d()->length())
return left->asReturnedValue();
- return (new (ctx->engine->memoryManager) String(ctx->engine, left->stringValue(), right->stringValue()))->asReturnedValue();
+ return (ctx->engine()->memoryManager->alloc<String>(ctx->d()->engine, left->stringValue(), right->stringValue()))->asReturnedValue();
}
Scope scope(ctx);
@@ -544,14 +543,14 @@ QV4::ReturnedValue Runtime::addString(QV4::ExecutionContext *ctx, const QV4::Val
pright = convert_to_string_add(ctx, right);
if (scope.engine->hasException)
return Encode::undefined();
- if (!pleft->stringValue()->length())
+ if (!pleft->stringValue()->d()->length())
return pright->asReturnedValue();
- if (!pright->stringValue()->length())
+ if (!pright->stringValue()->d()->length())
return pleft->asReturnedValue();
- return (new (ctx->engine->memoryManager) String(ctx->engine, pleft->stringValue(), pright->stringValue()))->asReturnedValue();
+ return (ctx->engine()->memoryManager->alloc<String>(ctx->d()->engine, pleft->stringValue(), pright->stringValue()))->asReturnedValue();
}
-void Runtime::setProperty(ExecutionContext *ctx, const ValueRef object, const StringRef name, const ValueRef value)
+void Runtime::setProperty(ExecutionContext *ctx, const ValueRef object, String *name, const ValueRef value)
{
Scope scope(ctx);
ScopedObject o(scope, object->toObject(ctx));
@@ -588,8 +587,8 @@ ReturnedValue Runtime::getElement(ExecutionContext *ctx, const ValueRef object,
}
if (idx < UINT_MAX) {
- if (!o->arrayData->hasAttributes()) {
- ScopedValue v(scope, o->arrayData->get(idx));
+ if (!o->arrayData()->hasAttributes()) {
+ ScopedValue v(scope, o->arrayData()->get(idx));
if (!v->isEmpty())
return v->asReturnedValue();
}
@@ -600,7 +599,7 @@ ReturnedValue Runtime::getElement(ExecutionContext *ctx, const ValueRef object,
ScopedString name(scope, index->toString(ctx));
if (scope.hasException())
return Encode::undefined();
- return o->get(name);
+ return o->get(name.getPointer());
}
void Runtime::setElement(ExecutionContext *ctx, const ValueRef object, const ValueRef index, const ValueRef value)
@@ -613,9 +612,9 @@ void Runtime::setElement(ExecutionContext *ctx, const ValueRef object, const Val
uint idx = index->asArrayIndex();
if (idx < UINT_MAX) {
if (o->arrayType() == ArrayData::Simple) {
- SimpleArrayData *s = static_cast<SimpleArrayData *>(o->arrayData);
- if (s && idx < s->len && !s->data[idx].isEmpty()) {
- s->data[idx] = value;
+ SimpleArrayData *s = static_cast<SimpleArrayData *>(o->arrayData());
+ if (s && idx < s->len() && !s->arrayData()[idx].isEmpty()) {
+ s->arrayData()[idx] = value;
return;
}
}
@@ -624,7 +623,7 @@ void Runtime::setElement(ExecutionContext *ctx, const ValueRef object, const Val
}
ScopedString name(scope, index->toString(ctx));
- o->put(name, value);
+ o->put(name.getPointer(), value);
}
ReturnedValue Runtime::foreachIterator(ExecutionContext *ctx, const ValueRef in)
@@ -633,7 +632,7 @@ ReturnedValue Runtime::foreachIterator(ExecutionContext *ctx, const ValueRef in)
Scoped<Object> o(scope, (Object *)0);
if (!in->isNullOrUndefined())
o = in->toObject(ctx);
- Scoped<Object> it(scope, ctx->engine->newForEachIteratorObject(ctx, o));
+ Scoped<Object> it(scope, ctx->engine()->newForEachIteratorObject(ctx, o));
return it.asReturnedValue();
}
@@ -648,12 +647,12 @@ ReturnedValue Runtime::foreachNextPropertyName(const ValueRef foreach_iterator)
}
-void Runtime::setActivationProperty(ExecutionContext *ctx, const StringRef name, const ValueRef value)
+void Runtime::setActivationProperty(ExecutionContext *ctx, String *name, const ValueRef value)
{
ctx->setProperty(name, value);
}
-ReturnedValue Runtime::getProperty(ExecutionContext *ctx, const ValueRef object, const StringRef name)
+ReturnedValue Runtime::getProperty(ExecutionContext *ctx, const ValueRef object, String *name)
{
Scope scope(ctx);
@@ -672,7 +671,7 @@ ReturnedValue Runtime::getProperty(ExecutionContext *ctx, const ValueRef object,
return o->get(name);
}
-ReturnedValue Runtime::getActivationProperty(ExecutionContext *ctx, const StringRef name)
+ReturnedValue Runtime::getActivationProperty(ExecutionContext *ctx, String *name)
{
return ctx->getProperty(name);
}
@@ -866,31 +865,31 @@ QV4::Bool Runtime::compareLessEqual(const QV4::ValueRef l, const QV4::ValueRef r
}
#ifndef V4_BOOTSTRAP
-ReturnedValue Runtime::callGlobalLookup(ExecutionContext *context, uint index, CallDataRef callData)
+ReturnedValue Runtime::callGlobalLookup(ExecutionContext *context, uint index, CallData *callData)
{
Scope scope(context);
Q_ASSERT(callData->thisObject.isUndefined());
- Lookup *l = context->lookups + index;
+ Lookup *l = context->d()->lookups + index;
Scoped<FunctionObject> o(scope, l->globalGetter(l, context));
if (!o)
return context->throwTypeError();
- if (o.getPointer() == context->engine->evalFunction && l->name->equals(context->engine->id_eval))
+ if (o.getPointer() == scope.engine->evalFunction && l->name->equals(scope.engine->id_eval))
return static_cast<EvalFunction *>(o.getPointer())->evalCall(callData, true);
return o->call(callData);
}
-ReturnedValue Runtime::callActivationProperty(ExecutionContext *context, const StringRef name, CallDataRef callData)
+ReturnedValue Runtime::callActivationProperty(ExecutionContext *context, String *name, CallData *callData)
{
Q_ASSERT(callData->thisObject.isUndefined());
Scope scope(context);
ScopedObject base(scope);
- ScopedValue func(scope, context->getPropertyAndBase(name, base));
- if (context->engine->hasException)
+ ScopedValue func(scope, context->getPropertyAndBase(name, base.ptr->o));
+ if (scope.engine->hasException)
return Encode::undefined();
if (base)
@@ -905,14 +904,14 @@ ReturnedValue Runtime::callActivationProperty(ExecutionContext *context, const S
return context->throwTypeError(msg);
}
- if (o == context->engine->evalFunction && name->equals(context->engine->id_eval)) {
+ if (o == scope.engine->evalFunction && name->equals(scope.engine->id_eval)) {
return static_cast<EvalFunction *>(o)->evalCall(callData, true);
}
return o->call(callData);
}
-ReturnedValue Runtime::callProperty(ExecutionContext *context, const StringRef name, CallDataRef callData)
+ReturnedValue Runtime::callProperty(ExecutionContext *context, String *name, CallData *callData)
{
Scope scope(context);
Scoped<Object> baseObject(scope, callData->thisObject);
@@ -938,9 +937,9 @@ ReturnedValue Runtime::callProperty(ExecutionContext *context, const StringRef n
return o->call(callData);
}
-ReturnedValue Runtime::callPropertyLookup(ExecutionContext *context, uint index, CallDataRef callData)
+ReturnedValue Runtime::callPropertyLookup(ExecutionContext *context, uint index, CallData *callData)
{
- Lookup *l = context->lookups + index;
+ Lookup *l = context->d()->lookups + index;
Value v;
v = l->getter(l, callData->thisObject);
if (!v.isObject())
@@ -949,7 +948,7 @@ ReturnedValue Runtime::callPropertyLookup(ExecutionContext *context, uint index,
return v.objectValue()->call(callData);
}
-ReturnedValue Runtime::callElement(ExecutionContext *context, const ValueRef index, CallDataRef callData)
+ReturnedValue Runtime::callElement(ExecutionContext *context, const ValueRef index, CallData *callData)
{
Scope scope(context);
ScopedObject baseObject(scope, callData->thisObject.toObject(context));
@@ -959,14 +958,14 @@ ReturnedValue Runtime::callElement(ExecutionContext *context, const ValueRef ind
return Encode::undefined();
callData->thisObject = baseObject;
- ScopedObject o(scope, baseObject->get(s));
+ ScopedObject o(scope, baseObject->get(s.getPointer()));
if (!o)
return context->throwTypeError();
return o->call(callData);
}
-ReturnedValue Runtime::callValue(ExecutionContext *context, const ValueRef func, CallDataRef callData)
+ReturnedValue Runtime::callValue(ExecutionContext *context, const ValueRef func, CallData *callData)
{
if (!func->isObject())
return context->throwTypeError();
@@ -975,12 +974,12 @@ ReturnedValue Runtime::callValue(ExecutionContext *context, const ValueRef func,
}
-ReturnedValue Runtime::constructGlobalLookup(ExecutionContext *context, uint index, CallDataRef callData)
+ReturnedValue Runtime::constructGlobalLookup(ExecutionContext *context, uint index, CallData *callData)
{
Scope scope(context);
Q_ASSERT(callData->thisObject.isUndefined());
- Lookup *l = context->lookups + index;
+ Lookup *l = context->d()->lookups + index;
Scoped<Object> f(scope, l->globalGetter(l, context));
if (!f)
return context->throwTypeError();
@@ -989,11 +988,11 @@ ReturnedValue Runtime::constructGlobalLookup(ExecutionContext *context, uint ind
}
-ReturnedValue Runtime::constructActivationProperty(ExecutionContext *context, const StringRef name, CallDataRef callData)
+ReturnedValue Runtime::constructActivationProperty(ExecutionContext *context, String *name, CallData *callData)
{
Scope scope(context);
ScopedValue func(scope, context->getProperty(name));
- if (context->engine->hasException)
+ if (scope.engine->hasException)
return Encode::undefined();
Object *f = func->asObject();
@@ -1003,7 +1002,7 @@ ReturnedValue Runtime::constructActivationProperty(ExecutionContext *context, co
return f->construct(callData);
}
-ReturnedValue Runtime::constructValue(ExecutionContext *context, const ValueRef func, CallDataRef callData)
+ReturnedValue Runtime::constructValue(ExecutionContext *context, const ValueRef func, CallData *callData)
{
Object *f = func->asObject();
if (!f)
@@ -1012,7 +1011,7 @@ ReturnedValue Runtime::constructValue(ExecutionContext *context, const ValueRef
return f->construct(callData);
}
-ReturnedValue Runtime::constructProperty(ExecutionContext *context, const StringRef name, CallDataRef callData)
+ReturnedValue Runtime::constructProperty(ExecutionContext *context, String *name, CallData *callData)
{
Scope scope(context);
ScopedObject thisObject(scope, callData->thisObject.toObject(context));
@@ -1026,9 +1025,9 @@ ReturnedValue Runtime::constructProperty(ExecutionContext *context, const String
return f->construct(callData);
}
-ReturnedValue Runtime::constructPropertyLookup(ExecutionContext *context, uint index, CallDataRef callData)
+ReturnedValue Runtime::constructPropertyLookup(ExecutionContext *context, uint index, CallData *callData)
{
- Lookup *l = context->lookups + index;
+ Lookup *l = context->d()->lookups + index;
Value v;
v = l->getter(l, callData->thisObject);
if (!v.isObject())
@@ -1050,39 +1049,39 @@ ReturnedValue Runtime::typeofValue(ExecutionContext *ctx, const ValueRef value)
ScopedString res(scope);
switch (value->type()) {
case Value::Undefined_Type:
- res = ctx->engine->id_undefined;
+ res = ctx->engine()->id_undefined;
break;
case Value::Null_Type:
- res = ctx->engine->id_object;
+ res = ctx->engine()->id_object;
break;
case Value::Boolean_Type:
- res = ctx->engine->id_boolean;
+ res = ctx->engine()->id_boolean;
break;
case Value::Managed_Type:
if (value->isString())
- res = ctx->engine->id_string;
+ res = ctx->engine()->id_string;
else if (value->objectValue()->asFunctionObject())
- res = ctx->engine->id_function;
+ res = ctx->engine()->id_function;
else
- res = ctx->engine->id_object; // ### implementation-defined
+ res = ctx->engine()->id_object; // ### implementation-defined
break;
default:
- res = ctx->engine->id_number;
+ res = ctx->engine()->id_number;
break;
}
return res.asReturnedValue();
}
-QV4::ReturnedValue Runtime::typeofName(ExecutionContext *context, const StringRef name)
+QV4::ReturnedValue Runtime::typeofName(ExecutionContext *context, String *name)
{
Scope scope(context);
ScopedValue prop(scope, context->getProperty(name));
// typeof doesn't throw. clear any possible exception
- context->engine->hasException = false;
+ scope.engine->hasException = false;
return Runtime::typeofValue(context, prop);
}
-QV4::ReturnedValue Runtime::typeofMember(ExecutionContext *context, const ValueRef base, const StringRef name)
+QV4::ReturnedValue Runtime::typeofMember(ExecutionContext *context, const ValueRef base, String *name)
{
Scope scope(context);
ScopedObject obj(scope, base->toObject(context));
@@ -1099,7 +1098,7 @@ QV4::ReturnedValue Runtime::typeofElement(ExecutionContext *context, const Value
ScopedObject obj(scope, base->toObject(context));
if (scope.engine->hasException)
return Encode::undefined();
- ScopedValue prop(scope, obj->get(name));
+ ScopedValue prop(scope, obj->get(name.getPointer()));
return Runtime::typeofValue(context, prop);
}
@@ -1107,29 +1106,29 @@ ExecutionContext *Runtime::pushWithScope(const ValueRef o, ExecutionContext *ctx
{
Scope scope(ctx);
ScopedObject obj(scope, o->toObject(ctx));
- return ctx->newWithContext(obj);
+ return reinterpret_cast<ExecutionContext *>(ctx->newWithContext(obj));
}
ReturnedValue Runtime::unwindException(ExecutionContext *ctx)
{
- if (!ctx->engine->hasException)
+ if (!ctx->engine()->hasException)
return Primitive::emptyValue().asReturnedValue();
- return ctx->engine->catchException(ctx, 0);
+ return ctx->engine()->catchException(ctx, 0);
}
-ExecutionContext *Runtime::pushCatchScope(ExecutionContext *ctx, const StringRef exceptionVarName)
+ExecutionContext *Runtime::pushCatchScope(ExecutionContext *ctx, String *exceptionVarName)
{
Scope scope(ctx);
- ScopedValue v(scope, ctx->engine->catchException(ctx, 0));
- return ctx->newCatchContext(exceptionVarName, v);
+ ScopedValue v(scope, ctx->engine()->catchException(ctx, 0));
+ return reinterpret_cast<ExecutionContext *>(ctx->newCatchContext(exceptionVarName, v));
}
ExecutionContext *Runtime::popScope(ExecutionContext *ctx)
{
- return ctx->engine->popContext();
+ return ctx->engine()->popContext();
}
-void Runtime::declareVar(ExecutionContext *ctx, bool deletable, const StringRef name)
+void Runtime::declareVar(ExecutionContext *ctx, bool deletable, String *name)
{
ctx->createMutableBinding(name, deletable);
}
@@ -1137,7 +1136,7 @@ void Runtime::declareVar(ExecutionContext *ctx, bool deletable, const StringRef
ReturnedValue Runtime::arrayLiteral(ExecutionContext *ctx, Value *values, uint length)
{
Scope scope(ctx);
- Scoped<ArrayObject> a(scope, ctx->engine->newArrayObject());
+ Scoped<ArrayObject> a(scope, ctx->engine()->newArrayObject());
if (length) {
a->arrayReserve(length);
@@ -1150,8 +1149,8 @@ ReturnedValue Runtime::arrayLiteral(ExecutionContext *ctx, Value *values, uint l
ReturnedValue Runtime::objectLiteral(QV4::ExecutionContext *ctx, const QV4::Value *args, int classId, int arrayValueCount, int arrayGetterSetterCountAndFlags)
{
Scope scope(ctx);
- QV4::InternalClass *klass = ctx->compilationUnit->runtimeClasses[classId];
- Scoped<Object> o(scope, ctx->engine->newObject(klass));
+ QV4::InternalClass *klass = ctx->d()->compilationUnit->runtimeClasses[classId];
+ Scoped<Object> o(scope, ctx->engine()->newObject(klass));
{
bool needSparseArray = arrayGetterSetterCountAndFlags >> 30;
@@ -1160,26 +1159,30 @@ ReturnedValue Runtime::objectLiteral(QV4::ExecutionContext *ctx, const QV4::Valu
}
for (uint i = 0; i < klass->size; ++i)
- o->memberData[i] = *args++;
-
- ScopedValue entry(scope);
- for (int i = 0; i < arrayValueCount; ++i) {
- uint idx = args->toUInt32();
- ++args;
- entry = *args++;
- o->arraySet(idx, entry);
+ o->memberData()[i] = *args++;
+
+ if (arrayValueCount > 0) {
+ ScopedValue entry(scope);
+ for (int i = 0; i < arrayValueCount; ++i) {
+ uint idx = args->toUInt32();
+ ++args;
+ entry = *args++;
+ o->arraySet(idx, entry);
+ }
}
- ScopedProperty pd(scope);
uint arrayGetterSetterCount = arrayGetterSetterCountAndFlags & ((1 << 30) - 1);
- for (uint i = 0; i < arrayGetterSetterCount; ++i) {
- uint idx = args->toUInt32();
- ++args;
- pd->value = *args;
- ++args;
- pd->set = *args;
- ++args;
- o->arraySet(idx, pd, Attr_Accessor);
+ if (arrayGetterSetterCount > 0) {
+ ScopedProperty pd(scope);
+ for (uint i = 0; i < arrayGetterSetterCount; ++i) {
+ uint idx = args->toUInt32();
+ ++args;
+ pd->value = *args;
+ ++args;
+ pd->set = *args;
+ ++args;
+ o->arraySet(idx, pd, Attr_Accessor);
+ }
}
return o.asReturnedValue();
@@ -1187,9 +1190,9 @@ ReturnedValue Runtime::objectLiteral(QV4::ExecutionContext *ctx, const QV4::Valu
QV4::ReturnedValue Runtime::setupArgumentsObject(ExecutionContext *ctx)
{
- assert(ctx->type >= ExecutionContext::Type_CallContext);
+ Q_ASSERT(ctx->d()->type >= ExecutionContext::Type_CallContext);
CallContext *c = static_cast<CallContext *>(ctx);
- return (new (c->engine->memoryManager) ArgumentsObject(c))->asReturnedValue();
+ return (c->engine()->memoryManager->alloc<ArgumentsObject>(c))->asReturnedValue();
}
#endif // V4_BOOTSTRAP
@@ -1275,27 +1278,27 @@ unsigned Runtime::doubleToUInt(const double &d)
ReturnedValue Runtime::regexpLiteral(ExecutionContext *ctx, int id)
{
- return ctx->compilationUnit->runtimeRegularExpressions[id].asReturnedValue();
+ return ctx->d()->compilationUnit->runtimeRegularExpressions[id].asReturnedValue();
}
ReturnedValue Runtime::getQmlIdArray(NoThrowContext *ctx)
{
- return ctx->engine->qmlContextObject()->getPointer()->as<QmlContextWrapper>()->idObjectsArray();
+ return ctx->engine()->qmlContextObject()->getPointer()->as<QmlContextWrapper>()->idObjectsArray();
}
ReturnedValue Runtime::getQmlContextObject(NoThrowContext *ctx)
{
- QQmlContextData *context = QmlContextWrapper::callingContext(ctx->engine);
+ QQmlContextData *context = QmlContextWrapper::callingContext(ctx->engine());
if (!context)
return Encode::undefined();
- return QObjectWrapper::wrap(ctx->engine, context->contextObject);
+ return QObjectWrapper::wrap(ctx->d()->engine, context->contextObject);
}
ReturnedValue Runtime::getQmlScopeObject(NoThrowContext *ctx)
{
Scope scope(ctx);
- QV4::Scoped<QmlContextWrapper> c(scope, ctx->engine->qmlContextObject()->getPointer()->as<QmlContextWrapper>());
- return QObjectWrapper::wrap(ctx->engine, c->getScopeObject());
+ QV4::Scoped<QmlContextWrapper> c(scope, ctx->engine()->qmlContextObject()->getPointer()->as<QmlContextWrapper>());
+ return QObjectWrapper::wrap(ctx->d()->engine, c->getScopeObject());
}
ReturnedValue Runtime::getQmlQObjectProperty(ExecutionContext *ctx, const ValueRef object, int propertyIndex, bool captureRequired)
@@ -1312,11 +1315,11 @@ ReturnedValue Runtime::getQmlQObjectProperty(ExecutionContext *ctx, const ValueR
QV4::ReturnedValue Runtime::getQmlAttachedProperty(ExecutionContext *ctx, int attachedPropertiesId, int propertyIndex)
{
Scope scope(ctx);
- QV4::Scoped<QmlContextWrapper> c(scope, ctx->engine->qmlContextObject()->getPointer()->as<QmlContextWrapper>());
+ QV4::Scoped<QmlContextWrapper> c(scope, ctx->engine()->qmlContextObject()->getPointer()->as<QmlContextWrapper>());
QObject *scopeObject = c->getScopeObject();
QObject *attachedObject = qmlAttachedPropertiesObjectById(attachedPropertiesId, scopeObject);
- QQmlEngine *qmlEngine = ctx->engine->v8Engine->engine();
+ QQmlEngine *qmlEngine = ctx->engine()->v8Engine->engine();
QQmlData::ensurePropertyCache(qmlEngine, attachedObject);
return QV4::QObjectWrapper::getProperty(attachedObject, ctx, propertyIndex, /*captureRequired*/true);
}
@@ -1334,24 +1337,24 @@ void Runtime::setQmlQObjectProperty(ExecutionContext *ctx, const ValueRef object
ReturnedValue Runtime::getQmlImportedScripts(NoThrowContext *ctx)
{
- QQmlContextData *context = QmlContextWrapper::callingContext(ctx->engine);
+ QQmlContextData *context = QmlContextWrapper::callingContext(ctx->engine());
if (!context)
return Encode::undefined();
return context->importedScripts.value();
}
-QV4::ReturnedValue Runtime::getQmlSingleton(QV4::NoThrowContext *ctx, const QV4::StringRef name)
+QV4::ReturnedValue Runtime::getQmlSingleton(QV4::NoThrowContext *ctx, String *name)
{
- return ctx->engine->qmlContextObject()->getPointer()->as<QmlContextWrapper>()->qmlSingletonWrapper(ctx->engine->v8Engine, name);
+ return ctx->engine()->qmlContextObject()->getPointer()->as<QmlContextWrapper>()->qmlSingletonWrapper(ctx->engine()->v8Engine, name);
}
void Runtime::convertThisToObject(ExecutionContext *ctx)
{
- Value *t = &ctx->callData->thisObject;
+ Value *t = &ctx->d()->callData->thisObject;
if (t->isObject())
return;
if (t->isNullOrUndefined()) {
- *t = ctx->engine->globalObject->asReturnedValue();
+ *t = ctx->engine()->globalObject->asReturnedValue();
} else {
*t = t->toObject(ctx)->asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4runtime_p.h b/src/qml/jsruntime/qv4runtime_p.h
index 0979105680..992b027379 100644
--- a/src/qml/jsruntime/qv4runtime_p.h
+++ b/src/qml/jsruntime/qv4runtime_p.h
@@ -105,51 +105,51 @@ struct NoThrowContext : public ExecutionContext
struct Q_QML_PRIVATE_EXPORT Runtime {
// call
- static ReturnedValue callGlobalLookup(ExecutionContext *context, uint index, CallDataRef callData);
- static ReturnedValue callActivationProperty(ExecutionContext *, const StringRef name, CallDataRef callData);
- static ReturnedValue callProperty(ExecutionContext *context, const StringRef name, CallDataRef callData);
- static ReturnedValue callPropertyLookup(ExecutionContext *context, uint index, CallDataRef callData);
- static ReturnedValue callElement(ExecutionContext *context, const ValueRef index, CallDataRef callData);
- static ReturnedValue callValue(ExecutionContext *context, const ValueRef func, CallDataRef callData);
+ static ReturnedValue callGlobalLookup(ExecutionContext *context, uint index, CallData *callData);
+ static ReturnedValue callActivationProperty(ExecutionContext *, String *name, CallData *callData);
+ static ReturnedValue callProperty(ExecutionContext *context, String *name, CallData *callData);
+ static ReturnedValue callPropertyLookup(ExecutionContext *context, uint index, CallData *callData);
+ static ReturnedValue callElement(ExecutionContext *context, const ValueRef index, CallData *callData);
+ static ReturnedValue callValue(ExecutionContext *context, const ValueRef func, CallData *callData);
// construct
- static ReturnedValue constructGlobalLookup(ExecutionContext *context, uint index, CallDataRef callData);
- static ReturnedValue constructActivationProperty(ExecutionContext *, const StringRef name, CallDataRef callData);
- static ReturnedValue constructProperty(ExecutionContext *context, const StringRef name, CallDataRef callData);
- static ReturnedValue constructPropertyLookup(ExecutionContext *context, uint index, CallDataRef callData);
- static ReturnedValue constructValue(ExecutionContext *context, const ValueRef func, CallDataRef callData);
+ static ReturnedValue constructGlobalLookup(ExecutionContext *context, uint index, CallData *callData);
+ static ReturnedValue constructActivationProperty(ExecutionContext *, String *name, CallData *callData);
+ static ReturnedValue constructProperty(ExecutionContext *context, String *name, CallData *callData);
+ static ReturnedValue constructPropertyLookup(ExecutionContext *context, uint index, CallData *callData);
+ static ReturnedValue constructValue(ExecutionContext *context, const ValueRef func, CallData *callData);
// set & get
- static void setActivationProperty(ExecutionContext *ctx, const StringRef name, const ValueRef value);
- static void setProperty(ExecutionContext *ctx, const ValueRef object, const StringRef name, const ValueRef value);
+ static void setActivationProperty(ExecutionContext *ctx, String *name, const ValueRef value);
+ static void setProperty(ExecutionContext *ctx, const ValueRef object, String *name, const ValueRef value);
static void setElement(ExecutionContext *ctx, const ValueRef object, const ValueRef index, const ValueRef value);
- static ReturnedValue getProperty(ExecutionContext *ctx, const ValueRef object, const StringRef name);
- static ReturnedValue getActivationProperty(ExecutionContext *ctx, const StringRef name);
+ static ReturnedValue getProperty(ExecutionContext *ctx, const ValueRef object, String *name);
+ static ReturnedValue getActivationProperty(ExecutionContext *ctx, String *name);
static ReturnedValue getElement(ExecutionContext *ctx, const ValueRef object, const ValueRef index);
// typeof
static ReturnedValue typeofValue(ExecutionContext *ctx, const ValueRef val);
- static ReturnedValue typeofName(ExecutionContext *context, const StringRef name);
- static ReturnedValue typeofMember(ExecutionContext* context, const ValueRef base, const StringRef name);
+ static ReturnedValue typeofName(ExecutionContext *context, String *name);
+ static ReturnedValue typeofMember(ExecutionContext* context, const ValueRef base, String *name);
static ReturnedValue typeofElement(ExecutionContext* context, const ValueRef base, const ValueRef index);
// delete
static ReturnedValue deleteElement(ExecutionContext *ctx, const ValueRef base, const ValueRef index);
- static ReturnedValue deleteMember(ExecutionContext *ctx, const ValueRef base, const StringRef name);
- static ReturnedValue deleteName(ExecutionContext *ctx, const StringRef name);
+ static ReturnedValue deleteMember(ExecutionContext *ctx, const ValueRef base, String *name);
+ static ReturnedValue deleteName(ExecutionContext *ctx, String *name);
// exceptions & scopes
static void throwException(ExecutionContext*, const ValueRef value);
static ReturnedValue unwindException(ExecutionContext *ctx);
static ExecutionContext *pushWithScope(const ValueRef o, ExecutionContext *ctx);
- static ExecutionContext *pushCatchScope(ExecutionContext *ctx, const StringRef exceptionVarName);
+ static ExecutionContext *pushCatchScope(ExecutionContext *ctx, String *exceptionVarName);
static ExecutionContext *popScope(ExecutionContext *ctx);
// closures
static ReturnedValue closure(ExecutionContext *ctx, int functionId);
// function header
- static void declareVar(ExecutionContext *ctx, bool deletable, const StringRef name);
+ static void declareVar(ExecutionContext *ctx, bool deletable, String *name);
static ReturnedValue setupArgumentsObject(ExecutionContext *ctx);
static void convertThisToObject(ExecutionContext *ctx);
@@ -226,7 +226,7 @@ struct Q_QML_PRIVATE_EXPORT Runtime {
static ReturnedValue getQmlImportedScripts(NoThrowContext *ctx);
static ReturnedValue getQmlContextObject(NoThrowContext *ctx);
static ReturnedValue getQmlScopeObject(NoThrowContext *ctx);
- static ReturnedValue getQmlSingleton(NoThrowContext *ctx, const StringRef name);
+ static ReturnedValue getQmlSingleton(NoThrowContext *ctx, String *name);
static ReturnedValue getQmlAttachedProperty(ExecutionContext *ctx, int attachedPropertiesId, int propertyIndex);
static ReturnedValue getQmlQObjectProperty(ExecutionContext *ctx, const ValueRef object, int propertyIndex, bool captureRequired);
static void setQmlQObjectProperty(ExecutionContext *ctx, const ValueRef object, int propertyIndex, const ValueRef value);
diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h
index 5d471ab4fb..563d097440 100644
--- a/src/qml/jsruntime/qv4scopedvalue_p.h
+++ b/src/qml/jsruntime/qv4scopedvalue_p.h
@@ -117,6 +117,18 @@ struct ScopedValue
#endif
}
+ ScopedValue(const Scope &scope, HeapObject *o)
+ {
+ ptr = scope.engine->jsStackTop++;
+ ptr->m = reinterpret_cast<Managed *>(o);
+#if QT_POINTER_SIZE == 4
+ ptr->tag = QV4::Value::Managed_Type;
+#endif
+#ifndef QT_NO_DEBUG
+ ++scope.size;
+#endif
+ }
+
ScopedValue(const Scope &scope, Managed *m)
{
ptr = scope.engine->jsStackTop++;
@@ -150,6 +162,14 @@ struct ScopedValue
return *this;
}
+ ScopedValue &operator=(HeapObject *o) {
+ ptr->m = reinterpret_cast<Managed *>(o);
+#if QT_POINTER_SIZE == 4
+ ptr->tag = QV4::Value::Managed_Type;
+#endif
+ return *this;
+ }
+
ScopedValue &operator=(Managed *m) {
ptr->val = m->asReturnedValue();
return *this;
@@ -215,6 +235,19 @@ struct Scoped
++scope.size;
#endif
}
+ Scoped(const Scope &scope, HeapObject *o)
+ {
+ Value v;
+ v.m = reinterpret_cast<Managed *>(o);
+#if QT_POINTER_SIZE == 4
+ v.tag = QV4::Value::Managed_Type;
+#endif
+ ptr = scope.engine->jsStackTop++;
+ setPointer(value_cast<T>(v));
+#ifndef QT_NO_DEBUG
+ ++scope.size;
+#endif
+ }
Scoped(const Scope &scope, const ScopedValue &v)
{
ptr = scope.engine->jsStackTop++;
@@ -280,6 +313,15 @@ struct Scoped
#endif
}
+ Scoped<T> &operator=(HeapObject *o) {
+ Value v;
+ v.m = reinterpret_cast<Managed *>(o);
+#if QT_POINTER_SIZE == 4
+ v.tag = QV4::Value::Managed_Type;
+#endif
+ setPointer(value_cast<T>(v));
+ return *this;
+ }
Scoped<T> &operator=(const Value &v) {
setPointer(value_cast<T>(v));
return *this;
@@ -308,6 +350,9 @@ struct Scoped
return *this;
}
+ operator T *() {
+ return static_cast<T *>(ptr->managed());
+ }
T *operator->() {
return static_cast<T *>(ptr->managed());
@@ -379,10 +424,6 @@ struct ScopedCallData {
};
-struct StringRef;
-struct ObjectRef;
-struct FunctionObjectRef;
-
template<typename T>
inline Scoped<T>::Scoped(const Scope &scope, const ValueRef &v)
{
@@ -400,38 +441,6 @@ inline Scoped<T> &Scoped<T>::operator=(const ValueRef &v)
return *this;
}
-struct CallDataRef {
- CallDataRef(const ScopedCallData &c)
- : ptr(c.ptr) {}
- CallDataRef(CallData *v) { ptr = v; }
- // Important: Do NOT add a copy constructor to this class
- // adding a copy constructor actually changes the calling convention, ie.
- // is not even binary compatible. Adding it would break assumptions made
- // in the jit'ed code.
- CallDataRef &operator=(const ScopedCallData &c)
- { *ptr = *c.ptr; return *this; }
- CallDataRef &operator=(const CallDataRef &o)
- { *ptr = *o.ptr; return *this; }
-
- operator const CallData *() const {
- return ptr;
- }
- const CallData *operator->() const {
- return ptr;
- }
-
- operator CallData *() {
- return ptr;
- }
- CallData *operator->() {
- return ptr;
- }
-
-private:
- CallData *ptr;
-};
-
-
template <typename T>
inline Value &Value::operator=(Returned<T> *t)
{
@@ -467,14 +476,20 @@ inline Returned<T> *Value::as()
template<typename T>
inline TypedValue<T> &TypedValue<T>::operator =(T *t)
{
- val = t->asReturnedValue();
+ m = t;
+#if QT_POINTER_SIZE == 4
+ tag = Managed_Type;
+#endif
return *this;
}
template<typename T>
inline TypedValue<T> &TypedValue<T>::operator =(const Scoped<T> &v)
{
- val = v.ptr->val;
+ m = v.ptr->managed();
+#if QT_POINTER_SIZE == 4
+ tag = Managed_Type;
+#endif
return *this;
}
@@ -517,22 +532,12 @@ PersistentValue::PersistentValue(Returned<T> *obj)
{
}
-inline PersistentValue::PersistentValue(const ManagedRef obj)
- : d(new PersistentValuePrivate(obj.asReturnedValue()))
-{
-}
-
template<typename T>
inline PersistentValue &PersistentValue::operator=(Returned<T> *obj)
{
return operator=(QV4::Value::fromManaged(obj->getPointer()).asReturnedValue());
}
-inline PersistentValue &PersistentValue::operator=(const ManagedRef obj)
-{
- return operator=(obj.asReturnedValue());
-}
-
inline PersistentValue &PersistentValue::operator=(const ScopedValue &other)
{
return operator=(other.asReturnedValue());
@@ -573,18 +578,6 @@ inline ValueRef &ValueRef::operator=(const ScopedValue &o)
return *this;
}
-
-inline Value *extractValuePointer(const ScopedValue &v)
-{
- return v.ptr;
-}
-
-template<typename T>
-Value *extractValuePointer(const Scoped<T> &v)
-{
- return v.ptr;
-}
-
struct ScopedProperty
{
ScopedProperty(Scope &scope)
diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp
index 36f61a1df5..e08a63bd1f 100644
--- a/src/qml/jsruntime/qv4script.cpp
+++ b/src/qml/jsruntime/qv4script.cpp
@@ -61,12 +61,11 @@
using namespace QV4;
-QmlBindingWrapper::QmlBindingWrapper(ExecutionContext *scope, Function *f, ObjectRef qml)
- : FunctionObject(scope, scope->engine->id_eval, /*createProto = */ false)
+QmlBindingWrapper::Data::Data(ExecutionContext *scope, Function *f, Object *qml)
+ : FunctionObject::Data(scope, scope->d()->engine->id_eval, /*createProto = */ false)
, qml(qml)
- , qmlContext(0)
{
- Q_ASSERT(scope->inUse);
+ Q_ASSERT(scope->inUse());
setVTable(staticVTable());
function = f;
@@ -75,32 +74,30 @@ QmlBindingWrapper::QmlBindingWrapper(ExecutionContext *scope, Function *f, Objec
needsActivation = function ? function->needsActivation() : false;
Scope s(scope);
- ScopedValue protectThis(s, this);
+ Scoped<QmlBindingWrapper> o(s, this);
- defineReadonlyProperty(scope->engine->id_length, Primitive::fromInt32(1));
+ o->defineReadonlyProperty(scope->d()->engine->id_length, Primitive::fromInt32(1));
- qmlContext = scope->engine->currentContext()->newQmlContext(this, qml);
- scope->engine->popContext();
+ o->d()->qmlContext = reinterpret_cast<CallContext *>(s.engine->currentContext()->newQmlContext(o, qml));
+ s.engine->popContext();
}
-QmlBindingWrapper::QmlBindingWrapper(ExecutionContext *scope, ObjectRef qml)
- : FunctionObject(scope, scope->engine->id_eval, /*createProto = */ false)
+QmlBindingWrapper::Data::Data(ExecutionContext *scope, Object *qml)
+ : FunctionObject::Data(scope, scope->d()->engine->id_eval, /*createProto = */ false)
, qml(qml)
- , qmlContext(0)
{
- Q_ASSERT(scope->inUse);
+ Q_ASSERT(scope->inUse());
setVTable(staticVTable());
- function = 0;
needsActivation = false;
Scope s(scope);
- ScopedValue protectThis(s, this);
+ Scoped<QmlBindingWrapper> o(s, this);
- defineReadonlyProperty(scope->engine->id_length, Primitive::fromInt32(1));
+ o->defineReadonlyProperty(scope->d()->engine->id_length, Primitive::fromInt32(1));
- qmlContext = scope->engine->currentContext()->newQmlContext(this, qml);
- scope->engine->popContext();
+ o->d()->qmlContext = reinterpret_cast<CallContext *>(s.engine->currentContext()->newQmlContext(o, qml));
+ s.engine->popContext();
}
ReturnedValue QmlBindingWrapper::call(Managed *that, CallData *)
@@ -110,13 +107,13 @@ ReturnedValue QmlBindingWrapper::call(Managed *that, CallData *)
Scope scope(engine);
QmlBindingWrapper *This = static_cast<QmlBindingWrapper *>(that);
- if (!This->function)
+ if (!This->function())
return QV4::Encode::undefined();
- CallContext *ctx = This->qmlContext;
- std::fill(ctx->locals, ctx->locals + ctx->function->varCount(), Primitive::undefinedValue());
+ CallContext *ctx = This->d()->qmlContext;
+ std::fill(ctx->d()->locals, ctx->d()->locals + ctx->d()->function->varCount(), Primitive::undefinedValue());
engine->pushContext(ctx);
- ScopedValue result(scope, This->function->code(ctx, This->function->codeData));
+ ScopedValue result(scope, This->function()->code(ctx, This->function()->codeData));
engine->popContext();
return result.asReturnedValue();
@@ -125,16 +122,16 @@ ReturnedValue QmlBindingWrapper::call(Managed *that, CallData *)
void QmlBindingWrapper::markObjects(Managed *m, ExecutionEngine *e)
{
QmlBindingWrapper *wrapper = static_cast<QmlBindingWrapper*>(m);
- if (wrapper->qml)
- wrapper->qml->mark(e);
+ if (wrapper->d()->qml)
+ wrapper->d()->qml->mark(e);
FunctionObject::markObjects(m, e);
- if (wrapper->qmlContext)
- wrapper->qmlContext->mark(e);
+ if (wrapper->d()->qmlContext)
+ wrapper->d()->qmlContext->mark(e);
}
static ReturnedValue signalParameterGetter(QV4::CallContext *ctx, uint parameterIndex)
{
- QV4::CallContext *signalEmittingContext = ctx->parent->asCallContext();
+ QV4::CallContext *signalEmittingContext = ctx->d()->parent->asCallContext();
Q_ASSERT(signalEmittingContext);
return signalEmittingContext->argument(parameterIndex);
}
@@ -144,7 +141,7 @@ Returned<FunctionObject> *QmlBindingWrapper::createQmlCallableForFunction(QQmlCo
ExecutionEngine *engine = QQmlEnginePrivate::getV4Engine(qmlContext->engine);
QV4::Scope valueScope(engine);
QV4::ScopedObject qmlScopeObject(valueScope, QV4::QmlContextWrapper::qmlScope(engine->v8Engine, qmlContext, scopeObject));
- QV4::Scoped<QV4::QmlBindingWrapper> wrapper(valueScope, new (engine->memoryManager) QV4::QmlBindingWrapper(engine->rootContext, qmlScopeObject));
+ QV4::Scoped<QV4::QmlBindingWrapper> wrapper(valueScope, engine->memoryManager->alloc<QV4::QmlBindingWrapper>(engine->rootContext, qmlScopeObject));
if (!signalParameters.isEmpty()) {
if (error)
@@ -153,10 +150,11 @@ Returned<FunctionObject> *QmlBindingWrapper::createQmlCallableForFunction(QQmlCo
QV4::ScopedString s(valueScope);
int index = 0;
foreach (const QByteArray &param, signalParameters) {
- p->setGetter(new (engine->memoryManager) QV4::IndexedBuiltinFunction(wrapper->context(), index++, signalParameterGetter));
+ QV4::ScopedFunctionObject g(valueScope, engine->memoryManager->alloc<QV4::IndexedBuiltinFunction>(wrapper->context(), index++, signalParameterGetter));
+ p->setGetter(g);
p->setSetter(0);
s = engine->newString(QString::fromUtf8(param));
- qmlScopeObject->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotEnumerable|QV4::Attr_NotConfigurable);
+ qmlScopeObject->insertMember(s.getPointer(), p, QV4::Attr_Accessor|QV4::Attr_NotEnumerable|QV4::Attr_NotConfigurable);
}
}
@@ -166,35 +164,37 @@ Returned<FunctionObject> *QmlBindingWrapper::createQmlCallableForFunction(QQmlCo
DEFINE_OBJECT_VTABLE(QmlBindingWrapper);
-struct CompilationUnitHolder : public QV4::Object
+struct CompilationUnitHolder : public Object
{
- V4_OBJECT
+ struct Data : Object::Data {
+ Data(ExecutionEngine *engine, CompiledData::CompilationUnit *unit)
+ : Object::Data(engine)
+ , unit(unit)
+ {
+ unit->ref();
+ setVTable(staticVTable());
+ }
+ ~Data()
+ {
+ unit->deref();
+ }
+ QV4::CompiledData::CompilationUnit *unit;
+ };
+ V4_OBJECT(Object)
- CompilationUnitHolder(ExecutionEngine *engine, CompiledData::CompilationUnit *unit)
- : Object(engine)
- , unit(unit)
- {
- unit->ref();
- setVTable(staticVTable());
- }
- ~CompilationUnitHolder()
- {
- unit->deref();
- }
static void destroy(Managed *that)
{
- static_cast<CompilationUnitHolder*>(that)->~CompilationUnitHolder();
+ static_cast<CompilationUnitHolder*>(that)->d()->~Data();
}
- QV4::CompiledData::CompilationUnit *unit;
};
DEFINE_OBJECT_VTABLE(CompilationUnitHolder);
-Script::Script(ExecutionEngine *v4, ObjectRef qml, CompiledData::CompilationUnit *compilationUnit)
+Script::Script(ExecutionEngine *v4, Object *qml, CompiledData::CompilationUnit *compilationUnit)
: line(0), column(0), scope(v4->rootContext), strictMode(false), inheritContext(true), parsed(false)
- , qml(qml.asReturnedValue()), vmFunction(0), parseAsBinding(true)
+ , qml(qml->asReturnedValue()), vmFunction(0), parseAsBinding(true)
{
parsed = true;
@@ -202,7 +202,7 @@ Script::Script(ExecutionEngine *v4, ObjectRef qml, CompiledData::CompilationUnit
vmFunction = compilationUnit->linkToEngine(v4);
Q_ASSERT(vmFunction);
Scope valueScope(v4);
- ScopedValue holder(valueScope, new (v4->memoryManager) CompilationUnitHolder(v4, compilationUnit));
+ ScopedObject holder(valueScope, v4->memoryManager->alloc<CompilationUnitHolder>(v4, compilationUnit));
compilationUnitHolder = holder.asReturnedValue();
} else
vmFunction = 0;
@@ -221,7 +221,7 @@ void Script::parse()
parsed = true;
- ExecutionEngine *v4 = scope->engine;
+ ExecutionEngine *v4 = scope->d()->engine;
Scope valueScope(v4);
MemoryManager::GCBlocker gcBlocker(v4->memoryManager);
@@ -274,7 +274,7 @@ void Script::parse()
isel->setUseFastLookups(false);
QV4::CompiledData::CompilationUnit *compilationUnit = isel->compile();
vmFunction = compilationUnit->linkToEngine(v4);
- ScopedValue holder(valueScope, new (v4->memoryManager) CompilationUnitHolder(v4, compilationUnit));
+ ScopedObject holder(valueScope, v4->memoryManager->alloc<CompilationUnitHolder>(v4, compilationUnit));
compilationUnitHolder = holder.asReturnedValue();
}
@@ -295,16 +295,16 @@ ReturnedValue Script::run()
ContextStateSaver(ExecutionContext *context)
: savedContext(context)
- , strictMode(context->strictMode)
- , lookups(context->lookups)
- , compilationUnit(context->compilationUnit)
+ , strictMode(context->d()->strictMode)
+ , lookups(context->d()->lookups)
+ , compilationUnit(context->d()->compilationUnit)
{}
~ContextStateSaver()
{
- savedContext->strictMode = strictMode;
- savedContext->lookups = lookups;
- savedContext->compilationUnit = compilationUnit;
+ savedContext->d()->strictMode = strictMode;
+ savedContext->d()->lookups = lookups;
+ savedContext->d()->compilationUnit = compilationUnit;
}
};
@@ -313,7 +313,7 @@ ReturnedValue Script::run()
if (!vmFunction)
return Encode::undefined();
- QV4::ExecutionEngine *engine = scope->engine;
+ QV4::ExecutionEngine *engine = scope->d()->engine;
QV4::Scope valueScope(engine);
if (qml.isUndefined()) {
@@ -321,14 +321,14 @@ ReturnedValue Script::run()
ExecutionContextSaver ctxSaver(scope);
ContextStateSaver stateSaver(scope);
- scope->strictMode = vmFunction->isStrict();
- scope->lookups = vmFunction->compilationUnit->runtimeLookups;
- scope->compilationUnit = vmFunction->compilationUnit;
+ scope->d()->strictMode = vmFunction->isStrict();
+ scope->d()->lookups = vmFunction->compilationUnit->runtimeLookups;
+ scope->d()->compilationUnit = vmFunction->compilationUnit;
return vmFunction->code(scope, vmFunction->codeData);
} else {
ScopedObject qmlObj(valueScope, qml.value());
- FunctionObject *f = new (engine->memoryManager) QmlBindingWrapper(scope, vmFunction, qmlObj);
+ ScopedFunctionObject f(valueScope, engine->memoryManager->alloc<QmlBindingWrapper>(scope, vmFunction, qmlObj));
ScopedCallData callData(valueScope, 0);
callData->thisObject = Primitive::undefinedValue();
return f->call(callData);
@@ -401,14 +401,14 @@ ReturnedValue Script::qmlBinding()
{
if (!parsed)
parse();
- ExecutionEngine *v4 = scope->engine;
+ ExecutionEngine *v4 = scope->d()->engine;
Scope valueScope(v4);
ScopedObject qmlObj(valueScope, qml.value());
- ScopedObject v(valueScope, new (v4->memoryManager) QmlBindingWrapper(scope, vmFunction, qmlObj));
+ ScopedObject v(valueScope, v4->memoryManager->alloc<QmlBindingWrapper>(scope, vmFunction, qmlObj));
return v.asReturnedValue();
}
-QV4::ReturnedValue Script::evaluate(ExecutionEngine *engine, const QString &script, ObjectRef scopeObject)
+QV4::ReturnedValue Script::evaluate(ExecutionEngine *engine, const QString &script, Object *scopeObject)
{
QV4::Scope scope(engine);
QV4::Script qmlScript(engine, scopeObject, script, QString());
diff --git a/src/qml/jsruntime/qv4script_p.h b/src/qml/jsruntime/qv4script_p.h
index de582f9674..6a749d1438 100644
--- a/src/qml/jsruntime/qv4script_p.h
+++ b/src/qml/jsruntime/qv4script_p.h
@@ -55,23 +55,25 @@ namespace QV4 {
struct ExecutionContext;
-struct QmlBindingWrapper : FunctionObject {
- V4_OBJECT
-
- QmlBindingWrapper(ExecutionContext *scope, Function *f, ObjectRef qml);
- // Constructor for QML functions and signal handlers, resulting binding wrapper is not callable!
- QmlBindingWrapper(ExecutionContext *scope, ObjectRef qml);
+struct Q_QML_EXPORT QmlBindingWrapper : FunctionObject {
+ struct Data : FunctionObject::Data {
+ Data(ExecutionContext *scope, Function *f, Object *qml);
+ // Constructor for QML functions and signal handlers, resulting binding wrapper is not callable!
+ Data(ExecutionContext *scope, Object *qml);
+ Object *qml;
+ CallContext *qmlContext;
+ };
+ V4_OBJECT(FunctionObject)
static ReturnedValue call(Managed *that, CallData *);
static void markObjects(Managed *m, ExecutionEngine *e);
- CallContext *context() const { return qmlContext; }
+ CallContext *context() const { return d()->qmlContext; }
- static Returned<FunctionObject> *createQmlCallableForFunction(QQmlContextData *qmlContext, QObject *scopeObject, QV4::Function *runtimeFunction, const QList<QByteArray> &signalParameters = QList<QByteArray>(), QString *error = 0);
+ static Returned<FunctionObject> *createQmlCallableForFunction(QQmlContextData *qmlContext, QObject *scopeObject, QV4::Function *runtimeFunction,
+ const QList<QByteArray> &signalParameters = QList<QByteArray>(), QString *error = 0);
private:
- Object *qml;
- CallContext *qmlContext;
};
struct Q_QML_EXPORT Script {
@@ -79,11 +81,11 @@ struct Q_QML_EXPORT Script {
: sourceFile(source), line(line), column(column), sourceCode(sourceCode)
, scope(scope), strictMode(false), inheritContext(false), parsed(false)
, vmFunction(0), parseAsBinding(false) {}
- Script(ExecutionEngine *engine, ObjectRef qml, const QString &sourceCode, const QString &source = QString(), int line = 1, int column = 0)
+ Script(ExecutionEngine *engine, Object *qml, const QString &sourceCode, const QString &source = QString(), int line = 1, int column = 0)
: sourceFile(source), line(line), column(column), sourceCode(sourceCode)
, scope(engine->rootContext), strictMode(false), inheritContext(true), parsed(false)
- , qml(qml.asReturnedValue()), vmFunction(0), parseAsBinding(true) {}
- Script(ExecutionEngine *engine, ObjectRef qml, CompiledData::CompilationUnit *compilationUnit);
+ , qml(qml->asReturnedValue()), vmFunction(0), parseAsBinding(true) {}
+ Script(ExecutionEngine *engine, Object *qml, CompiledData::CompilationUnit *compilationUnit);
~Script();
QString sourceFile;
int line;
@@ -106,7 +108,7 @@ struct Q_QML_EXPORT Script {
static QV4::CompiledData::CompilationUnit *precompile(IR::Module *module, Compiler::JSUnitGenerator *unitGenerator, ExecutionEngine *engine, const QUrl &url, const QString &source, QList<QQmlError> *reportedErrors = 0);
- static ReturnedValue evaluate(ExecutionEngine *engine, const QString &script, ObjectRef scopeObject);
+ static ReturnedValue evaluate(ExecutionEngine *engine, const QString &script, Object *scopeObject);
};
}
diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp
index 89231cfe5f..b55cd2daad 100644
--- a/src/qml/jsruntime/qv4sequenceobject.cpp
+++ b/src/qml/jsruntime/qv4sequenceobject.cpp
@@ -58,13 +58,13 @@ using namespace QV4;
// helper function to generate valid warnings if errors occur during sequence operations.
static void generateWarning(QV4::ExecutionContext *ctx, const QString& description)
{
- QQmlEngine *engine = ctx->engine->v8Engine->engine();
+ QQmlEngine *engine = ctx->d()->engine->v8Engine->engine();
if (!engine)
return;
QQmlError retn;
retn.setDescription(description);
- QV4::StackFrame frame = ctx->engine->currentStackFrame();
+ QV4::StackFrame frame = ctx->d()->engine->currentStackFrame();
retn.setLine(frame.line);
retn.setUrl(QUrl(frame.source));
@@ -163,38 +163,41 @@ template <> bool convertValueToElement(const ValueRef value)
}
template <typename Container>
-class QQmlSequence : public QV4::Object
+struct QQmlSequence : public QV4::Object
{
- V4_OBJECT
+ struct Data : Object::Data {
+ Data(QV4::ExecutionEngine *engine, const Container &container)
+ : Object::Data(InternalClass::create(engine, staticVTable(), engine->sequencePrototype.asObject()))
+ , container(container)
+ , propertyIndex(-1)
+ , isReference(false)
+ {
+ QV4::Scope scope(engine);
+ QV4::Scoped<QQmlSequence<Container> > o(scope, this);
+ o->setArrayType(ArrayData::Custom);
+ o->init();
+ }
+
+ Data(QV4::ExecutionEngine *engine, QObject *object, int propertyIndex)
+ : Object::Data(InternalClass::create(engine, staticVTable(), engine->sequencePrototype.asObject()))
+ , object(object)
+ , propertyIndex(propertyIndex)
+ , isReference(true)
+ {
+ QV4::Scope scope(engine);
+ QV4::Scoped<QQmlSequence<Container> > o(scope, this);
+ o->setArrayType(ArrayData::Custom);
+ o->loadReference();
+ o->init();
+ }
+ mutable Container container;
+ QPointer<QObject> object;
+ int propertyIndex;
+ bool isReference;
+ };
+ V4_OBJECT(QV4::Object)
Q_MANAGED_TYPE(QmlSequence)
public:
- QQmlSequence(QV4::ExecutionEngine *engine, const Container &container)
- : QV4::Object(InternalClass::create(engine, staticVTable(), engine->sequencePrototype.asObject()))
- , m_container(container)
- , m_object(0)
- , m_propertyIndex(-1)
- , m_isReference(false)
- {
- QV4::Scope scope(engine);
- QV4::ScopedObject protectThis(scope, this);
- Q_UNUSED(protectThis);
- setArrayType(ArrayData::Custom);
- init();
- }
-
- QQmlSequence(QV4::ExecutionEngine *engine, QObject *object, int propertyIndex)
- : QV4::Object(InternalClass::create(engine, staticVTable(), engine->sequencePrototype.asObject()))
- , m_object(object)
- , m_propertyIndex(propertyIndex)
- , m_isReference(true)
- {
- QV4::Scope scope(engine);
- QV4::ScopedObject protectThis(scope, this);
- Q_UNUSED(protectThis);
- setArrayType(ArrayData::Custom);
- loadReference();
- init();
- }
void init()
{
@@ -210,8 +213,8 @@ public:
*hasProperty = false;
return Encode::undefined();
}
- if (m_isReference) {
- if (!m_object) {
+ if (d()->isReference) {
+ if (!d()->object) {
if (hasProperty)
*hasProperty = false;
return Encode::undefined();
@@ -219,10 +222,10 @@ public:
loadReference();
}
qint32 signedIdx = static_cast<qint32>(index);
- if (signedIdx < m_container.count()) {
+ if (signedIdx < d()->container.count()) {
if (hasProperty)
*hasProperty = true;
- return convertElementToValue(engine(), m_container.at(signedIdx));
+ return convertElementToValue(engine(), d()->container.at(signedIdx));
}
if (hasProperty)
*hasProperty = false;
@@ -231,7 +234,7 @@ public:
void containerPutIndexed(uint index, const QV4::ValueRef value)
{
- if (internalClass->engine->hasException)
+ if (internalClass()->engine->hasException)
return;
/* Qt containers have int (rather than uint) allowable indexes. */
@@ -240,33 +243,33 @@ public:
return;
}
- if (m_isReference) {
- if (!m_object)
+ if (d()->isReference) {
+ if (!d()->object)
return;
loadReference();
}
qint32 signedIdx = static_cast<qint32>(index);
- int count = m_container.count();
+ int count = d()->container.count();
typename Container::value_type element = convertValueToElement<typename Container::value_type>(value);
if (signedIdx == count) {
- m_container.append(element);
+ d()->container.append(element);
} else if (signedIdx < count) {
- m_container[signedIdx] = element;
+ d()->container[signedIdx] = element;
} else {
/* according to ECMA262r3 we need to insert */
/* the value at the given index, increasing length to index+1. */
- m_container.reserve(signedIdx + 1);
+ d()->container.reserve(signedIdx + 1);
while (signedIdx > count++) {
- m_container.append(typename Container::value_type());
+ d()->container.append(typename Container::value_type());
}
- m_container.append(element);
+ d()->container.append(element);
}
- if (m_isReference)
+ if (d()->isReference)
storeReference();
}
@@ -277,33 +280,33 @@ public:
generateWarning(engine()->currentContext(), QLatin1String("Index out of range during indexed query"));
return QV4::Attr_Invalid;
}
- if (m_isReference) {
- if (!m_object)
+ if (d()->isReference) {
+ if (!d()->object)
return QV4::Attr_Invalid;
loadReference();
}
qint32 signedIdx = static_cast<qint32>(index);
- return (signedIdx < m_container.count()) ? QV4::Attr_Data : QV4::Attr_Invalid;
+ return (signedIdx < d()->container.count()) ? QV4::Attr_Data : QV4::Attr_Invalid;
}
- void containerAdvanceIterator(ObjectIterator *it, StringRef name, uint *index, Property *p, PropertyAttributes *attrs)
+ void containerAdvanceIterator(ObjectIterator *it, String *&name, uint *index, Property *p, PropertyAttributes *attrs)
{
name = (String *)0;
*index = UINT_MAX;
- if (m_isReference) {
- if (!m_object) {
+ if (d()->isReference) {
+ if (!d()->object) {
QV4::Object::advanceIterator(this, it, name, index, p, attrs);
return;
}
loadReference();
}
- if (it->arrayIndex < static_cast<uint>(m_container.count())) {
+ if (it->arrayIndex < static_cast<uint>(d()->container.count())) {
*index = it->arrayIndex;
++it->arrayIndex;
*attrs = QV4::Attr_Data;
- p->value = convertElementToValue(engine(), m_container.at(*index));
+ p->value = convertElementToValue(engine(), d()->container.at(*index));
return;
}
QV4::Object::advanceIterator(this, it, name, index, p, attrs);
@@ -314,21 +317,21 @@ public:
/* Qt containers have int (rather than uint) allowable indexes. */
if (index > INT_MAX)
return false;
- if (m_isReference) {
- if (!m_object)
+ if (d()->isReference) {
+ if (!d()->object)
return false;
loadReference();
}
qint32 signedIdx = static_cast<qint32>(index);
- if (signedIdx >= m_container.count())
+ if (signedIdx >= d()->container.count())
return false;
/* according to ECMA262r3 it should be Undefined, */
/* but we cannot, so we insert a default-value instead. */
- m_container.replace(signedIdx, typename Container::value_type());
+ d()->container.replace(signedIdx, typename Container::value_type());
- if (m_isReference)
+ if (d()->isReference)
storeReference();
return true;
@@ -339,9 +342,9 @@ public:
QQmlSequence<Container> *otherSequence = other->as<QQmlSequence<Container> >();
if (!otherSequence)
return false;
- if (m_isReference && otherSequence->m_isReference) {
- return m_object == otherSequence->m_object && m_propertyIndex == otherSequence->m_propertyIndex;
- } else if (!m_isReference && !otherSequence->m_isReference) {
+ if (d()->isReference && otherSequence->d()->isReference) {
+ return d()->object == otherSequence->d()->object && d()->propertyIndex == otherSequence->d()->propertyIndex;
+ } else if (!d()->isReference && !otherSequence->d()->isReference) {
return this == otherSequence;
}
return false;
@@ -366,9 +369,9 @@ public:
QV4::Scope scope(m_ctx);
ScopedObject compare(scope, m_compareFn);
ScopedCallData callData(scope, 2);
- callData->args[0] = convertElementToValue(this->m_ctx->engine, lhs);
- callData->args[1] = convertElementToValue(this->m_ctx->engine, rhs);
- callData->thisObject = this->m_ctx->engine->globalObject;
+ callData->args[0] = convertElementToValue(this->m_ctx->d()->engine, lhs);
+ callData->args[1] = convertElementToValue(this->m_ctx->d()->engine, rhs);
+ callData->thisObject = this->m_ctx->d()->engine->globalObject;
QV4::ScopedValue result(scope, compare->call(callData));
return result->toNumber() < 0;
}
@@ -380,82 +383,82 @@ public:
void sort(QV4::CallContext *ctx)
{
- if (m_isReference) {
- if (!m_object)
+ if (d()->isReference) {
+ if (!d()->object)
return;
loadReference();
}
QV4::Scope scope(ctx);
- if (ctx->callData->argc == 1 && ctx->callData->args[0].asFunctionObject()) {
- CompareFunctor cf(ctx, ctx->callData->args[0]);
- std::sort(m_container.begin(), m_container.end(), cf);
+ if (ctx->d()->callData->argc == 1 && ctx->d()->callData->args[0].asFunctionObject()) {
+ CompareFunctor cf(ctx, ctx->d()->callData->args[0]);
+ std::sort(d()->container.begin(), d()->container.end(), cf);
} else {
DefaultCompareFunctor cf;
- std::sort(m_container.begin(), m_container.end(), cf);
+ std::sort(d()->container.begin(), d()->container.end(), cf);
}
- if (m_isReference)
+ if (d()->isReference)
storeReference();
}
static QV4::ReturnedValue method_get_length(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
- QV4::Scoped<QQmlSequence<Container> > This(scope, ctx->callData->thisObject.as<QQmlSequence<Container> >());
+ QV4::Scoped<QQmlSequence<Container> > This(scope, ctx->d()->callData->thisObject.as<QQmlSequence<Container> >());
if (!This)
return ctx->throwTypeError();
- if (This->m_isReference) {
- if (!This->m_object)
+ if (This->d()->isReference) {
+ if (!This->d()->object)
return QV4::Encode(0);
This->loadReference();
}
- return QV4::Encode(This->m_container.count());
+ return QV4::Encode(This->d()->container.count());
}
static QV4::ReturnedValue method_set_length(QV4::CallContext* ctx)
{
QV4::Scope scope(ctx);
- QV4::Scoped<QQmlSequence<Container> > This(scope, ctx->callData->thisObject.as<QQmlSequence<Container> >());
+ QV4::Scoped<QQmlSequence<Container> > This(scope, ctx->d()->callData->thisObject.as<QQmlSequence<Container> >());
if (!This)
return ctx->throwTypeError();
- quint32 newLength = ctx->callData->args[0].toUInt32();
+ quint32 newLength = ctx->d()->callData->args[0].toUInt32();
/* Qt containers have int (rather than uint) allowable indexes. */
if (newLength > INT_MAX) {
generateWarning(ctx, QLatin1String("Index out of range during length set"));
return QV4::Encode::undefined();
}
/* Read the sequence from the QObject property if we're a reference */
- if (This->m_isReference) {
- if (!This->m_object)
+ if (This->d()->isReference) {
+ if (!This->d()->object)
return QV4::Encode::undefined();
This->loadReference();
}
/* Determine whether we need to modify the sequence */
qint32 newCount = static_cast<qint32>(newLength);
- qint32 count = This->m_container.count();
+ qint32 count = This->d()->container.count();
if (newCount == count) {
return QV4::Encode::undefined();
} else if (newCount > count) {
/* according to ECMA262r3 we need to insert */
/* undefined values increasing length to newLength. */
/* We cannot, so we insert default-values instead. */
- This->m_container.reserve(newCount);
+ This->d()->container.reserve(newCount);
while (newCount > count++) {
- This->m_container.append(typename Container::value_type());
+ This->d()->container.append(typename Container::value_type());
}
} else {
/* according to ECMA262r3 we need to remove */
/* elements until the sequence is the required length. */
while (newCount < count) {
count--;
- This->m_container.removeAt(count);
+ This->d()->container.removeAt(count);
}
}
/* write back if required. */
- if (This->m_isReference) {
+ if (This->d()->isReference) {
/* write back. already checked that object is non-null, so skip that check here. */
This->storeReference();
}
@@ -463,9 +466,9 @@ public:
}
QVariant toVariant() const
- { return QVariant::fromValue<Container>(m_container); }
+ { return QVariant::fromValue<Container>(d()->container); }
- static QVariant toVariant(QV4::ArrayObjectRef array)
+ static QVariant toVariant(QV4::ArrayObject *array)
{
QV4::Scope scope(array->engine());
Container result;
@@ -479,27 +482,22 @@ public:
private:
void loadReference() const
{
- Q_ASSERT(m_object);
- Q_ASSERT(m_isReference);
- void *a[] = { &m_container, 0 };
- QMetaObject::metacall(m_object, QMetaObject::ReadProperty, m_propertyIndex, a);
+ Q_ASSERT(d()->object);
+ Q_ASSERT(d()->isReference);
+ void *a[] = { &d()->container, 0 };
+ QMetaObject::metacall(d()->object, QMetaObject::ReadProperty, d()->propertyIndex, a);
}
void storeReference()
{
- Q_ASSERT(m_object);
- Q_ASSERT(m_isReference);
+ Q_ASSERT(d()->object);
+ Q_ASSERT(d()->isReference);
int status = -1;
QQmlPropertyPrivate::WriteFlags flags = QQmlPropertyPrivate::DontRemoveBinding;
- void *a[] = { &m_container, 0, &status, &flags };
- QMetaObject::metacall(m_object, QMetaObject::WriteProperty, m_propertyIndex, a);
+ void *a[] = { &d()->container, 0, &status, &flags };
+ QMetaObject::metacall(d()->object, QMetaObject::WriteProperty, d()->propertyIndex, a);
}
- mutable Container m_container;
- QPointer<QObject> m_object;
- int m_propertyIndex;
- bool m_isReference;
-
static QV4::ReturnedValue getIndexed(QV4::Managed *that, uint index, bool *hasProperty)
{ return static_cast<QQmlSequence<Container> *>(that)->containerGetIndexed(index, hasProperty); }
static void putIndexed(Managed *that, uint index, const QV4::ValueRef value)
@@ -510,7 +508,7 @@ private:
{ return static_cast<QQmlSequence<Container> *>(that)->containerDeleteIndexedProperty(index); }
static bool isEqualTo(Managed *that, Managed *other)
{ return static_cast<QQmlSequence<Container> *>(that)->containerIsEqualTo(other); }
- static void advanceIterator(Managed *that, ObjectIterator *it, StringRef name, uint *index, Property *p, PropertyAttributes *attrs)
+ static void advanceIterator(Managed *that, ObjectIterator *it, String *&name, uint *index, Property *p, PropertyAttributes *attrs)
{ return static_cast<QQmlSequence<Container> *>(that)->containerAdvanceIterator(it, name, index, p, attrs); }
static void destroy(Managed *that)
@@ -539,27 +537,22 @@ template<>
DEFINE_OBJECT_VTABLE(QQmlRealList);
#define REGISTER_QML_SEQUENCE_METATYPE(unused, unused2, SequenceType, unused3) qRegisterMetaType<SequenceType>(#SequenceType);
-SequencePrototype::SequencePrototype(InternalClass *ic)
- : QV4::Object(ic)
-{
- FOREACH_QML_SEQUENCE_TYPE(REGISTER_QML_SEQUENCE_METATYPE)
-}
-#undef REGISTER_QML_SEQUENCE_METATYPE
-
void SequencePrototype::init()
{
+ FOREACH_QML_SEQUENCE_TYPE(REGISTER_QML_SEQUENCE_METATYPE)
defineDefaultProperty(QStringLiteral("sort"), method_sort, 1);
defineDefaultProperty(engine()->id_valueOf, method_valueOf, 0);
}
+#undef REGISTER_QML_SEQUENCE_METATYPE
QV4::ReturnedValue SequencePrototype::method_sort(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
- QV4::ScopedObject o(scope, ctx->callData->thisObject);
+ QV4::ScopedObject o(scope, ctx->d()->callData->thisObject);
if (!o || !o->isListType())
return ctx->throwTypeError();
- if (ctx->callData->argc >= 2)
+ if (ctx->d()->callData->argc >= 2)
return o.asReturnedValue();
#define CALL_SORT(SequenceElementType, SequenceElementTypeName, SequenceType, DefaultValue) \
@@ -587,7 +580,7 @@ bool SequencePrototype::isSequenceType(int sequenceTypeId)
#define NEW_REFERENCE_SEQUENCE(ElementType, ElementTypeName, SequenceType, unused) \
if (sequenceType == qMetaTypeId<SequenceType>()) { \
- QV4::Scoped<QV4::Object> obj(scope, new (engine->memoryManager) QQml##ElementTypeName##List(engine, object, propertyIndex)); \
+ QV4::Scoped<QV4::Object> obj(scope, engine->memoryManager->alloc<QQml##ElementTypeName##List>(engine, object, propertyIndex)); \
return obj.asReturnedValue(); \
} else
@@ -605,7 +598,7 @@ ReturnedValue SequencePrototype::newSequence(QV4::ExecutionEngine *engine, int s
#define NEW_COPY_SEQUENCE(ElementType, ElementTypeName, SequenceType, unused) \
if (sequenceType == qMetaTypeId<SequenceType>()) { \
- QV4::Scoped<QV4::Object> obj(scope, new (engine->memoryManager) QQml##ElementTypeName##List(engine, v.value<SequenceType >())); \
+ QV4::Scoped<QV4::Object> obj(scope, engine->memoryManager->alloc<QQml##ElementTypeName##List>(engine, v.value<SequenceType >())); \
return obj.asReturnedValue(); \
} else
@@ -627,7 +620,7 @@ ReturnedValue SequencePrototype::fromVariant(QV4::ExecutionEngine *engine, const
return list->toVariant(); \
else
-QVariant SequencePrototype::toVariant(ObjectRef object)
+QVariant SequencePrototype::toVariant(Object *object)
{
Q_ASSERT(object->isListType());
FOREACH_QML_SEQUENCE_TYPE(SEQUENCE_TO_VARIANT) { /* else */ return QVariant(); }
@@ -660,7 +653,7 @@ QVariant SequencePrototype::toVariant(const QV4::ValueRef array, int typeHint, b
return qMetaTypeId<SequenceType>(); \
} else
-int SequencePrototype::metaTypeForSequence(QV4::ObjectRef object)
+int SequencePrototype::metaTypeForSequence(QV4::Object *object)
{
FOREACH_QML_SEQUENCE_TYPE(MAP_META_TYPE)
/*else*/ {
diff --git a/src/qml/jsruntime/qv4sequenceobject_p.h b/src/qml/jsruntime/qv4sequenceobject_p.h
index 4a5e82b688..727f312930 100644
--- a/src/qml/jsruntime/qv4sequenceobject_p.h
+++ b/src/qml/jsruntime/qv4sequenceobject_p.h
@@ -65,13 +65,11 @@ namespace QV4 {
struct SequencePrototype : public QV4::Object
{
- SequencePrototype(QV4::InternalClass *ic);
-
void init();
static ReturnedValue method_valueOf(QV4::CallContext *ctx)
{
- return ctx->callData->thisObject.toString(ctx)->asReturnedValue();
+ return ctx->d()->callData->thisObject.toString(ctx)->asReturnedValue();
}
static ReturnedValue method_sort(QV4::CallContext *ctx);
@@ -79,8 +77,8 @@ struct SequencePrototype : public QV4::Object
static bool isSequenceType(int sequenceTypeId);
static ReturnedValue newSequence(QV4::ExecutionEngine *engine, int sequenceTypeId, QObject *object, int propertyIndex, bool *succeeded);
static ReturnedValue fromVariant(QV4::ExecutionEngine *engine, const QVariant& v, bool *succeeded);
- static int metaTypeForSequence(ObjectRef object);
- static QVariant toVariant(QV4::ObjectRef object);
+ static int metaTypeForSequence(Object *object);
+ static QVariant toVariant(Object *object);
static QVariant toVariant(const ValueRef array, int typeHint, bool *succeeded);
};
diff --git a/src/qml/jsruntime/qv4serialize.cpp b/src/qml/jsruntime/qv4serialize.cpp
index 3d754389a2..4e88a331a4 100644
--- a/src/qml/jsruntime/qv4serialize.cpp
+++ b/src/qml/jsruntime/qv4serialize.cpp
@@ -208,7 +208,7 @@ void Serialize::serialize(QByteArray &data, const QV4::ValueRef v, QV8Engine *en
} else if (QV4::DateObject *d = v->asDateObject()) {
reserve(data, sizeof(quint32) + sizeof(double));
push(data, valueheader(WorkerDate));
- push(data, d->value.asDouble());
+ push(data, d->date().asDouble());
} else if (v->as<RegExpObject>()) {
Scoped<RegExpObject> re(scope, v);
quint32 flags = re->flags();
@@ -281,7 +281,7 @@ void Serialize::serialize(QByteArray &data, const QV4::ValueRef v, QV8Engine *en
QV4::ExecutionContext *ctx = v4->currentContext();
str = s;
- val = o->get(str);
+ val = o->get(str.getPointer());
if (scope.hasException())
ctx->catchException();
@@ -342,7 +342,7 @@ ReturnedValue Serialize::deserialize(const char *&data, QV8Engine *engine)
name = deserialize(data, engine);
value = deserialize(data, engine);
n = name.asReturnedValue();
- o->put(n, value);
+ o->put(n.getPointer(), value);
}
return o.asReturnedValue();
}
@@ -372,7 +372,7 @@ ReturnedValue Serialize::deserialize(const char *&data, QV8Engine *engine)
QVariant var = qVariantFromValue(ref);
QV4::ScopedValue v(scope, engine->fromVariant((var)));
QV4::ScopedString s(scope, v4->newString(QStringLiteral("__qml:hidden:ref")));
- rv->asObject()->defineReadonlyProperty(s, v);
+ rv->asObject()->defineReadonlyProperty(s.getPointer(), v);
agent->release();
agent->setV8Engine(engine);
diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp
index d9aa881f21..123d1648c2 100644
--- a/src/qml/jsruntime/qv4string.cpp
+++ b/src/qml/jsruntime/qv4string.cpp
@@ -108,7 +108,7 @@ static uint toArrayIndex(const char *ch, const char *end, bool *ok)
const ObjectVTable String::static_vtbl =
{
- DEFINE_MANAGED_VTABLE_INT(String),
+ DEFINE_MANAGED_VTABLE_INT(String, 0),
0,
0,
get,
@@ -133,13 +133,13 @@ void String::destroy(Managed *that)
void String::markObjects(Managed *that, ExecutionEngine *e)
{
String *s = static_cast<String *>(that);
- if (s->largestSubLength) {
- s->left->mark(e);
- s->right->mark(e);
+ if (s->d()->largestSubLength) {
+ s->d()->left->mark(e);
+ s->d()->right->mark(e);
}
}
-ReturnedValue String::get(Managed *m, const StringRef name, bool *hasProperty)
+ReturnedValue String::get(Managed *m, String *name, bool *hasProperty)
{
ExecutionEngine *v4 = m->engine();
Scope scope(v4);
@@ -148,7 +148,7 @@ ReturnedValue String::get(Managed *m, const StringRef name, bool *hasProperty)
if (name->equals(v4->id_length)) {
if (hasProperty)
*hasProperty = true;
- return Primitive::fromInt32(that->_text->size).asReturnedValue();
+ return Primitive::fromInt32(that->d()->text->size).asReturnedValue();
}
PropertyAttributes attrs;
Property *pd = v4->stringObjectClass->prototype->__getPropertyDescriptor__(name, &attrs);
@@ -168,7 +168,7 @@ ReturnedValue String::getIndexed(Managed *m, uint index, bool *hasProperty)
Scope scope(engine);
ScopedString that(scope, static_cast<String *>(m));
- if (index < static_cast<uint>(that->_text->size)) {
+ if (index < static_cast<uint>(that->d()->text->size)) {
if (hasProperty)
*hasProperty = true;
return Encode(engine->newString(that->toQString().mid(index, 1)));
@@ -185,7 +185,7 @@ ReturnedValue String::getIndexed(Managed *m, uint index, bool *hasProperty)
return engine->stringObjectClass->prototype->getValue(that, pd, attrs);
}
-void String::put(Managed *m, const StringRef name, const ValueRef value)
+void String::put(Managed *m, String *name, const ValueRef value)
{
Scope scope(m->engine());
if (scope.hasException())
@@ -206,7 +206,7 @@ void String::putIndexed(Managed *m, uint index, const ValueRef value)
o->putIndexed(index, value);
}
-PropertyAttributes String::query(const Managed *m, StringRef name)
+PropertyAttributes String::query(const Managed *m, String *name)
{
uint idx = name->asArrayIndex();
if (idx != UINT_MAX)
@@ -217,10 +217,10 @@ PropertyAttributes String::query(const Managed *m, StringRef name)
PropertyAttributes String::queryIndexed(const Managed *m, uint index)
{
const String *that = static_cast<const String *>(m);
- return (index < static_cast<uint>(that->_text->size)) ? Attr_NotConfigurable|Attr_NotWritable : Attr_Invalid;
+ return (index < static_cast<uint>(that->d()->text->size)) ? Attr_NotConfigurable|Attr_NotWritable : Attr_Invalid;
}
-bool String::deleteProperty(Managed *, const StringRef)
+bool String::deleteProperty(Managed *, String *)
{
return false;
}
@@ -235,44 +235,50 @@ bool String::isEqualTo(Managed *t, Managed *o)
if (t == o)
return true;
- if (!o->internalClass->vtable->isString)
+ if (!o->internalClass()->vtable->isString)
return false;
String *that = static_cast<String *>(t);
String *other = static_cast<String *>(o);
if (that->hashValue() != other->hashValue())
return false;
- if (that->identifier && that->identifier == other->identifier)
+ if (that->identifier() && that->identifier() == other->identifier())
return true;
- if (that->subtype >= StringType_UInt && that->subtype == other->subtype)
+ if (that->subtype() >= StringType_UInt && that->subtype() == other->subtype())
return true;
return that->toQString() == other->toQString();
}
-String::String(ExecutionEngine *engine, const QString &text)
- : Managed(engine->stringClass), _text(const_cast<QString &>(text).data_ptr())
- , identifier(0), stringHash(UINT_MAX)
- , largestSubLength(0)
+String::Data::Data(ExecutionEngine *engine, const QString &t)
+ : Managed::Data(engine->stringClass)
{
- _text->ref.ref();
- len = _text->size;
subtype = StringType_Unknown;
+
+ text = const_cast<QString &>(t).data_ptr();
+ text->ref.ref();
+ identifier = 0;
+ stringHash = UINT_MAX;
+ largestSubLength = 0;
+ len = text->size;
}
-String::String(ExecutionEngine *engine, String *l, String *r)
- : Managed(engine->stringClass)
- , left(l), right(r)
- , stringHash(UINT_MAX), largestSubLength(qMax(l->largestSubLength, r->largestSubLength))
- , len(l->len + r->len)
+String::Data::Data(ExecutionEngine *engine, String *l, String *r)
+ : Managed::Data(engine->stringClass)
{
subtype = StringType_Unknown;
- if (!l->largestSubLength && l->len > largestSubLength)
- largestSubLength = l->len;
- if (!r->largestSubLength && r->len > largestSubLength)
- largestSubLength = r->len;
+ left = l;
+ right = r;
+ stringHash = UINT_MAX;
+ largestSubLength = qMax(l->d()->largestSubLength, r->d()->largestSubLength);
+ len = l->d()->len + r->d()->len;
+
+ if (!l->d()->largestSubLength && l->d()->len > largestSubLength)
+ largestSubLength = l->d()->len;
+ if (!r->d()->largestSubLength && r->d()->len > largestSubLength)
+ largestSubLength = r->d()->len;
// make sure we don't get excessive depth in our strings
if (len > 256 && len >= 2*largestSubLength)
@@ -283,10 +289,10 @@ uint String::toUInt(bool *ok) const
{
*ok = true;
- if (subtype == StringType_Unknown)
+ if (subtype() == StringType_Unknown)
createHashValue();
- if (subtype >= StringType_UInt)
- return stringHash;
+ if (subtype() >= StringType_UInt)
+ return d()->stringHash;
// ### this conversion shouldn't be required
double d = RuntimeHelpers::stringToNumber(toQString());
@@ -297,15 +303,15 @@ uint String::toUInt(bool *ok) const
return UINT_MAX;
}
-bool String::equals(const StringRef other) const
+bool String::equals(String *other) const
{
- if (this == other.getPointer())
+ if (this == other)
return true;
if (hashValue() != other->hashValue())
return false;
- if (identifier && identifier == other->identifier)
+ if (identifier() && identifier() == other->identifier())
return true;
- if (subtype >= StringType_UInt && subtype == other->subtype)
+ if (subtype() >= StringType_UInt && subtype() == other->subtype())
return true;
return toQString() == other->toQString();
@@ -313,13 +319,13 @@ bool String::equals(const StringRef other) const
void String::makeIdentifierImpl() const
{
- if (largestSubLength)
- simplifyString();
- Q_ASSERT(!largestSubLength);
+ if (d()->largestSubLength)
+ d()->simplifyString();
+ Q_ASSERT(!d()->largestSubLength);
engine()->identifierTable->identifier(this);
}
-void String::simplifyString() const
+void String::Data::simplifyString() const
{
Q_ASSERT(largestSubLength);
@@ -327,20 +333,20 @@ void String::simplifyString() const
QString result(l, Qt::Uninitialized);
QChar *ch = const_cast<QChar *>(result.constData());
recursiveAppend(ch);
- _text = result.data_ptr();
- _text->ref.ref();
+ text = result.data_ptr();
+ text->ref.ref();
identifier = 0;
largestSubLength = 0;
}
-QChar *String::recursiveAppend(QChar *ch) const
+QChar *String::Data::recursiveAppend(QChar *ch) const
{
if (largestSubLength) {
- ch = left->recursiveAppend(ch);
- ch = right->recursiveAppend(ch);
+ ch = left->d()->recursiveAppend(ch);
+ ch = right->d()->recursiveAppend(ch);
} else {
- memcpy(ch, _text->data(), _text->size*sizeof(QChar));
- ch += _text->size;
+ memcpy(ch, text->data(), text->size*sizeof(QChar));
+ ch += text->size;
}
return ch;
}
@@ -348,17 +354,17 @@ QChar *String::recursiveAppend(QChar *ch) const
void String::createHashValue() const
{
- if (largestSubLength)
- simplifyString();
- Q_ASSERT(!largestSubLength);
- const QChar *ch = reinterpret_cast<const QChar *>(_text->data());
- const QChar *end = ch + _text->size;
+ if (d()->largestSubLength)
+ d()->simplifyString();
+ Q_ASSERT(!d()->largestSubLength);
+ const QChar *ch = reinterpret_cast<const QChar *>(d()->text->data());
+ const QChar *end = ch + d()->text->size;
// array indices get their number as hash value
bool ok;
- stringHash = ::toArrayIndex(ch, end, &ok);
+ d()->stringHash = ::toArrayIndex(ch, end, &ok);
if (ok) {
- subtype = (stringHash == UINT_MAX) ? StringType_UInt : StringType_ArrayIndex;
+ setSubtype((d()->stringHash == UINT_MAX) ? StringType_UInt : StringType_ArrayIndex);
return;
}
@@ -368,8 +374,8 @@ void String::createHashValue() const
++ch;
}
- stringHash = h;
- subtype = StringType_Regular;
+ d()->stringHash = h;
+ setSubtype(StringType_Regular);
}
uint String::createHashValue(const QChar *ch, int length)
@@ -414,7 +420,7 @@ uint String::createHashValue(const char *ch, int length)
uint String::getLength(const Managed *m)
{
- return static_cast<const String *>(m)->length();
+ return static_cast<const String *>(m)->d()->length();
}
#endif // V4_BOOTSTRAP
diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h
index ed2a4e3646..f9d3cd1cc0 100644
--- a/src/qml/jsruntime/qv4string_p.h
+++ b/src/qml/jsruntime/qv4string_p.h
@@ -53,8 +53,36 @@ struct Identifier;
struct Q_QML_PRIVATE_EXPORT String : public Managed {
#ifndef V4_BOOTSTRAP
+ struct Q_QML_PRIVATE_EXPORT Data : Managed::Data {
+ Data(ExecutionEngine *engine, const QString &text);
+ Data(ExecutionEngine *engine, String *l, String *n);
+ ~Data() {
+ if (!largestSubLength && !text->ref.deref())
+ QStringData::deallocate(text);
+ }
+ void simplifyString() const;
+ int length() const {
+ Q_ASSERT((largestSubLength &&
+ (len == left->d()->len + right->d()->len)) ||
+ len == (uint)text->size);
+ return len;
+ }
+ union {
+ mutable QStringData *text;
+ mutable String *left;
+ };
+ union {
+ mutable Identifier *identifier;
+ mutable String *right;
+ };
+ mutable uint stringHash;
+ mutable uint largestSubLength;
+ uint len;
+ private:
+ QChar *recursiveAppend(QChar *ch) const;
+ };
// ### FIXME: Should this be a V4_OBJECT
- V4_OBJECT
+ V4_OBJECT(QV4::Managed)
Q_MANAGED_TYPE(String)
enum {
IsString = true
@@ -67,24 +95,16 @@ struct Q_QML_PRIVATE_EXPORT String : public Managed {
StringType_ArrayIndex
};
- String(ExecutionEngine *engine, const QString &text);
- String(ExecutionEngine *engine, String *l, String *n);
- ~String() {
- if (!largestSubLength && !_text->ref.deref())
- QStringData::deallocate(_text);
- _data = 0;
- }
-
- bool equals(const StringRef other) const;
+ bool equals(String *other) const;
inline bool isEqualTo(const String *other) const {
if (this == other)
return true;
if (hashValue() != other->hashValue())
return false;
- Q_ASSERT(!largestSubLength);
- if (identifier && identifier == other->identifier)
+ Q_ASSERT(!d()->largestSubLength);
+ if (d()->identifier && d()->identifier == other->d()->identifier)
return true;
- if (subtype >= StringType_UInt && subtype == other->subtype)
+ if (subtype() >= StringType_UInt && subtype() == other->subtype())
return true;
return toQString() == other->toQString();
@@ -95,34 +115,32 @@ struct Q_QML_PRIVATE_EXPORT String : public Managed {
}
inline QString toQString() const {
- if (largestSubLength)
- simplifyString();
- QStringDataPtr ptr = { _text };
- _text->ref.ref();
+ if (d()->largestSubLength)
+ d()->simplifyString();
+ QStringDataPtr ptr = { d()->text };
+ d()->text->ref.ref();
return QString(ptr);
}
- void simplifyString() const;
-
inline unsigned hashValue() const {
- if (subtype == StringType_Unknown)
+ if (subtype() == StringType_Unknown)
createHashValue();
- Q_ASSERT(!largestSubLength);
+ Q_ASSERT(!d()->largestSubLength);
- return stringHash;
+ return d()->stringHash;
}
uint asArrayIndex() const {
- if (subtype == StringType_Unknown)
+ if (subtype() == StringType_Unknown)
createHashValue();
- Q_ASSERT(!largestSubLength);
- if (subtype == StringType_ArrayIndex)
- return stringHash;
+ Q_ASSERT(!d()->largestSubLength);
+ if (subtype() == StringType_ArrayIndex)
+ return d()->stringHash;
return UINT_MAX;
}
uint toUInt(bool *ok) const;
void makeIdentifier() const {
- if (identifier)
+ if (d()->identifier)
return;
makeIdentifierImpl();
}
@@ -135,44 +153,26 @@ struct Q_QML_PRIVATE_EXPORT String : public Managed {
bool startsWithUpper() const {
const String *l = this;
- while (l->largestSubLength)
- l = l->left;
- return l->_text->size && QChar::isUpper(l->_text->data()[0]);
- }
- int length() const {
- Q_ASSERT((largestSubLength && (len == left->len + right->len)) || len == (uint)_text->size);
- return len;
+ while (l->d()->largestSubLength)
+ l = l->d()->left;
+ return l->d()->text->size && QChar::isUpper(l->d()->text->data()[0]);
}
- union {
- mutable QStringData *_text;
- mutable String *left;
- };
- union {
- mutable Identifier *identifier;
- mutable String *right;
- };
- mutable uint stringHash;
- mutable uint largestSubLength;
- uint len;
-
+ Identifier *identifier() const { return d()->identifier; }
protected:
static void destroy(Managed *);
static void markObjects(Managed *that, ExecutionEngine *e);
- static ReturnedValue get(Managed *m, const StringRef name, bool *hasProperty);
+ static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
- static void put(Managed *m, const StringRef name, const ValueRef value);
+ static void put(Managed *m, String *name, const ValueRef value);
static void putIndexed(Managed *m, uint index, const ValueRef value);
- static PropertyAttributes query(const Managed *m, StringRef name);
+ static PropertyAttributes query(const Managed *m, String *name);
static PropertyAttributes queryIndexed(const Managed *m, uint index);
- static bool deleteProperty(Managed *, const StringRef);
+ static bool deleteProperty(Managed *, String *);
static bool deleteIndexedProperty(Managed *m, uint index);
static bool isEqualTo(Managed *that, Managed *o);
static uint getLength(const Managed *m);
-
-private:
- QChar *recursiveAppend(QChar *ch) const;
#endif
public:
@@ -191,7 +191,6 @@ inline ReturnedValue value_convert<String>(ExecutionEngine *e, const Value &v)
return v.toString(e)->asReturnedValue();
}
-DEFINE_REF(String, Managed);
#endif
}
diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp
index f1e51703a8..3f683495cd 100644
--- a/src/qml/jsruntime/qv4stringobject.cpp
+++ b/src/qml/jsruntime/qv4stringobject.cpp
@@ -77,44 +77,38 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(StringObject);
-StringObject::StringObject(InternalClass *ic)
- : Object(ic)
+StringObject::Data::Data(InternalClass *ic)
+ : Object::Data(ic)
{
Q_ASSERT(internalClass->vtable == staticVTable());
-
- Scope scope(engine());
- ScopedObject protectThis(scope, this);
-
value = ic->engine->newString(QStringLiteral(""))->asReturnedValue();
-
tmpProperty.value = Primitive::undefinedValue();
- defineReadonlyProperty(ic->engine->id_length, Primitive::fromInt32(0));
+ Scope scope(ic->engine);
+ ScopedObject s(scope, this);
+ s->defineReadonlyProperty(ic->engine->id_length, Primitive::fromInt32(0));
}
-StringObject::StringObject(ExecutionEngine *engine, const ValueRef val)
- : Object(engine->stringObjectClass)
+StringObject::Data::Data(ExecutionEngine *engine, const ValueRef val)
+ : Object::Data(engine->stringObjectClass)
{
+ value = val;
+ Q_ASSERT(value.isString());
+ tmpProperty.value = Primitive::undefinedValue();
setVTable(staticVTable());
Scope scope(engine);
- ScopedObject protectThis(scope, this);
-
- value = *val;
-
- tmpProperty.value = Primitive::undefinedValue();
-
- assert(value.isString());
- defineReadonlyProperty(engine->id_length, Primitive::fromUInt32(value.stringValue()->toQString().length()));
+ ScopedObject s(scope, this);
+ s->defineReadonlyProperty(engine->id_length, Primitive::fromUInt32(value.stringValue()->toQString().length()));
}
Property *StringObject::getIndex(uint index) const
{
- QString str = value.stringValue()->toQString();
+ QString str = d()->value.stringValue()->toQString();
if (index >= (uint)str.length())
return 0;
- tmpProperty.value = Encode(internalClass->engine->newString(str.mid(index, 1)));
- return &tmpProperty;
+ d()->tmpProperty.value = Encode(internalClass()->engine->newString(str.mid(index, 1)));
+ return &d()->tmpProperty;
}
bool StringObject::deleteIndexedProperty(Managed *m, uint index)
@@ -127,19 +121,19 @@ bool StringObject::deleteIndexedProperty(Managed *m, uint index)
return false;
}
- if (index < static_cast<uint>(o->value.stringValue()->toQString().length())) {
- if (v4->currentContext()->strictMode)
+ if (index < static_cast<uint>(o->d()->value.stringValue()->toQString().length())) {
+ if (v4->currentContext()->d()->strictMode)
v4->currentContext()->throwTypeError();
return false;
}
return true;
}
-void StringObject::advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, Property *p, PropertyAttributes *attrs)
+void StringObject::advanceIterator(Managed *m, ObjectIterator *it, String *&name, uint *index, Property *p, PropertyAttributes *attrs)
{
name = (String *)0;
StringObject *s = static_cast<StringObject *>(m);
- uint slen = s->value.stringValue()->toQString().length();
+ uint slen = s->d()->value.stringValue()->toQString().length();
if (it->arrayIndex <= slen) {
while (it->arrayIndex < slen) {
*index = it->arrayIndex;
@@ -152,7 +146,7 @@ void StringObject::advanceIterator(Managed *m, ObjectIterator *it, StringRef nam
return;
}
}
- if (s->arrayData) {
+ if (s->arrayData()) {
it->arrayNode = s->sparseBegin();
// iterate until we're past the end of the string
while (it->arrayNode && it->arrayNode->key() < slen)
@@ -166,15 +160,15 @@ void StringObject::advanceIterator(Managed *m, ObjectIterator *it, StringRef nam
void StringObject::markObjects(Managed *that, ExecutionEngine *e)
{
StringObject *o = static_cast<StringObject *>(that);
- o->value.stringValue()->mark(e);
- o->tmpProperty.value.mark(e);
+ o->d()->value.stringValue()->mark(e);
+ o->d()->tmpProperty.value.mark(e);
Object::markObjects(that, e);
}
DEFINE_OBJECT_VTABLE(StringCtor);
-StringCtor::StringCtor(ExecutionContext *scope)
- : FunctionObject(scope, QStringLiteral("String"))
+StringCtor::Data::Data(ExecutionContext *scope)
+ : FunctionObject::Data(scope, QStringLiteral("String"))
{
setVTable(staticVTable());
}
@@ -203,7 +197,7 @@ ReturnedValue StringCtor::call(Managed *m, CallData *callData)
return value.asReturnedValue();
}
-void StringPrototype::init(ExecutionEngine *engine, ObjectRef ctor)
+void StringPrototype::init(ExecutionEngine *engine, Object *ctor)
{
Scope scope(engine);
ScopedObject o(scope);
@@ -238,11 +232,11 @@ void StringPrototype::init(ExecutionEngine *engine, ObjectRef ctor)
static QString getThisString(ExecutionContext *ctx)
{
Scope scope(ctx);
- ScopedValue t(scope, ctx->callData->thisObject);
+ ScopedValue t(scope, ctx->d()->callData->thisObject);
if (t->isString())
return t->stringValue()->toQString();
if (StringObject *thisString = t->asStringObject())
- return thisString->value.stringValue()->toQString();
+ return thisString->d()->value.stringValue()->toQString();
if (t->isUndefined() || t->isNull()) {
ctx->throwTypeError();
return QString();
@@ -252,41 +246,41 @@ static QString getThisString(ExecutionContext *ctx)
ReturnedValue StringPrototype::method_toString(CallContext *context)
{
- if (context->callData->thisObject.isString())
- return context->callData->thisObject.asReturnedValue();
+ if (context->d()->callData->thisObject.isString())
+ return context->d()->callData->thisObject.asReturnedValue();
- StringObject *o = context->callData->thisObject.asStringObject();
+ StringObject *o = context->d()->callData->thisObject.asStringObject();
if (!o)
return context->throwTypeError();
- return o->value.asReturnedValue();
+ return o->d()->value.asReturnedValue();
}
ReturnedValue StringPrototype::method_charAt(CallContext *context)
{
const QString str = getThisString(context);
- if (context->engine->hasException)
+ if (context->d()->engine->hasException)
return Encode::undefined();
int pos = 0;
- if (context->callData->argc > 0)
- pos = (int) context->callData->args[0].toInteger();
+ if (context->d()->callData->argc > 0)
+ pos = (int) context->d()->callData->args[0].toInteger();
QString result;
if (pos >= 0 && pos < str.length())
result += str.at(pos);
- return context->engine->newString(result)->asReturnedValue();
+ return context->d()->engine->newString(result)->asReturnedValue();
}
ReturnedValue StringPrototype::method_charCodeAt(CallContext *context)
{
const QString str = getThisString(context);
- if (context->engine->hasException)
+ if (context->d()->engine->hasException)
return Encode::undefined();
int pos = 0;
- if (context->callData->argc > 0)
- pos = (int) context->callData->args[0].toInteger();
+ if (context->d()->callData->argc > 0)
+ pos = (int) context->d()->callData->args[0].toInteger();
if (pos >= 0 && pos < str.length())
@@ -304,30 +298,30 @@ ReturnedValue StringPrototype::method_concat(CallContext *context)
return Encode::undefined();
ScopedValue v(scope);
- for (int i = 0; i < context->callData->argc; ++i) {
- v = RuntimeHelpers::toString(context, ValueRef(&context->callData->args[i]));
+ for (int i = 0; i < context->d()->callData->argc; ++i) {
+ v = RuntimeHelpers::toString(context, ValueRef(&context->d()->callData->args[i]));
if (scope.hasException())
return Encode::undefined();
Q_ASSERT(v->isString());
value += v->stringValue()->toQString();
}
- return context->engine->newString(value)->asReturnedValue();
+ return context->d()->engine->newString(value)->asReturnedValue();
}
ReturnedValue StringPrototype::method_indexOf(CallContext *context)
{
QString value = getThisString(context);
- if (context->engine->hasException)
+ if (context->d()->engine->hasException)
return Encode::undefined();
QString searchString;
- if (context->callData->argc)
- searchString = context->callData->args[0].toString(context)->toQString();
+ if (context->d()->callData->argc)
+ searchString = context->d()->callData->args[0].toString(context)->toQString();
int pos = 0;
- if (context->callData->argc > 1)
- pos = (int) context->callData->args[1].toInteger();
+ if (context->d()->callData->argc > 1)
+ pos = (int) context->d()->callData->args[1].toInteger();
int index = -1;
if (! value.isEmpty())
@@ -345,8 +339,8 @@ ReturnedValue StringPrototype::method_lastIndexOf(CallContext *context)
return Encode::undefined();
QString searchString;
- if (context->callData->argc)
- searchString = context->callData->args[0].toQString();
+ if (context->d()->callData->argc)
+ searchString = context->d()->callData->args[0].toQString();
ScopedValue posArg(scope, context->argument(1));
double position = RuntimeHelpers::toNumber(posArg);
@@ -371,36 +365,36 @@ ReturnedValue StringPrototype::method_localeCompare(CallContext *context)
if (scope.engine->hasException)
return Encode::undefined();
- ScopedValue v(scope, context->callData->argument(0));
+ ScopedValue v(scope, context->d()->callData->argument(0));
const QString that = v->toQString();
return Encode(QString::localeAwareCompare(value, that));
}
ReturnedValue StringPrototype::method_match(CallContext *context)
{
- if (context->callData->thisObject.isUndefined() || context->callData->thisObject.isNull())
+ if (context->d()->callData->thisObject.isUndefined() || context->d()->callData->thisObject.isNull())
return context->throwTypeError();
Scope scope(context);
- ScopedString s(scope, context->callData->thisObject.toString(context));
+ ScopedString s(scope, context->d()->callData->thisObject.toString(context));
- ScopedValue regexp(scope, context->callData->argument(0));
+ ScopedValue regexp(scope, context->d()->callData->argument(0));
Scoped<RegExpObject> rx(scope, regexp);
if (!rx) {
ScopedCallData callData(scope, 1);
callData->args[0] = regexp;
- rx = context->engine->regExpCtor.asFunctionObject()->construct(callData);
+ rx = context->d()->engine->regExpCtor.asFunctionObject()->construct(callData);
}
if (!rx)
// ### CHECK
return context->throwTypeError();
- bool global = rx->global;
+ bool global = rx->global();
// ### use the standard builtin function, not the one that might be redefined in the proto
- ScopedString execString(scope, context->engine->newString(QStringLiteral("exec")));
- Scoped<FunctionObject> exec(scope, context->engine->regExpClass->prototype->get(execString));
+ ScopedString execString(scope, context->d()->engine->newString(QStringLiteral("exec")));
+ Scoped<FunctionObject> exec(scope, context->d()->engine->regExpClass->prototype->get(execString.getPointer()));
ScopedCallData callData(scope, 1);
callData->thisObject = rx;
@@ -408,9 +402,9 @@ ReturnedValue StringPrototype::method_match(CallContext *context)
if (!global)
return exec->call(callData);
- ScopedString lastIndex(scope, context->engine->newString(QStringLiteral("lastIndex")));
- rx->put(lastIndex, ScopedValue(scope, Primitive::fromInt32(0)));
- Scoped<ArrayObject> a(scope, context->engine->newArrayObject());
+ ScopedString lastIndex(scope, context->d()->engine->newString(QStringLiteral("lastIndex")));
+ rx->put(lastIndex.getPointer(), ScopedValue(scope, Primitive::fromInt32(0)));
+ Scoped<ArrayObject> a(scope, context->d()->engine->newArrayObject());
double previousLastIndex = 0;
uint n = 0;
@@ -422,11 +416,11 @@ ReturnedValue StringPrototype::method_match(CallContext *context)
if (result->isNull())
break;
assert(result->isObject());
- index = rx->get(lastIndex, 0);
+ index = rx->get(lastIndex.getPointer(), 0);
double thisIndex = index->toInteger();
if (previousLastIndex == thisIndex) {
previousLastIndex = thisIndex + 1;
- rx->put(lastIndex, ScopedValue(scope, Primitive::fromDouble(previousLastIndex)));
+ rx->put(lastIndex.getPointer(), ScopedValue(scope, Primitive::fromDouble(previousLastIndex)));
} else {
previousLastIndex = thisIndex;
}
@@ -491,10 +485,10 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx)
{
Scope scope(ctx);
QString string;
- if (StringObject *thisString = ctx->callData->thisObject.asStringObject())
- string = thisString->value.stringValue()->toQString();
+ if (StringObject *thisString = ctx->d()->callData->thisObject.asStringObject())
+ string = thisString->d()->value.stringValue()->toQString();
else
- string = ctx->callData->thisObject.toString(ctx)->toQString();
+ string = ctx->d()->callData->thisObject.toString(ctx)->toQString();
int numCaptures = 0;
int numStringMatches = 0;
@@ -510,7 +504,7 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx)
uint offset = 0;
// We extract the pointer here to work around a compiler bug on Android.
- Scoped<RegExp> re(scope, regExp->value);
+ Scoped<RegExp> re(scope, regExp->value());
while (true) {
int oldSize = nMatchOffsets;
if (allocatedMatchOffsets < nMatchOffsets + re->captureCount() * 2) {
@@ -526,14 +520,14 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx)
break;
}
nMatchOffsets += re->captureCount() * 2;
- if (!regExp->global)
+ if (!regExp->d()->global)
break;
offset = qMax(offset + 1, matchOffsets[oldSize + 1]);
}
- if (regExp->global)
+ if (regExp->global())
regExp->lastIndexProperty(ctx)->value = Primitive::fromUInt32(0);
- numStringMatches = nMatchOffsets / (regExp->value->captureCount() * 2);
- numCaptures = regExp->value->captureCount();
+ numStringMatches = nMatchOffsets / (regExp->value()->captureCount() * 2);
+ numCaptures = regExp->value()->captureCount();
} else {
numCaptures = 1;
QString searchString = searchValue->toString(ctx)->toQString();
@@ -563,14 +557,14 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx)
uint end = matchOffsets[idx + 1];
entry = Primitive::undefinedValue();
if (start != JSC::Yarr::offsetNoMatch && end != JSC::Yarr::offsetNoMatch)
- entry = ctx->engine->newString(string.mid(start, end - start));
+ entry = ctx->d()->engine->newString(string.mid(start, end - start));
callData->args[k] = entry;
}
uint matchStart = matchOffsets[i * numCaptures * 2];
Q_ASSERT(matchStart >= static_cast<uint>(lastEnd));
uint matchEnd = matchOffsets[i * numCaptures * 2 + 1];
callData->args[numCaptures] = Primitive::fromUInt32(matchStart);
- callData->args[numCaptures + 1] = ctx->engine->newString(string);
+ callData->args[numCaptures + 1] = ctx->d()->engine->newString(string);
replacement = searchCallback->call(callData);
result += string.midRef(lastEnd, matchStart - lastEnd);
@@ -600,7 +594,7 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx)
if (matchOffsets != _matchOffsets)
free(matchOffsets);
- return ctx->engine->newString(result)->asReturnedValue();
+ return ctx->d()->engine->newString(result)->asReturnedValue();
}
ReturnedValue StringPrototype::method_search(CallContext *ctx)
@@ -614,14 +608,14 @@ ReturnedValue StringPrototype::method_search(CallContext *ctx)
if (!regExp) {
ScopedCallData callData(scope, 1);
callData->args[0] = regExpValue;
- regExpValue = ctx->engine->regExpCtor.asFunctionObject()->construct(callData);
+ regExpValue = ctx->d()->engine->regExpCtor.asFunctionObject()->construct(callData);
if (scope.engine->hasException)
return Encode::undefined();
regExp = regExpValue->as<RegExpObject>();
Q_ASSERT(regExp);
}
- uint* matchOffsets = (uint*)alloca(regExp->value->captureCount() * 2 * sizeof(uint));
- uint result = regExp->value->match(string, /*offset*/0, matchOffsets);
+ uint* matchOffsets = (uint*)alloca(regExp->value()->captureCount() * 2 * sizeof(uint));
+ uint result = regExp->value()->match(string, /*offset*/0, matchOffsets);
if (result == JSC::Yarr::offsetNoMatch)
return Encode(-1);
return Encode(result);
@@ -630,14 +624,14 @@ ReturnedValue StringPrototype::method_search(CallContext *ctx)
ReturnedValue StringPrototype::method_slice(CallContext *ctx)
{
const QString text = getThisString(ctx);
- if (ctx->engine->hasException)
+ if (ctx->d()->engine->hasException)
return Encode::undefined();
const double length = text.length();
- double start = ctx->callData->argc ? ctx->callData->args[0].toInteger() : 0;
- double end = (ctx->callData->argc < 2 || ctx->callData->args[1].isUndefined())
- ? length : ctx->callData->args[1].toInteger();
+ double start = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toInteger() : 0;
+ double end = (ctx->d()->callData->argc < 2 || ctx->d()->callData->args[1].isUndefined())
+ ? length : ctx->d()->callData->args[1].toInteger();
if (start < 0)
start = qMax(length + start, 0.);
@@ -653,7 +647,7 @@ ReturnedValue StringPrototype::method_slice(CallContext *ctx)
const int intEnd = int(end);
int count = qMax(0, intEnd - intStart);
- return ctx->engine->newString(text.mid(intStart, count))->asReturnedValue();
+ return ctx->d()->engine->newString(text.mid(intStart, count))->asReturnedValue();
}
ReturnedValue StringPrototype::method_split(CallContext *ctx)
@@ -666,15 +660,15 @@ ReturnedValue StringPrototype::method_split(CallContext *ctx)
ScopedValue separatorValue(scope, ctx->argument(0));
ScopedValue limitValue(scope, ctx->argument(1));
- ScopedArrayObject array(scope, ctx->engine->newArrayObject());
+ ScopedArrayObject array(scope, ctx->d()->engine->newArrayObject());
if (separatorValue->isUndefined()) {
if (limitValue->isUndefined()) {
- ScopedString s(scope, ctx->engine->newString(text));
+ ScopedString s(scope, ctx->d()->engine->newString(text));
array->push_back(s);
return array.asReturnedValue();
}
- return ctx->engine->newString(text.left(limitValue->toInteger()))->asReturnedValue();
+ return ctx->d()->engine->newString(text.left(limitValue->toInteger()))->asReturnedValue();
}
uint limit = limitValue->isUndefined() ? UINT_MAX : limitValue->toUInt32();
@@ -684,55 +678,55 @@ ReturnedValue StringPrototype::method_split(CallContext *ctx)
Scoped<RegExpObject> re(scope, separatorValue);
if (re) {
- if (re->value->pattern().isEmpty()) {
+ if (re->value()->pattern().isEmpty()) {
re = (RegExpObject *)0;
- separatorValue = ctx->engine->newString(QString());
+ separatorValue = ctx->d()->engine->newString(QString());
}
}
ScopedString s(scope);
if (re) {
uint offset = 0;
- uint* matchOffsets = (uint*)alloca(re->value->captureCount() * 2 * sizeof(uint));
+ uint* matchOffsets = (uint*)alloca(re->value()->captureCount() * 2 * sizeof(uint));
while (true) {
- uint result = re->value->match(text, offset, matchOffsets);
+ uint result = re->value()->match(text, offset, matchOffsets);
if (result == JSC::Yarr::offsetNoMatch)
break;
- array->push_back((s = ctx->engine->newString(text.mid(offset, matchOffsets[0] - offset))));
+ array->push_back((s = ctx->d()->engine->newString(text.mid(offset, matchOffsets[0] - offset))));
offset = qMax(offset + 1, matchOffsets[1]);
if (array->getLength() >= limit)
break;
- for (int i = 1; i < re->value->captureCount(); ++i) {
+ for (int i = 1; i < re->value()->captureCount(); ++i) {
uint start = matchOffsets[i * 2];
uint end = matchOffsets[i * 2 + 1];
- array->push_back((s = ctx->engine->newString(text.mid(start, end - start))));
+ array->push_back((s = ctx->d()->engine->newString(text.mid(start, end - start))));
if (array->getLength() >= limit)
break;
}
}
if (array->getLength() < limit)
- array->push_back((s = ctx->engine->newString(text.mid(offset))));
+ array->push_back((s = ctx->d()->engine->newString(text.mid(offset))));
} else {
QString separator = separatorValue->toString(ctx)->toQString();
if (separator.isEmpty()) {
for (uint i = 0; i < qMin(limit, uint(text.length())); ++i)
- array->push_back((s = ctx->engine->newString(text.mid(i, 1))));
+ array->push_back((s = ctx->d()->engine->newString(text.mid(i, 1))));
return array.asReturnedValue();
}
int start = 0;
int end;
while ((end = text.indexOf(separator, start)) != -1) {
- array->push_back((s = ctx->engine->newString(text.mid(start, end - start))));
+ array->push_back((s = ctx->d()->engine->newString(text.mid(start, end - start))));
start = end + separator.size();
if (array->getLength() >= limit)
break;
}
if (array->getLength() < limit && start != -1)
- array->push_back((s = ctx->engine->newString(text.mid(start))));
+ array->push_back((s = ctx->d()->engine->newString(text.mid(start))));
}
return array.asReturnedValue();
}
@@ -740,16 +734,16 @@ ReturnedValue StringPrototype::method_split(CallContext *ctx)
ReturnedValue StringPrototype::method_substr(CallContext *context)
{
const QString value = getThisString(context);
- if (context->engine->hasException)
+ if (context->d()->engine->hasException)
return Encode::undefined();
double start = 0;
- if (context->callData->argc > 0)
- start = context->callData->args[0].toInteger();
+ if (context->d()->callData->argc > 0)
+ start = context->d()->callData->args[0].toInteger();
double length = +qInf();
- if (context->callData->argc > 1)
- length = context->callData->args[1].toInteger();
+ if (context->d()->callData->argc > 1)
+ length = context->d()->callData->args[1].toInteger();
double count = value.length();
if (start < 0)
@@ -759,21 +753,21 @@ ReturnedValue StringPrototype::method_substr(CallContext *context)
qint32 x = Primitive::toInt32(start);
qint32 y = Primitive::toInt32(length);
- return context->engine->newString(value.mid(x, y))->asReturnedValue();
+ return context->d()->engine->newString(value.mid(x, y))->asReturnedValue();
}
ReturnedValue StringPrototype::method_substring(CallContext *context)
{
QString value = getThisString(context);
- if (context->engine->hasException)
+ if (context->d()->engine->hasException)
return Encode::undefined();
int length = value.length();
double start = 0;
double end = length;
- if (context->callData->argc > 0)
- start = context->callData->args[0].toInteger();
+ if (context->d()->callData->argc > 0)
+ start = context->d()->callData->args[0].toInteger();
Scope scope(context);
ScopedValue endValue(scope, context->argument(1));
@@ -800,15 +794,15 @@ ReturnedValue StringPrototype::method_substring(CallContext *context)
qint32 x = (int)start;
qint32 y = (int)(end - start);
- return context->engine->newString(value.mid(x, y))->asReturnedValue();
+ return context->d()->engine->newString(value.mid(x, y))->asReturnedValue();
}
ReturnedValue StringPrototype::method_toLowerCase(CallContext *ctx)
{
QString value = getThisString(ctx);
- if (ctx->engine->hasException)
+ if (ctx->d()->engine->hasException)
return Encode::undefined();
- return ctx->engine->newString(value.toLower())->asReturnedValue();
+ return ctx->d()->engine->newString(value.toLower())->asReturnedValue();
}
ReturnedValue StringPrototype::method_toLocaleLowerCase(CallContext *ctx)
@@ -819,9 +813,9 @@ ReturnedValue StringPrototype::method_toLocaleLowerCase(CallContext *ctx)
ReturnedValue StringPrototype::method_toUpperCase(CallContext *ctx)
{
QString value = getThisString(ctx);
- if (ctx->engine->hasException)
+ if (ctx->d()->engine->hasException)
return Encode::undefined();
- return ctx->engine->newString(value.toUpper())->asReturnedValue();
+ return ctx->d()->engine->newString(value.toUpper())->asReturnedValue();
}
ReturnedValue StringPrototype::method_toLocaleUpperCase(CallContext *ctx)
@@ -831,19 +825,19 @@ ReturnedValue StringPrototype::method_toLocaleUpperCase(CallContext *ctx)
ReturnedValue StringPrototype::method_fromCharCode(CallContext *context)
{
- QString str(context->callData->argc, Qt::Uninitialized);
+ QString str(context->d()->callData->argc, Qt::Uninitialized);
QChar *ch = str.data();
- for (int i = 0; i < context->callData->argc; ++i) {
- *ch = QChar(context->callData->args[i].toUInt16());
+ for (int i = 0; i < context->d()->callData->argc; ++i) {
+ *ch = QChar(context->d()->callData->args[i].toUInt16());
++ch;
}
- return context->engine->newString(str)->asReturnedValue();
+ return context->d()->engine->newString(str)->asReturnedValue();
}
ReturnedValue StringPrototype::method_trim(CallContext *ctx)
{
QString s = getThisString(ctx);
- if (ctx->engine->hasException)
+ if (ctx->d()->engine->hasException)
return Encode::undefined();
const QChar *chars = s.constData();
@@ -857,5 +851,5 @@ ReturnedValue StringPrototype::method_trim(CallContext *ctx)
break;
}
- return ctx->engine->newString(QString(chars + start, end - start + 1))->asReturnedValue();
+ return ctx->d()->engine->newString(QString(chars + start, end - start + 1))->asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4stringobject_p.h b/src/qml/jsruntime/qv4stringobject_p.h
index c38fd5b75f..0fc556f849 100644
--- a/src/qml/jsruntime/qv4stringobject_p.h
+++ b/src/qml/jsruntime/qv4stringobject_p.h
@@ -50,27 +50,32 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
struct StringObject: Object {
- V4_OBJECT
+ struct Data : Object::Data {
+ Data(ExecutionEngine *engine, const ValueRef value);
+ Data(InternalClass *ic);
+ Value value;
+ // ### get rid of tmpProperty
+ mutable Property tmpProperty;
+ };
+ V4_OBJECT(Object)
Q_MANAGED_TYPE(StringObject)
- Value value;
- mutable Property tmpProperty;
- StringObject(ExecutionEngine *engine, const ValueRef value);
Property *getIndex(uint index) const;
static bool deleteIndexedProperty(Managed *m, uint index);
protected:
- StringObject(InternalClass *ic);
- static void advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, Property *p, PropertyAttributes *attrs);
+ static void advanceIterator(Managed *m, ObjectIterator *it, String *&name, uint *index, Property *p, PropertyAttributes *attrs);
static void markObjects(Managed *that, ExecutionEngine *e);
};
struct StringCtor: FunctionObject
{
- V4_OBJECT
- StringCtor(ExecutionContext *scope);
+ struct Data : FunctionObject::Data {
+ Data(ExecutionContext *scope);
+ };
+ V4_OBJECT(FunctionObject)
static ReturnedValue construct(Managed *m, CallData *callData);
static ReturnedValue call(Managed *that, CallData *callData);
@@ -78,8 +83,7 @@ struct StringCtor: FunctionObject
struct StringPrototype: StringObject
{
- StringPrototype(InternalClass *ic): StringObject(ic) {}
- void init(ExecutionEngine *engine, ObjectRef ctor);
+ void init(ExecutionEngine *engine, Object *ctor);
static ReturnedValue method_toString(CallContext *context);
static ReturnedValue method_charAt(CallContext *context);
diff --git a/src/qml/jsruntime/qv4value.cpp b/src/qml/jsruntime/qv4value.cpp
index e9246f7a14..e122b18892 100644
--- a/src/qml/jsruntime/qv4value.cpp
+++ b/src/qml/jsruntime/qv4value.cpp
@@ -95,7 +95,7 @@ double Value::toNumberImpl() const
if (isString())
return RuntimeHelpers::stringToNumber(stringValue()->toQString());
{
- ExecutionContext *ctx = objectValue()->internalClass->engine->currentContext();
+ ExecutionContext *ctx = objectValue()->internalClass()->engine->currentContext();
Scope scope(ctx);
ScopedValue prim(scope, RuntimeHelpers::toPrimitive(ValueRef::fromRawValue(this), NUMBER_HINT));
return prim->toNumber();
@@ -129,7 +129,7 @@ QString Value::toQStringNoThrow() const
if (isString())
return stringValue()->toQString();
{
- ExecutionContext *ctx = objectValue()->internalClass->engine->currentContext();
+ ExecutionContext *ctx = objectValue()->internalClass()->engine->currentContext();
Scope scope(ctx);
ScopedValue ex(scope);
bool caughtException = false;
@@ -182,7 +182,7 @@ QString Value::toQString() const
if (isString())
return stringValue()->toQString();
{
- ExecutionContext *ctx = objectValue()->internalClass->engine->currentContext();
+ ExecutionContext *ctx = objectValue()->internalClass()->engine->currentContext();
Scope scope(ctx);
ScopedValue prim(scope, RuntimeHelpers::toPrimitive(ValueRef::fromRawValue(this), STRING_HINT));
return prim->toQString();
diff --git a/src/qml/jsruntime/qv4value_inl_p.h b/src/qml/jsruntime/qv4value_inl_p.h
index 1fe9e1c165..84a8e1adf2 100644
--- a/src/qml/jsruntime/qv4value_inl_p.h
+++ b/src/qml/jsruntime/qv4value_inl_p.h
@@ -64,13 +64,13 @@ inline bool Value::isString() const
{
if (!isManaged())
return false;
- return managed() && managed()->internalClass->vtable->isString;
+ return managed() && managed()->internalClass()->vtable->isString;
}
inline bool Value::isObject() const
{
if (!isManaged())
return false;
- return managed() && managed()->internalClass->vtable->isObject;
+ return managed() && managed()->internalClass()->vtable->isObject;
}
inline bool Value::isPrimitive() const
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
index 29cb8b42ed..7b49db74d9 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -64,6 +64,8 @@ struct Returned : private T
using T::asReturnedValue;
};
+struct HeapObject {};
+
struct Q_QML_PRIVATE_EXPORT Value
{
/*
@@ -347,6 +349,10 @@ struct Q_QML_PRIVATE_EXPORT Value
val = Value::fromManaged(t).val;
return *this;
}
+ Value &operator=(HeapObject *o) {
+ m = reinterpret_cast<Managed *>(o);
+ return *this;
+ }
template<typename T>
Value &operator=(const Scoped<T> &t);
@@ -430,7 +436,10 @@ struct TypedValue : public Value
{
template<typename X>
TypedValue &operator =(X *x) {
- val = Value::fromManaged(x).val;
+ m = x;
+#if QT_POINTER_SIZE == 4
+ tag = Managed_Type;
+#endif
}
TypedValue &operator =(T *t);
TypedValue &operator =(const Scoped<T> &v);
@@ -441,6 +450,7 @@ struct TypedValue : public Value
bool operator!() const { return !managed(); }
+ operator T *() { return static_cast<T *>(managed()); }
T *operator->() { return static_cast<T *>(managed()); }
const T *operator->() const { return static_cast<T *>(managed()); }
T *getPointer() const { return static_cast<T *>(managed()); }
diff --git a/src/qml/jsruntime/qv4variantobject.cpp b/src/qml/jsruntime/qv4variantobject.cpp
index 92cc19d8b9..a5b22a2de8 100644
--- a/src/qml/jsruntime/qv4variantobject.cpp
+++ b/src/qml/jsruntime/qv4variantobject.cpp
@@ -51,18 +51,15 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(VariantObject);
-VariantObject::VariantObject(InternalClass *ic)
- : Object(ic)
- , ExecutionEngine::ScarceResourceData(QVariant())
- , m_vmePropertyReferenceCount(0)
+VariantObject::Data::Data(InternalClass *ic)
+ : Object::Data(ic)
{
}
-VariantObject::VariantObject(ExecutionEngine *engine, const QVariant &value)
- : Object(engine->variantClass)
- , ExecutionEngine::ScarceResourceData(value)
- , m_vmePropertyReferenceCount(0)
+VariantObject::Data::Data(ExecutionEngine *engine, const QVariant &value)
+ : Object::Data(engine->variantClass)
{
+ data = value;
if (isScarce())
engine->scarceResources.insert(this);
}
@@ -89,7 +86,7 @@ QVariant VariantObject::toVariant(const QV4::ValueRef v)
return QVariant();
}
-bool VariantObject::isScarce() const
+bool VariantObject::Data::isScarce() const
{
QVariant::Type t = data.type();
return t == QVariant::Pixmap || t == QVariant::Image;
@@ -98,9 +95,7 @@ bool VariantObject::isScarce() const
void VariantObject::destroy(Managed *that)
{
VariantObject *v = static_cast<VariantObject *>(that);
- if (v->isScarce())
- v->node.remove();
- v->~VariantObject();
+ v->d()->~Data();
}
bool VariantObject::isEqualTo(Managed *m, Managed *other)
@@ -109,40 +104,35 @@ bool VariantObject::isEqualTo(Managed *m, Managed *other)
assert(lv);
if (QV4::VariantObject *rv = other->as<QV4::VariantObject>())
- return lv->data == rv->data;
+ return lv->d()->data == rv->d()->data;
if (QV4::QmlValueTypeWrapper *v = other->as<QmlValueTypeWrapper>())
- return v->isEqual(lv->data);
+ return v->isEqual(lv->d()->data);
return false;
}
void VariantObject::addVmePropertyReference()
{
- if (isScarce() && ++m_vmePropertyReferenceCount == 1) {
+ if (d()->isScarce() && ++d()->vmePropertyReferenceCount == 1) {
// remove from the ep->scarceResources list
// since it is now no longer eligible to be
// released automatically by the engine.
- node.remove();
+ d()->node.remove();
}
}
void VariantObject::removeVmePropertyReference()
{
- if (isScarce() && --m_vmePropertyReferenceCount == 0) {
+ if (d()->isScarce() && --d()->vmePropertyReferenceCount == 0) {
// and add to the ep->scarceResources list
// since it is now eligible to be released
// automatically by the engine.
- internalClass->engine->scarceResources.insert(this);
+ internalClass()->engine->scarceResources.insert(d());
}
}
-VariantPrototype::VariantPrototype(InternalClass *ic)
- : VariantObject(ic)
-{
-}
-
void VariantPrototype::init()
{
defineDefaultProperty(QStringLiteral("preserve"), method_preserve, 0);
@@ -154,20 +144,20 @@ void VariantPrototype::init()
QV4::ReturnedValue VariantPrototype::method_preserve(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<VariantObject> o(scope, ctx->callData->thisObject.as<QV4::VariantObject>());
- if (o && o->isScarce())
- o->node.remove();
+ Scoped<VariantObject> o(scope, ctx->d()->callData->thisObject.as<QV4::VariantObject>());
+ if (o && o->d()->isScarce())
+ o->d()->node.remove();
return Encode::undefined();
}
QV4::ReturnedValue VariantPrototype::method_destroy(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<VariantObject> o(scope, ctx->callData->thisObject.as<QV4::VariantObject>());
+ Scoped<VariantObject> o(scope, ctx->d()->callData->thisObject.as<QV4::VariantObject>());
if (o) {
- if (o->isScarce())
- o->node.remove();
- o->data = QVariant();
+ if (o->d()->isScarce())
+ o->d()->node.remove();
+ o->d()->data = QVariant();
}
return Encode::undefined();
}
@@ -175,26 +165,26 @@ QV4::ReturnedValue VariantPrototype::method_destroy(CallContext *ctx)
QV4::ReturnedValue VariantPrototype::method_toString(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<VariantObject> o(scope, ctx->callData->thisObject.as<QV4::VariantObject>());
+ Scoped<VariantObject> o(scope, ctx->d()->callData->thisObject.as<QV4::VariantObject>());
if (!o)
return Encode::undefined();
- QString result = o->data.toString();
- if (result.isEmpty() && !o->data.canConvert(QVariant::String))
- result = QString::fromLatin1("QVariant(%0)").arg(QString::fromLatin1(o->data.typeName()));
- return Encode(ctx->engine->newString(result));
+ QString result = o->d()->data.toString();
+ if (result.isEmpty() && !o->d()->data.canConvert(QVariant::String))
+ result = QString::fromLatin1("QVariant(%0)").arg(QString::fromLatin1(o->d()->data.typeName()));
+ return Encode(ctx->d()->engine->newString(result));
}
QV4::ReturnedValue VariantPrototype::method_valueOf(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<VariantObject> o(scope, ctx->callData->thisObject.as<QV4::VariantObject>());
+ Scoped<VariantObject> o(scope, ctx->d()->callData->thisObject.as<QV4::VariantObject>());
if (o) {
- QVariant v = o->data;
+ QVariant v = o->d()->data;
switch (v.type()) {
case QVariant::Invalid:
return Encode::undefined();
case QVariant::String:
- return Encode(ctx->engine->newString(v.toString()));
+ return Encode(ctx->d()->engine->newString(v.toString()));
case QVariant::Int:
return Encode(v.toInt());
case QVariant::Double:
@@ -206,7 +196,7 @@ QV4::ReturnedValue VariantPrototype::method_valueOf(CallContext *ctx)
break;
}
}
- return ctx->callData->thisObject.asReturnedValue();
+ return ctx->d()->callData->thisObject.asReturnedValue();
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4variantobject_p.h b/src/qml/jsruntime/qv4variantobject_p.h
index 656608d49b..18e93f6ca7 100644
--- a/src/qml/jsruntime/qv4variantobject_p.h
+++ b/src/qml/jsruntime/qv4variantobject_p.h
@@ -64,31 +64,33 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
-struct VariantObject : Object, public ExecutionEngine::ScarceResourceData
+struct VariantObject : Object
{
- V4_OBJECT
-public:
- VariantObject(InternalClass *ic);
- VariantObject(ExecutionEngine *engine, const QVariant &value);
+ struct Data : Object::Data, public ExecutionEngine::ScarceResourceData
+ {
+ Data(InternalClass *ic);
+ Data(ExecutionEngine *engine, const QVariant &value);
+ ~Data() {
+ if (isScarce())
+ node.remove();
+ }
+ bool isScarce() const;
+ int vmePropertyReferenceCount;
+ };
+ V4_OBJECT(Object)
static QVariant toVariant(const ValueRef v);
void addVmePropertyReference();
void removeVmePropertyReference();
- bool isScarce() const;
- int m_vmePropertyReferenceCount;
static void destroy(Managed *that);
static bool isEqualTo(Managed *m, Managed *other);
};
-DEFINE_REF(VariantObject, Object);
-
struct VariantPrototype : VariantObject
{
public:
- VariantPrototype(InternalClass *ic);
-
void init();
static ReturnedValue method_preserve(CallContext *ctx);
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index 8e52ed5a96..7f058bf8b7 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -185,14 +185,14 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code
const uchar *exceptionHandler = 0;
- context->lineNumber = -1;
- QV4::ExecutionEngine *engine = context->engine;
+ context->d()->lineNumber = -1;
+ QV4::ExecutionEngine *engine = context->d()->engine;
#ifdef DO_TRACE_INSTR
qDebug("Starting VME with context=%p and code=%p", context, code);
#endif // DO_TRACE_INSTR
- QV4::StringValue * const runtimeStrings = context->compilationUnit->runtimeStrings;
+ QV4::StringValue * const runtimeStrings = context->d()->compilationUnit->runtimeStrings;
// setup lookup scopes
int scopeDepth = 0;
@@ -200,28 +200,28 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code
QV4::ExecutionContext *scope = context;
while (scope) {
++scopeDepth;
- scope = scope->outer;
+ scope = scope->d()->outer;
}
}
QV4::Value **scopes = static_cast<QV4::Value **>(alloca(sizeof(QV4::Value *)*(2 + 2*scopeDepth)));
{
- scopes[0] = const_cast<QV4::Value *>(context->compilationUnit->data->constants());
+ scopes[0] = const_cast<QV4::Value *>(context->d()->compilationUnit->data->constants());
// stack gets setup in push instruction
scopes[1] = 0;
QV4::ExecutionContext *scope = context;
int i = 0;
while (scope) {
- if (scope->type >= QV4::ExecutionContext::Type_SimpleCallContext) {
+ if (scope->d()->type >= QV4::ExecutionContext::Type_SimpleCallContext) {
QV4::CallContext *cc = static_cast<QV4::CallContext *>(scope);
- scopes[2*i + 2] = cc->callData->args;
- scopes[2*i + 3] = cc->locals;
+ scopes[2*i + 2] = cc->d()->callData->args;
+ scopes[2*i + 3] = cc->d()->locals;
} else {
scopes[2*i + 2] = 0;
scopes[2*i + 3] = 0;
}
++i;
- scope = scope->outer;
+ scope = scope->d()->outer;
}
}
@@ -253,7 +253,7 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code
MOTH_BEGIN_INSTR(LoadRegExp)
// TRACE(value, "%s", instr.value.toString(context)->toQString().toUtf8().constData());
- VALUE(instr.result) = context->compilationUnit->runtimeRegularExpressions[instr.regExpId];
+ VALUE(instr.result) = context->d()->compilationUnit->runtimeRegularExpressions[instr.regExpId];
MOTH_END_INSTR(LoadRegExp)
MOTH_BEGIN_INSTR(LoadClosure)
@@ -267,7 +267,7 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code
MOTH_BEGIN_INSTR(GetGlobalLookup)
TRACE(inline, "property name = %s", runtimeStrings[instr.name]->toQString().toUtf8().constData());
- QV4::Lookup *l = context->lookups + instr.index;
+ QV4::Lookup *l = context->d()->lookups + instr.index;
STOREVALUE(instr.result, l->globalGetter(l, context));
MOTH_END_INSTR(GetGlobalLookup)
@@ -282,7 +282,7 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code
MOTH_END_INSTR(LoadElement)
MOTH_BEGIN_INSTR(LoadElementLookup)
- QV4::Lookup *l = context->lookups + instr.lookup;
+ QV4::Lookup *l = context->d()->lookups + instr.lookup;
STOREVALUE(instr.result, l->indexedGetter(l, VALUEPTR(instr.base), VALUEPTR(instr.index)));
MOTH_END_INSTR(LoadElementLookup)
@@ -292,7 +292,7 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code
MOTH_END_INSTR(StoreElement)
MOTH_BEGIN_INSTR(StoreElementLookup)
- QV4::Lookup *l = context->lookups + instr.lookup;
+ QV4::Lookup *l = context->d()->lookups + instr.lookup;
l->indexedSetter(l, VALUEPTR(instr.base), VALUEPTR(instr.index), VALUEPTR(instr.source));
CHECK_EXCEPTION;
MOTH_END_INSTR(StoreElementLookup)
@@ -302,7 +302,7 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code
MOTH_END_INSTR(LoadProperty)
MOTH_BEGIN_INSTR(GetLookup)
- QV4::Lookup *l = context->lookups + instr.index;
+ QV4::Lookup *l = context->d()->lookups + instr.index;
STOREVALUE(instr.result, l->getter(l, VALUEPTR(instr.base)));
MOTH_END_INSTR(GetLookup)
@@ -312,7 +312,7 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code
MOTH_END_INSTR(StoreProperty)
MOTH_BEGIN_INSTR(SetLookup)
- QV4::Lookup *l = context->lookups + instr.index;
+ QV4::Lookup *l = context->d()->lookups + instr.index;
l->setter(l, VALUEPTR(instr.base), VALUEPTR(instr.source));
CHECK_EXCEPTION;
MOTH_END_INSTR(SetLookup)
@@ -333,7 +333,7 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code
MOTH_BEGIN_INSTR(Push)
TRACE(inline, "stack size: %u", instr.value);
stackSize = instr.value;
- stack = context->engine->stackPush(stackSize);
+ stack = context->engine()->stackPush(stackSize);
#ifndef QT_NO_DEBUG
memset(stack, 0, stackSize * sizeof(QV4::Value));
#endif
@@ -342,7 +342,7 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code
MOTH_BEGIN_INSTR(CallValue)
#if 0 //def DO_TRACE_INSTR
- if (Debugging::Debugger *debugger = context->engine->debugger) {
+ if (Debugging::Debugger *debugger = context->engine()->debugger) {
if (QV4::FunctionObject *o = (VALUE(instr.dest)).asFunctionObject()) {
if (Debugging::FunctionDebugInfo *info = debugger->debugInfo(o)) {
QString n = debugger->name(o);
@@ -655,24 +655,24 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code
MOTH_END_INSTR(BinopContext)
MOTH_BEGIN_INSTR(Ret)
- context->engine->stackPop(stackSize);
+ context->engine()->stackPop(stackSize);
// TRACE(Ret, "returning value %s", result.toString(context)->toQString().toUtf8().constData());
return VALUE(instr.result).asReturnedValue();
MOTH_END_INSTR(Ret)
MOTH_BEGIN_INSTR(Debug)
- context->lineNumber = instr.lineNumber;
- QV4::Debugging::Debugger *debugger = context->engine->debugger;
+ context->d()->lineNumber = instr.lineNumber;
+ QV4::Debugging::Debugger *debugger = context->engine()->debugger;
if (debugger && debugger->pauseAtNextOpportunity())
debugger->maybeBreakAtInstruction();
MOTH_END_INSTR(Debug)
MOTH_BEGIN_INSTR(Line)
- context->lineNumber = instr.lineNumber;
+ context->d()->lineNumber = instr.lineNumber;
MOTH_END_INSTR(Debug)
MOTH_BEGIN_INSTR(LoadThis)
- VALUE(instr.result) = context->callData->thisObject;
+ VALUE(instr.result) = context->d()->callData->thisObject;
MOTH_END_INSTR(LoadThis)
MOTH_BEGIN_INSTR(LoadQmlIdArray)
@@ -706,9 +706,9 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code
Q_ASSERT(false);
catchException:
- Q_ASSERT(context->engine->hasException);
+ Q_ASSERT(context->engine()->hasException);
if (!exceptionHandler) {
- context->engine->stackPop(stackSize);
+ context->engine()->stackPop(stackSize);
return QV4::Encode::undefined();
}
code = exceptionHandler;
@@ -732,7 +732,7 @@ void **VME::instructionJumpTable()
QV4::ReturnedValue VME::exec(QV4::ExecutionContext *ctxt, const uchar *code)
{
VME vme;
- QV4::Debugging::Debugger *debugger = ctxt->engine->debugger;
+ QV4::Debugging::Debugger *debugger = ctxt->engine()->debugger;
if (debugger)
debugger->enteringFunction();
QV4::ReturnedValue retVal = vme.run(ctxt, code);
diff --git a/src/qml/qml/ftw/qhashedstring_p.h b/src/qml/qml/ftw/qhashedstring_p.h
index 61a492013d..57217a6bf8 100644
--- a/src/qml/qml/ftw/qhashedstring_p.h
+++ b/src/qml/qml/ftw/qhashedstring_p.h
@@ -245,7 +245,7 @@ public:
}
inline bool equals(const QV4::String *string) const {
- if (length != string->length() || hash != string->hashValue())
+ if (length != string->d()->length() || hash != string->hashValue())
return false;
if (isQString()) {
QStringDataPtr dd;
diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h
index 721f2cc5a8..86cb395c3d 100644
--- a/src/qml/qml/qqml.h
+++ b/src/qml/qml/qqml.h
@@ -198,6 +198,44 @@ int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMin
return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type);
}
+template<typename T, typename E>
+int qmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString& reason)
+{
+ QML_GETTYPENAMES
+
+ QQmlAttachedPropertiesFunc attached = QQmlPrivate::attachedPropertiesFunc<E>();
+ const QMetaObject * attachedMetaObject = QQmlPrivate::attachedPropertiesMetaObject<E>();
+ if (!attached) {
+ attached = QQmlPrivate::attachedPropertiesFunc<T>();
+ attachedMetaObject = QQmlPrivate::attachedPropertiesMetaObject<T>();
+ }
+
+ QQmlPrivate::RegisterType type = {
+ 0,
+
+ qRegisterNormalizedMetaType<T *>(pointerName.constData()),
+ qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
+ 0, 0,
+ reason,
+
+ uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject,
+
+ attached,
+ attachedMetaObject,
+
+ QQmlPrivate::StaticCastSelector<T,QQmlParserStatus>::cast(),
+ QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueSource>::cast(),
+ QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueInterceptor>::cast(),
+
+ QQmlPrivate::createParent<E>, &E::staticMetaObject,
+
+ 0,
+ 0
+ };
+
+ return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type);
+}
+
template<typename T>
int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName)
{
@@ -414,6 +452,45 @@ int qmlRegisterCustomType(const char *uri, int versionMajor, int versionMinor,
return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type);
}
+template<typename T, typename E>
+int qmlRegisterCustomExtendedType(const char *uri, int versionMajor, int versionMinor,
+ const char *qmlName, QQmlCustomParser *parser)
+{
+ QML_GETTYPENAMES
+
+ QQmlAttachedPropertiesFunc attached = QQmlPrivate::attachedPropertiesFunc<E>();
+ const QMetaObject * attachedMetaObject = QQmlPrivate::attachedPropertiesMetaObject<E>();
+ if (!attached) {
+ attached = QQmlPrivate::attachedPropertiesFunc<T>();
+ attachedMetaObject = QQmlPrivate::attachedPropertiesMetaObject<T>();
+ }
+
+ QQmlPrivate::RegisterType type = {
+ 0,
+
+ qRegisterNormalizedMetaType<T *>(pointerName.constData()),
+ qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
+ sizeof(T), QQmlPrivate::createInto<T>,
+ QString(),
+
+ uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject,
+
+ attached,
+ attachedMetaObject,
+
+ QQmlPrivate::StaticCastSelector<T,QQmlParserStatus>::cast(),
+ QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueSource>::cast(),
+ QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueInterceptor>::cast(),
+
+ QQmlPrivate::createParent<E>, &E::staticMetaObject,
+
+ parser,
+ 0
+ };
+
+ return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type);
+}
+
class QQmlContext;
class QQmlEngine;
class QJSValue;
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp
index 571d78312e..1ba7a8091d 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -71,34 +71,6 @@ QQmlAbstractBinding::VTable QQmlBinding_vtable = {
QQmlBinding::Identifier QQmlBinding::Invalid = -1;
-QQmlBinding *
-QQmlBinding::createBinding(Identifier id, QObject *obj, QQmlContext *ctxt)
-{
- if (id < 0)
- return 0;
-
- QQmlBinding *rv = 0;
-
- QQmlContextData *ctxtdata = QQmlContextData::get(ctxt);
- QQmlEnginePrivate *engine = QQmlEnginePrivate::get(ctxt->engine());
- if (engine && ctxtdata && !ctxtdata->url.isEmpty()) {
- QQmlTypeData *typeData = engine->typeLoader.getType(ctxtdata->url);
- Q_ASSERT(typeData);
-
- if (QQmlCompiledData *cdata = typeData->compiledData()) {
- QV4::ExecutionEngine *v4 = engine->v4engine();
- QV4::Scope valueScope(v4);
- QV4::Function *runtimeFunction = cdata->compilationUnit->runtimeFunctions[cdata->customParserBindings[id]];
- QV4::ScopedValue function(valueScope, QV4::QmlBindingWrapper::createQmlCallableForFunction(ctxtdata, obj, runtimeFunction));
- rv = new QQmlBinding(function, obj, ctxtdata);
- }
-
- typeData->release();
- }
-
- return rv;
-}
-
static QQmlJavaScriptExpression::VTable QQmlBinding_jsvtable = {
QQmlBinding::expressionIdentifier,
QQmlBinding::expressionChanged
@@ -134,7 +106,7 @@ QQmlBinding::QQmlBinding(const QQmlScriptString &script, QObject *obj, QQmlConte
Q_ASSERT(typeData);
if (QQmlCompiledData *cdata = typeData->compiledData()) {
- url = cdata->name;
+ url = cdata->fileName();
if (scriptPrivate->bindingId != QQmlBinding::Invalid)
runtimeFunction = cdata->compilationUnit->runtimeFunctions.at(scriptPrivate->bindingId);
}
@@ -213,13 +185,13 @@ void QQmlBinding::update(QQmlPropertyPrivate::WriteFlags flags)
QV4::Scope scope(ep->v4engine());
QV4::ScopedFunctionObject f(scope, v4function.value());
Q_ASSERT(f);
- if (f->bindingKeyFlag) {
- QQmlSourceLocation loc = f->as<QV4::QQmlBindingFunction>()->bindingLocation;
+ if (f->bindingKeyFlag()) {
+ QQmlSourceLocation loc = f->as<QV4::QQmlBindingFunction>()->d()->bindingLocation;
url = loc.sourceFile;
lineNumber = loc.line;
columnNumber = loc.column;
} else {
- QV4::Function *function = f->asFunctionObject()->function;
+ QV4::Function *function = f->asFunctionObject()->function();
Q_ASSERT(function);
url = function->sourceFile();
@@ -312,7 +284,7 @@ QString QQmlBinding::expressionIdentifier(QQmlJavaScriptExpression *e)
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(This->context()->engine);
QV4::Scope scope(ep->v4engine());
QV4::ScopedValue f(scope, This->v4function.value());
- QV4::Function *function = f->asFunctionObject()->function;
+ QV4::Function *function = f->asFunctionObject()->function();
QString url = function->sourceFile();
quint16 lineNumber = function->compiledFunction->location.line;
diff --git a/src/qml/qml/qqmlbinding_p.h b/src/qml/qml/qqmlbinding_p.h
index 3c2c832e0c..879129fe85 100644
--- a/src/qml/qml/qqmlbinding_p.h
+++ b/src/qml/qml/qqmlbinding_p.h
@@ -112,8 +112,6 @@ public:
typedef int Identifier;
static Identifier Invalid;
- static QQmlBinding *createBinding(Identifier, QObject *, QQmlContext *);
-
QVariant evaluate();
static QString expressionIdentifier(QQmlJavaScriptExpression *);
diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp
index 876f367097..cec5c31898 100644
--- a/src/qml/qml/qqmlboundsignal.cpp
+++ b/src/qml/qml/qqmlboundsignal.cpp
@@ -190,7 +190,7 @@ QV4::Function *QQmlBoundSignalExpression::function() const
Q_ASSERT (context() && engine());
QV4::Scope scope(QQmlEnginePrivate::get(engine())->v4engine());
QV4::Scoped<QV4::FunctionObject> v(scope, m_v8function.value());
- return v ? v->function : 0;
+ return v ? v->function() : 0;
}
return 0;
}
diff --git a/src/qml/qml/qqmlcompiler_p.h b/src/qml/qml/qqmlcompiler_p.h
index f3b6f621ce..129d312ad1 100644
--- a/src/qml/qml/qqmlcompiler_p.h
+++ b/src/qml/qml/qqmlcompiler_p.h
@@ -91,8 +91,8 @@ public:
QQmlEngine *engine;
- QString name;
- QUrl url;
+ QString fileName() const { return compilationUnit->fileName(); }
+ QUrl url() const { return QUrl(fileName()); }
QQmlTypeNameCache *importCache;
int metaTypeId;
@@ -136,13 +136,8 @@ public:
// index in first hash is component index, hash inside maps from object index in that scope to integer id
QHash<int, QHash<int, int> > objectIndexToIdPerComponent;
QHash<int, int> objectIndexToIdForRoot;
- // hash key is object index
- struct CustomParserData {
- QByteArray compilationArtifact; // produced by custom parser
- QBitArray bindings; // bindings covered by the custom parser
- };
- QHash<int, CustomParserData> customParserData;
- QVector<int> customParserBindings; // index is binding identifier, value is compiled function index.
+ // hash key is object index, value is indicies of bindings covered by custom parser
+ QHash<int, QBitArray> customParserBindings;
QHash<int, QBitArray> deferredBindingsPerObject; // index is object index
int totalBindingsCount; // Number of bindings used in this type
int totalParserStatusCount; // Number of instantiated types that are QQmlParserStatus subclasses
@@ -154,9 +149,6 @@ public:
bool isInitialized() const { return hasEngine(); }
void initialize(QQmlEngine *);
- QV4::Function *functionForBindingId(int bindingId) const
- { return compilationUnit->runtimeFunctions[customParserBindings[bindingId]]; }
-
protected:
virtual void destroy(); // From QQmlRefCount
virtual void clear(); // From QQmlCleanup
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 68f950d840..616f54d174 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -592,7 +592,7 @@ QQmlComponent::QQmlComponent(QQmlEngine *engine, QQmlCompiledData *cc, int start
d->cc = cc;
cc->addref();
d->start = start;
- d->url = cc->url;
+ d->url = cc->url();
d->progress = 1.0;
}
@@ -1079,11 +1079,18 @@ void QQmlComponent::create(QQmlIncubator &incubator, QQmlContext *context,
class QQmlComponentIncubator;
-class QmlIncubatorObject : public QV4::Object
+struct QmlIncubatorObject : public QV4::Object
{
- V4_OBJECT
-public:
- QmlIncubatorObject(QV8Engine *engine, QQmlIncubator::IncubationMode = QQmlIncubator::Asynchronous);
+ struct Data : QV4::Object::Data {
+ Data(QV8Engine *engine, QQmlIncubator::IncubationMode = QQmlIncubator::Asynchronous);
+ QScopedPointer<QQmlComponentIncubator> incubator;
+ QV8Engine *v8;
+ QPointer<QObject> parent;
+ QV4::Value valuemap;
+ QV4::Value qmlGlobal;
+ QV4::Value statusChanged;
+ };
+ V4_OBJECT(QV4::Object)
static QV4::ReturnedValue method_get_statusChanged(QV4::CallContext *ctx);
static QV4::ReturnedValue method_set_statusChanged(QV4::CallContext *ctx);
@@ -1094,13 +1101,6 @@ public:
static void destroy(Managed *that);
static void markObjects(Managed *that, QV4::ExecutionEngine *e);
- QScopedPointer<QQmlComponentIncubator> incubator;
- QV8Engine *v8;
- QPointer<QObject> parent;
- QV4::Value valuemap;
- QV4::Value qmlGlobal;
- QV4::Value m_statusChanged;
-
void statusChanged(QQmlIncubator::Status);
void setInitialState(QObject *);
};
@@ -1110,20 +1110,24 @@ DEFINE_OBJECT_VTABLE(QmlIncubatorObject);
class QQmlComponentIncubator : public QQmlIncubator
{
public:
- QQmlComponentIncubator(QmlIncubatorObject *inc, IncubationMode mode)
+ QQmlComponentIncubator(QmlIncubatorObject::Data *inc, IncubationMode mode)
: QQmlIncubator(mode)
, incubatorObject(inc)
{}
virtual void statusChanged(Status s) {
- incubatorObject->statusChanged(s);
+ QV4::Scope scope(incubatorObject->internalClass->engine);
+ QV4::Scoped<QmlIncubatorObject> i(scope, incubatorObject);
+ i->statusChanged(s);
}
virtual void setInitialState(QObject *o) {
- incubatorObject->setInitialState(o);
+ QV4::Scope scope(incubatorObject->internalClass->engine);
+ QV4::Scoped<QmlIncubatorObject> i(scope, incubatorObject);
+ i->setInitialState(o);
}
- QmlIncubatorObject *incubatorObject;
+ QmlIncubatorObject::Data *incubatorObject;
};
@@ -1359,17 +1363,17 @@ void QQmlComponent::incubateObject(QQmlV4Function *args)
QQmlComponentExtension *e = componentExtension(args->engine());
- QV4::Scoped<QmlIncubatorObject> r(scope, new (v4->memoryManager) QmlIncubatorObject(args->engine(), mode));
+ QV4::Scoped<QmlIncubatorObject> r(scope, v4->memoryManager->alloc<QmlIncubatorObject>(args->engine(), mode));
QV4::ScopedObject p(scope, e->incubationProto.value());
r->setPrototype(p.getPointer());
if (!valuemap->isUndefined()) {
- r->valuemap = valuemap;
- r->qmlGlobal = args->qmlGlobal();
+ r->d()->valuemap = valuemap;
+ r->d()->qmlGlobal = args->qmlGlobal();
}
- r->parent = parent;
+ r->d()->parent = parent;
- QQmlIncubator *incubator = r.getPointer()->incubator.data();
+ QQmlIncubator *incubator = r.getPointer()->d()->incubator.data();
create(*incubator, creationContext());
if (incubator->status() == QQmlIncubator::Null) {
@@ -1419,21 +1423,21 @@ QQmlComponentExtension::QQmlComponentExtension(QV8Engine *engine)
QV4::ReturnedValue QmlIncubatorObject::method_get_object(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
- QV4::Scoped<QmlIncubatorObject> o(scope, ctx->callData->thisObject.as<QmlIncubatorObject>());
+ QV4::Scoped<QmlIncubatorObject> o(scope, ctx->d()->callData->thisObject.as<QmlIncubatorObject>());
if (!o)
return ctx->throwTypeError();
- return QV4::QObjectWrapper::wrap(ctx->engine, o->incubator->object());
+ return QV4::QObjectWrapper::wrap(ctx->d()->engine, o->d()->incubator->object());
}
QV4::ReturnedValue QmlIncubatorObject::method_forceCompletion(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
- QV4::Scoped<QmlIncubatorObject> o(scope, ctx->callData->thisObject.as<QmlIncubatorObject>());
+ QV4::Scoped<QmlIncubatorObject> o(scope, ctx->d()->callData->thisObject.as<QmlIncubatorObject>());
if (!o)
return ctx->throwTypeError();
- o->incubator->forceCompletion();
+ o->d()->incubator->forceCompletion();
return QV4::Encode::undefined();
}
@@ -1441,32 +1445,32 @@ QV4::ReturnedValue QmlIncubatorObject::method_forceCompletion(QV4::CallContext *
QV4::ReturnedValue QmlIncubatorObject::method_get_status(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
- QV4::Scoped<QmlIncubatorObject> o(scope, ctx->callData->thisObject.as<QmlIncubatorObject>());
+ QV4::Scoped<QmlIncubatorObject> o(scope, ctx->d()->callData->thisObject.as<QmlIncubatorObject>());
if (!o)
return ctx->throwTypeError();
- return QV4::Encode(o->incubator->status());
+ return QV4::Encode(o->d()->incubator->status());
}
QV4::ReturnedValue QmlIncubatorObject::method_get_statusChanged(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
- QV4::Scoped<QmlIncubatorObject> o(scope, ctx->callData->thisObject.as<QmlIncubatorObject>());
+ QV4::Scoped<QmlIncubatorObject> o(scope, ctx->d()->callData->thisObject.as<QmlIncubatorObject>());
if (!o)
return ctx->throwTypeError();
- return o->m_statusChanged.asReturnedValue();
+ return o->d()->statusChanged.asReturnedValue();
}
QV4::ReturnedValue QmlIncubatorObject::method_set_statusChanged(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
- QV4::Scoped<QmlIncubatorObject> o(scope, ctx->callData->thisObject.as<QmlIncubatorObject>());
- if (!o || ctx->callData->argc < 1)
+ QV4::Scoped<QmlIncubatorObject> o(scope, ctx->d()->callData->thisObject.as<QmlIncubatorObject>());
+ if (!o || ctx->d()->callData->argc < 1)
return ctx->throwTypeError();
- o->m_statusChanged = ctx->callData->args[0];
+ o->d()->statusChanged = ctx->d()->callData->args[0];
return QV4::Encode::undefined();
}
@@ -1474,65 +1478,63 @@ QQmlComponentExtension::~QQmlComponentExtension()
{
}
-QmlIncubatorObject::QmlIncubatorObject(QV8Engine *engine, QQmlIncubator::IncubationMode m)
- : Object(QV8Engine::getV4(engine))
+QmlIncubatorObject::Data::Data(QV8Engine *engine, QQmlIncubator::IncubationMode m)
+ : Object::Data(QV8Engine::getV4(engine))
+ , v8(engine)
+ , valuemap(QV4::Primitive::undefinedValue())
+ , qmlGlobal(QV4::Primitive::undefinedValue())
+ , statusChanged(QV4::Primitive::undefinedValue())
{
- incubator.reset(new QQmlComponentIncubator(this, m));
- v8 = engine;
setVTable(staticVTable());
- valuemap = QV4::Primitive::undefinedValue();
- qmlGlobal = QV4::Primitive::undefinedValue();
- m_statusChanged = QV4::Primitive::undefinedValue();
+ incubator.reset(new QQmlComponentIncubator(this, m));
}
void QmlIncubatorObject::setInitialState(QObject *o)
{
- QQmlComponent_setQmlParent(o, parent);
+ QQmlComponent_setQmlParent(o, d()->parent);
- if (!valuemap.isUndefined()) {
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(v8);
+ if (!d()->valuemap.isUndefined()) {
+ QV4::ExecutionEngine *v4 = QV8Engine::getV4(d()->v8);
QV4::Scope scope(v4);
- QV4::Scoped<QV4::FunctionObject> f(scope, QV4::Script::evaluate(v4, QString::fromLatin1(INITIALPROPERTIES_SOURCE), qmlGlobal));
+ QV4::Scoped<QV4::FunctionObject> f(scope, QV4::Script::evaluate(v4, QString::fromLatin1(INITIALPROPERTIES_SOURCE), d()->qmlGlobal.asObject()));
QV4::ScopedCallData callData(scope, 2);
callData->thisObject = v4->globalObject;
callData->args[0] = QV4::QObjectWrapper::wrap(v4, o);
- callData->args[1] = valuemap;
+ callData->args[1] = d()->valuemap;
f->call(callData);
}
}
void QmlIncubatorObject::destroy(Managed *that)
{
- QmlIncubatorObject *o = that->as<QmlIncubatorObject>();
- Q_ASSERT(o);
- o->~QmlIncubatorObject();
+ that->as<QmlIncubatorObject>()->d()->~Data();
}
void QmlIncubatorObject::markObjects(QV4::Managed *that, QV4::ExecutionEngine *e)
{
QmlIncubatorObject *o = that->as<QmlIncubatorObject>();
Q_ASSERT(o);
- o->valuemap.mark(e);
- o->qmlGlobal.mark(e);
- o->m_statusChanged.mark(e);
+ o->d()->valuemap.mark(e);
+ o->d()->qmlGlobal.mark(e);
+ o->d()->statusChanged.mark(e);
Object::markObjects(that, e);
}
void QmlIncubatorObject::statusChanged(QQmlIncubator::Status s)
{
- QV4::Scope scope(QV8Engine::getV4(v8));
+ QV4::Scope scope(QV8Engine::getV4(d()->v8));
// hold the incubated object in a scoped value to prevent it's destruction before this method returns
- QV4::ScopedObject incubatedObject(scope, QV4::QObjectWrapper::wrap(scope.engine, incubator->object()));
+ QV4::ScopedObject incubatedObject(scope, QV4::QObjectWrapper::wrap(scope.engine, d()->incubator->object()));
if (s == QQmlIncubator::Ready) {
- Q_ASSERT(QQmlData::get(incubator->object()));
- QQmlData::get(incubator->object())->explicitIndestructibleSet = false;
- QQmlData::get(incubator->object())->indestructible = false;
+ Q_ASSERT(QQmlData::get(d()->incubator->object()));
+ QQmlData::get(d()->incubator->object())->explicitIndestructibleSet = false;
+ QQmlData::get(d()->incubator->object())->indestructible = false;
}
- QV4::ScopedFunctionObject f(scope, m_statusChanged);
+ QV4::ScopedFunctionObject f(scope, d()->statusChanged);
if (f) {
QV4::ExecutionContext *ctx = scope.engine->currentContext();
QV4::ScopedCallData callData(scope, 1);
@@ -1542,7 +1544,7 @@ void QmlIncubatorObject::statusChanged(QQmlIncubator::Status s)
if (scope.hasException()) {
ctx->catchException();
QQmlError error = QV4::ExecutionEngine::catchExceptionAsQmlError(ctx);
- QQmlEnginePrivate::warning(QQmlEnginePrivate::get(v8->engine()), error);
+ QQmlEnginePrivate::warning(QQmlEnginePrivate::get(d()->v8->engine()), error);
}
}
}
diff --git a/src/qml/qml/qqmlcontextwrapper.cpp b/src/qml/qml/qqmlcontextwrapper.cpp
index a5574b706a..83ef8c6230 100644
--- a/src/qml/qml/qqmlcontextwrapper.cpp
+++ b/src/qml/qml/qqmlcontextwrapper.cpp
@@ -61,15 +61,18 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(QmlContextWrapper);
-QmlContextWrapper::QmlContextWrapper(QV8Engine *engine, QQmlContextData *context, QObject *scopeObject, bool ownsContext)
- : Object(QV8Engine::getV4(engine)),
- readOnly(true), ownsContext(ownsContext), isNullWrapper(false),
- context(context), scopeObject(scopeObject), idObjectsWrapper(0)
+QmlContextWrapper::Data::Data(QV8Engine *engine, QQmlContextData *context, QObject *scopeObject, bool ownsContext)
+ : Object::Data(QV8Engine::getV4(engine))
+ , readOnly(true)
+ , ownsContext(ownsContext)
+ , isNullWrapper(false)
+ , context(context)
+ , scopeObject(scopeObject)
{
setVTable(staticVTable());
}
-QmlContextWrapper::~QmlContextWrapper()
+QmlContextWrapper::Data::~Data()
{
if (context && ownsContext)
context->destroy();
@@ -80,7 +83,7 @@ ReturnedValue QmlContextWrapper::qmlScope(QV8Engine *v8, QQmlContextData *ctxt,
ExecutionEngine *v4 = QV8Engine::getV4(v8);
Scope valueScope(v4);
- Scoped<QmlContextWrapper> w(valueScope, new (v4->memoryManager) QmlContextWrapper(v8, ctxt, scope));
+ Scoped<QmlContextWrapper> w(valueScope, v4->memoryManager->alloc<QmlContextWrapper>(v8, ctxt, scope));
return w.asReturnedValue();
}
@@ -94,8 +97,8 @@ ReturnedValue QmlContextWrapper::urlScope(QV8Engine *v8, const QUrl &url)
context->isInternal = true;
context->isJSContext = true;
- Scoped<QmlContextWrapper> w(scope, new (v4->memoryManager) QmlContextWrapper(v8, context, 0, true));
- w->isNullWrapper = true;
+ Scoped<QmlContextWrapper> w(scope, v4->memoryManager->alloc<QmlContextWrapper>(v8, context, (QObject*)0, true));
+ w->d()->isNullWrapper = true;
return w.asReturnedValue();
}
@@ -127,11 +130,11 @@ void QmlContextWrapper::takeContextOwnership(const ValueRef qmlglobal)
Scope scope(v4);
QV4::Scoped<QmlContextWrapper> c(scope, qmlglobal);
Q_ASSERT(c);
- c->ownsContext = true;
+ c->d()->ownsContext = true;
}
-ReturnedValue QmlContextWrapper::get(Managed *m, const StringRef name, bool *hasProperty)
+ReturnedValue QmlContextWrapper::get(Managed *m, String *name, bool *hasProperty)
{
QV4::ExecutionEngine *v4 = m->engine();
QV4::Scope scope(v4);
@@ -149,10 +152,10 @@ ReturnedValue QmlContextWrapper::get(Managed *m, const StringRef name, bool *has
return result.asReturnedValue();
}
- if (resource->isNullWrapper)
+ if (resource->d()->isNullWrapper)
return Object::get(m, name, hasProperty);
- if (QV4::QmlContextWrapper::callingContext(v4) != resource->context)
+ if (QV4::QmlContextWrapper::callingContext(v4) != resource->d()->context)
return Object::get(m, name, hasProperty);
result = Object::get(m, name, &hasProp);
@@ -211,7 +214,7 @@ ReturnedValue QmlContextWrapper::get(Managed *m, const StringRef name, bool *has
while (context) {
// Search context properties
if (context->propertyNames.count()) {
- int propertyIdx = context->propertyNames.value(name.getPointer());
+ int propertyIdx = context->propertyNames.value(name);
if (propertyIdx != -1) {
@@ -247,7 +250,7 @@ ReturnedValue QmlContextWrapper::get(Managed *m, const StringRef name, bool *has
if (scopeObject) {
bool hasProp = false;
QV4::ScopedValue result(scope, QV4::QObjectWrapper::getQmlProperty(v4->currentContext(), context, scopeObject,
- name.getPointer(), QV4::QObjectWrapper::CheckRevision, &hasProp));
+ name, QV4::QObjectWrapper::CheckRevision, &hasProp));
if (hasProp) {
if (hasProperty)
*hasProperty = true;
@@ -260,7 +263,7 @@ ReturnedValue QmlContextWrapper::get(Managed *m, const StringRef name, bool *has
// Search context object
if (context->contextObject) {
bool hasProp = false;
- result = QV4::QObjectWrapper::getQmlProperty(v4->currentContext(), context, context->contextObject, name.getPointer(), QV4::QObjectWrapper::CheckRevision, &hasProp);
+ result = QV4::QObjectWrapper::getQmlProperty(v4->currentContext(), context, context->contextObject, name, QV4::QObjectWrapper::CheckRevision, &hasProp);
if (hasProp) {
if (hasProperty)
*hasProperty = true;
@@ -276,7 +279,7 @@ ReturnedValue QmlContextWrapper::get(Managed *m, const StringRef name, bool *has
return Primitive::undefinedValue().asReturnedValue();
}
-void QmlContextWrapper::put(Managed *m, const StringRef name, const ValueRef value)
+void QmlContextWrapper::put(Managed *m, String *name, const ValueRef value)
{
ExecutionEngine *v4 = m->engine();
QV4::Scope scope(v4);
@@ -295,11 +298,11 @@ void QmlContextWrapper::put(Managed *m, const StringRef name, const ValueRef val
return;
}
- if (wrapper->isNullWrapper) {
- if (wrapper && wrapper->readOnly) {
+ if (wrapper->d()->isNullWrapper) {
+ if (wrapper && wrapper->d()->readOnly) {
QString error = QLatin1String("Invalid write to global property \"") + name->toQString() +
QLatin1Char('"');
- Scoped<String> e(scope, v4->currentContext()->engine->newString(error));
+ Scoped<String> e(scope, v4->currentContext()->d()->engine->newString(error));
v4->currentContext()->throwError(e);
return;
}
@@ -322,18 +325,18 @@ void QmlContextWrapper::put(Managed *m, const StringRef name, const ValueRef val
while (context) {
// Search context properties
- if (context->propertyNames.count() && -1 != context->propertyNames.value(name.getPointer()))
+ if (context->propertyNames.count() && -1 != context->propertyNames.value(name))
return;
// Search scope object
if (scopeObject &&
- QV4::QObjectWrapper::setQmlProperty(v4->currentContext(), context, scopeObject, name.getPointer(), QV4::QObjectWrapper::CheckRevision, value))
+ QV4::QObjectWrapper::setQmlProperty(v4->currentContext(), context, scopeObject, name, QV4::QObjectWrapper::CheckRevision, value))
return;
scopeObject = 0;
// Search context object
if (context->contextObject &&
- QV4::QObjectWrapper::setQmlProperty(v4->currentContext(), context, context->contextObject, name.getPointer(), QV4::QObjectWrapper::CheckRevision, value))
+ QV4::QObjectWrapper::setQmlProperty(v4->currentContext(), context, context->contextObject, name, QV4::QObjectWrapper::CheckRevision, value))
return;
context = context->parent;
@@ -341,7 +344,7 @@ void QmlContextWrapper::put(Managed *m, const StringRef name, const ValueRef val
expressionContext->unresolvedNames = true;
- if (wrapper->readOnly) {
+ if (wrapper->d()->readOnly) {
QString error = QLatin1String("Invalid write to global property \"") + name->toQString() +
QLatin1Char('"');
v4->currentContext()->throwError(error);
@@ -353,14 +356,14 @@ void QmlContextWrapper::put(Managed *m, const StringRef name, const ValueRef val
void QmlContextWrapper::destroy(Managed *that)
{
- static_cast<QmlContextWrapper *>(that)->~QmlContextWrapper();
+ static_cast<QmlContextWrapper *>(that)->d()->~Data();
}
void QmlContextWrapper::markObjects(Managed *m, ExecutionEngine *engine)
{
QmlContextWrapper *This = static_cast<QmlContextWrapper*>(m);
- if (This->idObjectsWrapper)
- This->idObjectsWrapper->mark(engine);
+ if (This->d()->idObjectsWrapper)
+ This->d()->idObjectsWrapper->mark(engine);
Object::markObjects(m, engine);
}
@@ -409,19 +412,21 @@ void QmlContextWrapper::registerQmlDependencies(ExecutionEngine *engine, const C
ReturnedValue QmlContextWrapper::idObjectsArray()
{
- if (!idObjectsWrapper) {
+ if (!d()->idObjectsWrapper) {
ExecutionEngine *v4 = engine();
- idObjectsWrapper = new (v4->memoryManager) QQmlIdObjectsArray(v4, this);
+ Scope scope(v4);
+ Scoped<QQmlIdObjectsArray> a(scope, v4->memoryManager->alloc<QQmlIdObjectsArray>(v4, this));
+ d()->idObjectsWrapper = a.getPointer();
}
- return idObjectsWrapper->asReturnedValue();
+ return d()->idObjectsWrapper->asReturnedValue();
}
-ReturnedValue QmlContextWrapper::qmlSingletonWrapper(QV8Engine *v8, const StringRef &name)
+ReturnedValue QmlContextWrapper::qmlSingletonWrapper(QV8Engine *v8, String *name)
{
- if (!context->imports)
+ if (!d()->context->imports)
return Encode::undefined();
// Search for attached properties, enums and imported scripts
- QQmlTypeNameCache::Result r = context->imports->query(name);
+ QQmlTypeNameCache::Result r = d()->context->imports->query(name);
Q_ASSERT(r.isValid());
Q_ASSERT(r.type);
@@ -439,8 +444,8 @@ ReturnedValue QmlContextWrapper::qmlSingletonWrapper(QV8Engine *v8, const String
DEFINE_OBJECT_VTABLE(QQmlIdObjectsArray);
-QQmlIdObjectsArray::QQmlIdObjectsArray(ExecutionEngine *engine, QmlContextWrapper *contextWrapper)
- : Object(engine)
+QQmlIdObjectsArray::Data::Data(ExecutionEngine *engine, QmlContextWrapper *contextWrapper)
+ : Object::Data(engine)
, contextWrapper(contextWrapper)
{
setVTable(staticVTable());
@@ -449,7 +454,7 @@ QQmlIdObjectsArray::QQmlIdObjectsArray(ExecutionEngine *engine, QmlContextWrappe
ReturnedValue QQmlIdObjectsArray::getIndexed(Managed *m, uint index, bool *hasProperty)
{
QQmlIdObjectsArray *This = static_cast<QQmlIdObjectsArray*>(m);
- QQmlContextData *context = This->contextWrapper->getContext();
+ QQmlContextData *context = This->d()->contextWrapper->getContext();
if (!context) {
if (hasProperty)
*hasProperty = false;
@@ -475,7 +480,7 @@ ReturnedValue QQmlIdObjectsArray::getIndexed(Managed *m, uint index, bool *hasPr
void QQmlIdObjectsArray::markObjects(Managed *that, ExecutionEngine *engine)
{
QQmlIdObjectsArray *This = static_cast<QQmlIdObjectsArray*>(that);
- This->contextWrapper->mark(engine);
+ This->d()->contextWrapper->mark(engine);
Object::markObjects(that, engine);
}
diff --git a/src/qml/qml/qqmlcontextwrapper_p.h b/src/qml/qml/qqmlcontextwrapper_p.h
index 3facf71aa0..d6f25ac79a 100644
--- a/src/qml/qml/qqmlcontextwrapper_p.h
+++ b/src/qml/qml/qqmlcontextwrapper_p.h
@@ -73,9 +73,18 @@ struct QQmlIdObjectsArray;
struct Q_QML_EXPORT QmlContextWrapper : Object
{
- V4_OBJECT
- QmlContextWrapper(QV8Engine *engine, QQmlContextData *context, QObject *scopeObject, bool ownsContext = false);
- ~QmlContextWrapper();
+ struct Data : Object::Data {
+ Data(QV8Engine *engine, QQmlContextData *context, QObject *scopeObject, bool ownsContext = false);
+ ~Data();
+ bool readOnly;
+ bool ownsContext;
+ bool isNullWrapper;
+
+ QQmlGuardedContextData context;
+ QPointer<QObject> scopeObject;
+ QQmlIdObjectsArray *idObjectsWrapper;
+ };
+ V4_OBJECT(Object)
static ReturnedValue qmlScope(QV8Engine *e, QQmlContextData *ctxt, QObject *scope);
static ReturnedValue urlScope(QV8Engine *e, const QUrl &);
@@ -83,41 +92,35 @@ struct Q_QML_EXPORT QmlContextWrapper : Object
static QQmlContextData *callingContext(ExecutionEngine *v4);
static void takeContextOwnership(const ValueRef qmlglobal);
- inline QObject *getScopeObject() const { return scopeObject; }
- inline QQmlContextData *getContext() const { return context; }
+ inline QObject *getScopeObject() const { return d()->scopeObject; }
+ inline QQmlContextData *getContext() const { return d()->context; }
static QQmlContextData *getContext(const ValueRef value);
- void setReadOnly(bool b) { readOnly = b; }
+ void setReadOnly(bool b) { d()->readOnly = b; }
- static ReturnedValue get(Managed *m, const StringRef name, bool *hasProperty);
- static void put(Managed *m, const StringRef name, const ValueRef value);
+ static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
+ static void put(Managed *m, String *name, const ValueRef value);
static void destroy(Managed *that);
static void markObjects(Managed *m, ExecutionEngine *engine);
static void registerQmlDependencies(ExecutionEngine *context, const CompiledData::Function *compiledFunction);
ReturnedValue idObjectsArray();
- ReturnedValue qmlSingletonWrapper(QV8Engine *e, const StringRef &name);
+ ReturnedValue qmlSingletonWrapper(QV8Engine *e, String *name);
- bool readOnly;
- bool ownsContext;
- bool isNullWrapper;
-
- QQmlGuardedContextData context;
- QPointer<QObject> scopeObject;
-private:
- QQmlIdObjectsArray *idObjectsWrapper;
};
struct QQmlIdObjectsArray : public Object
{
- V4_OBJECT
- QQmlIdObjectsArray(ExecutionEngine *engine, QmlContextWrapper *contextWrapper);
+ struct Data : Object::Data {
+ Data(ExecutionEngine *engine, QmlContextWrapper *contextWrapper);
+ QmlContextWrapper *contextWrapper;
+ };
+ V4_OBJECT(Object)
static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
static void markObjects(Managed *that, ExecutionEngine *engine);
- QmlContextWrapper *contextWrapper;
};
}
diff --git a/src/qml/qml/qqmlcustomparser.cpp b/src/qml/qml/qqmlcustomparser.cpp
index 75acbdb778..312c4a8a10 100644
--- a/src/qml/qml/qqmlcustomparser.cpp
+++ b/src/qml/qml/qqmlcustomparser.cpp
@@ -109,6 +109,12 @@ void QQmlCustomParser::error(const QV4::CompiledData::Location &location, const
exceptions << error;
}
+struct StaticQtMetaObject : public QObject
+{
+ static const QMetaObject *get()
+ { return &staticQtMetaObject; }
+};
+
/*!
If \a script is a simple enumeration expression (eg. Text.AlignLeft),
returns the integer equivalent (eg. 1), and sets \a ok to true.
@@ -125,7 +131,34 @@ int QQmlCustomParser::evaluateEnum(const QByteArray& script, bool *ok) const
if (dot == -1)
return -1;
- return compiler->evaluateEnum(QString::fromUtf8(script.left(dot)), script.mid(dot+1), ok);
+
+ QString scope = QString::fromUtf8(script.left(dot));
+ QByteArray enumValue = script.mid(dot+1);
+
+ if (scope != QLatin1String("Qt")) {
+ if (imports.isNull())
+ return -1;
+ QQmlType *type = 0;
+
+ if (imports.isT1()) {
+ imports.asT1()->resolveType(scope, &type, 0, 0, 0);
+ } else {
+ QQmlTypeNameCache::Result result = imports.asT2()->query(scope);
+ if (result.isValid())
+ type = result.type;
+ }
+
+ return type ? type->enumValue(QHashedCStringRef(enumValue.constData(), enumValue.length()), ok) : -1;
+ }
+
+ const QMetaObject *mo = StaticQtMetaObject::get();
+ int i = mo->enumeratorCount();
+ while (i--) {
+ int v = mo->enumerator(i).keyToValue(enumValue.constData(), ok);
+ if (*ok)
+ return v;
+ }
+ return -1;
}
/*!
@@ -137,17 +170,6 @@ const QMetaObject *QQmlCustomParser::resolveType(const QString& name) const
return compiler->resolveType(name);
}
-QQmlBinding::Identifier QQmlCustomParser::bindingIdentifier(const QV4::CompiledData::Binding *binding)
-{
- return compiler->bindingIdentifier(binding, this);
-}
-
-struct StaticQtMetaObject : public QObject
-{
- static const QMetaObject *get()
- { return &staticQtMetaObject; }
-};
-
int QQmlCustomParserCompilerBackend::evaluateEnum(const QString &scope, const QByteArray &enumValue, bool *ok) const
{
Q_ASSERT_X(ok, "QQmlCompiler::evaluateEnum", "ok must not be a null pointer");
diff --git a/src/qml/qml/qqmlcustomparser_p.h b/src/qml/qml/qqmlcustomparser_p.h
index 2ce6375870..9e3f810738 100644
--- a/src/qml/qml/qqmlcustomparser_p.h
+++ b/src/qml/qml/qqmlcustomparser_p.h
@@ -71,8 +71,6 @@ struct QQmlCustomParserCompilerBackend
int evaluateEnum(const QString &scope, const QByteArray& enumValue, bool *ok) const;
const QMetaObject *resolveType(const QString& name) const;
-
- virtual QQmlBinding::Identifier bindingIdentifier(const QV4::CompiledData::Binding *, QQmlCustomParser *) { return QQmlBinding::Invalid; }
};
class Q_QML_PRIVATE_EXPORT QQmlCustomParser
@@ -92,8 +90,8 @@ public:
void clearErrors();
Flags flags() const { return m_flags; }
- virtual QByteArray compile(const QV4::CompiledData::QmlUnit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &bindings) = 0;
- virtual void setCustomData(QObject *, const QByteArray &, QQmlCompiledData *cdata) = 0;
+ virtual void verifyBindings(const QV4::CompiledData::QmlUnit *, const QList<const QV4::CompiledData::Binding *> &) = 0;
+ virtual void applyBindings(QObject *, QQmlCompiledData *, const QList<const QV4::CompiledData::Binding *> &) = 0;
QList<QQmlError> errors() const { return exceptions; }
@@ -108,13 +106,13 @@ protected:
const QMetaObject *resolveType(const QString&) const;
- QQmlBinding::Identifier bindingIdentifier(const QV4::CompiledData::Binding *binding);
-
private:
QList<QQmlError> exceptions;
QQmlCustomParserCompilerBackend *compiler;
Flags m_flags;
+ QBiPointer<const QQmlImports, QQmlTypeNameCache> imports;
friend class QQmlPropertyValidator;
+ friend class QQmlObjectCreator;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlCustomParser::Flags)
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 9bf983ab85..9ba6e67079 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -585,9 +585,6 @@ QQmlEnginePrivate::~QQmlEnginePrivate()
if (incubationController) incubationController->d = 0;
incubationController = 0;
- delete rootContext;
- rootContext = 0;
-
for(QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
(*iter)->release();
for(QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
@@ -907,6 +904,8 @@ QQmlEngine::~QQmlEngine()
if (d->isDebugging)
QQmlDebugServer::instance()->removeEngine(this);
+ d->typeLoader.invalidate();
+
// Emit onDestruction signals for the root context before
// we destroy the contexts, engine, Singleton Types etc. that
// may be required to handle the destruction signal.
@@ -919,6 +918,9 @@ QQmlEngine::~QQmlEngine()
QList<QQmlType*> singletonTypes = QQmlMetaType::qmlSingletonTypes();
foreach (QQmlType *currType, singletonTypes)
currType->singletonInstanceInfo()->destroy(this);
+
+ delete d->rootContext;
+ d->rootContext = 0;
}
/*! \fn void QQmlEngine::quit()
diff --git a/src/qml/qml/qqmlerror.cpp b/src/qml/qml/qqmlerror.cpp
index c583156c43..6d72bfcffa 100644
--- a/src/qml/qml/qqmlerror.cpp
+++ b/src/qml/qml/qqmlerror.cpp
@@ -249,16 +249,17 @@ QString QQmlError::toString() const
QUrl u(url());
int l(line());
- if (u.isEmpty()) {
+ if (u.isEmpty() || (u.isLocalFile() && u.path().isEmpty()))
rv = QLatin1String("<Unknown File>");
- } else if (l != -1) {
- rv = u.toString() + QLatin1Char(':') + QString::number(l);
+ else
+ rv = u.toString();
+
+ if (l != -1) {
+ rv += QLatin1Char(':') + QString::number(l);
int c(column());
if (c != -1)
rv += QLatin1Char(':') + QString::number(c);
- } else {
- rv = u.toString();
}
rv += QLatin1String(": ") + description();
diff --git a/src/qml/qml/qqmlexpression.cpp b/src/qml/qml/qqmlexpression.cpp
index 4dc3704bbb..e993ed98eb 100644
--- a/src/qml/qml/qqmlexpression.cpp
+++ b/src/qml/qml/qqmlexpression.cpp
@@ -161,7 +161,7 @@ QQmlExpression::QQmlExpression(const QQmlScriptString &script, QQmlContext *ctxt
Q_ASSERT(typeData);
if (QQmlCompiledData *cdata = typeData->compiledData()) {
- d->url = cdata->name;
+ d->url = cdata->fileName();
d->line = scriptPrivate->lineNumber;
d->column = scriptPrivate->columnNumber;
diff --git a/src/qml/qml/qqmlfileselector.cpp b/src/qml/qml/qqmlfileselector.cpp
index 187c3656c6..8498a4d67d 100644
--- a/src/qml/qml/qqmlfileselector.cpp
+++ b/src/qml/qml/qqmlfileselector.cpp
@@ -106,8 +106,8 @@ QQmlFileSelector::QQmlFileSelector(QQmlEngine* engine, QObject* parent)
{
Q_D(QQmlFileSelector);
d->engine = engine;
- interceptorInstances()->insert(d->myInstance, this);
- d->engine->setUrlInterceptor(d->myInstance);
+ interceptorInstances()->insert(d->myInstance.data(), this);
+ d->engine->setUrlInterceptor(d->myInstance.data());
}
QQmlFileSelector::~QQmlFileSelector()
@@ -117,7 +117,7 @@ QQmlFileSelector::~QQmlFileSelector()
d->engine->setUrlInterceptor(0);
d->engine = 0;
}
- interceptorInstances()->remove(d->myInstance);
+ interceptorInstances()->remove(d->myInstance.data());
}
QQmlFileSelectorPrivate::QQmlFileSelectorPrivate()
@@ -125,7 +125,7 @@ QQmlFileSelectorPrivate::QQmlFileSelectorPrivate()
Q_Q(QQmlFileSelector);
ownSelector = true;
selector = new QFileSelector(q);
- myInstance = new QQmlFileSelectorInterceptor(this);
+ myInstance.reset(new QQmlFileSelectorInterceptor(this));
}
/*!
diff --git a/src/qml/qml/qqmlfileselector_p.h b/src/qml/qml/qqmlfileselector_p.h
index 501f563ade..73a98788ee 100644
--- a/src/qml/qml/qqmlfileselector_p.h
+++ b/src/qml/qml/qqmlfileselector_p.h
@@ -71,7 +71,7 @@ public:
QFileSelector* selector;
QPointer<QQmlEngine> engine;
bool ownSelector;
- QQmlFileSelectorInterceptor* myInstance;
+ QScopedPointer<QQmlFileSelectorInterceptor> myInstance;
};
class Q_QML_PRIVATE_EXPORT QQmlFileSelectorInterceptor : public QQmlAbstractUrlInterceptor
diff --git a/src/qml/qml/qqmlincubator.cpp b/src/qml/qml/qqmlincubator.cpp
index 4cdeb19719..0665a4ac1a 100644
--- a/src/qml/qml/qqmlincubator.cpp
+++ b/src/qml/qml/qqmlincubator.cpp
@@ -283,7 +283,7 @@ void QQmlIncubatorPrivate::incubate(QQmlInstantiationInterrupt &i)
if (!compiledData)
return;
- QML_MEMORY_SCOPE_URL(compiledData->url);
+ QML_MEMORY_SCOPE_URL(compiledData->url());
QExplicitlySharedDataPointer<QQmlIncubatorPrivate> protectThis(this);
@@ -297,7 +297,7 @@ void QQmlIncubatorPrivate::incubate(QQmlInstantiationInterrupt &i)
if (!guardOk) {
QQmlError error;
- error.setUrl(compiledData->url);
+ error.setUrl(compiledData->url());
error.setDescription(QQmlComponent::tr("Object destroyed during incubation"));
errors << error;
progress = QQmlIncubatorPrivate::Completed;
diff --git a/src/qml/qml/qqmlinfo.cpp b/src/qml/qml/qqmlinfo.cpp
index 63ce2d419c..2f013863ca 100644
--- a/src/qml/qml/qqmlinfo.cpp
+++ b/src/qml/qml/qqmlinfo.cpp
@@ -147,7 +147,7 @@ QQmlInfo::~QQmlInfo()
d->buffer.prepend(QLatin1String("QML ") + typeName + QLatin1String(": "));
QQmlData *ddata = QQmlData::get(object, false);
- if (ddata && ddata->outerContext && !ddata->outerContext->url.isEmpty()) {
+ if (ddata && ddata->outerContext) {
error.setUrl(ddata->outerContext->url);
error.setLine(ddata->lineNumber);
error.setColumn(ddata->columnNumber);
diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp
index 560a4c8afd..8fea5e66d3 100644
--- a/src/qml/qml/qqmljavascriptexpression.cpp
+++ b/src/qml/qml/qqmljavascriptexpression.cpp
@@ -158,7 +158,7 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QQmlContextData *context,
QV4::ExecutionContext *ctx = v4->currentContext();
callData->thisObject = v4->globalObject;
if (scopeObject()) {
- QV4::ScopedValue value(scope, QV4::QObjectWrapper::wrap(ctx->engine, scopeObject()));
+ QV4::ScopedValue value(scope, QV4::QObjectWrapper::wrap(ctx->d()->engine, scopeObject()));
if (value->isObject())
callData->thisObject = value;
}
diff --git a/src/qml/qml/qqmllistwrapper.cpp b/src/qml/qml/qqmllistwrapper.cpp
index fd50e2dbbc..b84752501f 100644
--- a/src/qml/qml/qqmllistwrapper.cpp
+++ b/src/qml/qml/qqmllistwrapper.cpp
@@ -52,18 +52,18 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(QmlListWrapper);
-QmlListWrapper::QmlListWrapper(QV8Engine *engine)
- : Object(QV8Engine::getV4(engine)),
- v8(engine)
+QmlListWrapper::Data::Data(QV8Engine *engine)
+ : Object::Data(QV8Engine::getV4(engine))
+ , v8(engine)
{
setVTable(staticVTable());
+
QV4::Scope scope(QV8Engine::getV4(engine));
- QV4::ScopedObject protectThis(scope, this);
- Q_UNUSED(protectThis);
- setArrayType(ArrayData::Custom);
+ QV4::ScopedObject o(scope, this);
+ o->setArrayType(ArrayData::Custom);
}
-QmlListWrapper::~QmlListWrapper()
+QmlListWrapper::Data::~Data()
{
}
@@ -75,10 +75,10 @@ ReturnedValue QmlListWrapper::create(QV8Engine *v8, QObject *object, int propId,
ExecutionEngine *v4 = QV8Engine::getV4(v8);
Scope scope(v4);
- Scoped<QmlListWrapper> r(scope, new (v4->memoryManager) QmlListWrapper(v8));
- r->object = object;
- r->propertyType = propType;
- void *args[] = { &r->property, 0 };
+ Scoped<QmlListWrapper> r(scope, v4->memoryManager->alloc<QmlListWrapper>(v8));
+ r->d()->object = object;
+ r->d()->propertyType = propType;
+ void *args[] = { &r->d()->property, 0 };
QMetaObject::metacall(object, QMetaObject::ReadProperty, propId, args);
return r.asReturnedValue();
}
@@ -88,31 +88,31 @@ ReturnedValue QmlListWrapper::create(QV8Engine *v8, const QQmlListProperty<QObje
ExecutionEngine *v4 = QV8Engine::getV4(v8);
Scope scope(v4);
- Scoped<QmlListWrapper> r(scope, new (v4->memoryManager) QmlListWrapper(v8));
- r->object = prop.object;
- r->property = prop;
- r->propertyType = propType;
+ Scoped<QmlListWrapper> r(scope, v4->memoryManager->alloc<QmlListWrapper>(v8));
+ r->d()->object = prop.object;
+ r->d()->property = prop;
+ r->d()->propertyType = propType;
return r.asReturnedValue();
}
QVariant QmlListWrapper::toVariant() const
{
- if (!object)
+ if (!d()->object)
return QVariant();
- return QVariant::fromValue(QQmlListReferencePrivate::init(property, propertyType, v8->engine()));
+ return QVariant::fromValue(QQmlListReferencePrivate::init(d()->property, d()->propertyType, d()->v8->engine()));
}
-ReturnedValue QmlListWrapper::get(Managed *m, const StringRef name, bool *hasProperty)
+ReturnedValue QmlListWrapper::get(Managed *m, String *name, bool *hasProperty)
{
QV4::ExecutionEngine *v4 = m->engine();
QmlListWrapper *w = m->as<QmlListWrapper>();
if (!w)
return v4->currentContext()->throwTypeError();
- if (name->equals(v4->id_length) && !w->object.isNull()) {
- quint32 count = w->property.count ? w->property.count(&w->property) : 0;
+ if (name->equals(v4->id_length) && !w->d()->object.isNull()) {
+ quint32 count = w->d()->property.count ? w->d()->property.count(&w->d()->property) : 0;
return Primitive::fromUInt32(count).asReturnedValue();
}
@@ -135,11 +135,11 @@ ReturnedValue QmlListWrapper::getIndexed(Managed *m, uint index, bool *hasProper
return e->currentContext()->throwTypeError();
}
- quint32 count = w->property.count ? w->property.count(&w->property) : 0;
- if (index < count && w->property.at) {
+ quint32 count = w->d()->property.count ? w->d()->property.count(&w->d()->property) : 0;
+ if (index < count && w->d()->property.at) {
if (hasProperty)
*hasProperty = true;
- return QV4::QObjectWrapper::wrap(e, w->property.at(&w->property, index));
+ return QV4::QObjectWrapper::wrap(e, w->d()->property.at(&w->d()->property, index));
}
if (hasProperty)
@@ -147,7 +147,7 @@ ReturnedValue QmlListWrapper::getIndexed(Managed *m, uint index, bool *hasProper
return Primitive::undefinedValue().asReturnedValue();
}
-void QmlListWrapper::put(Managed *m, const StringRef name, const ValueRef value)
+void QmlListWrapper::put(Managed *m, String *name, const ValueRef value)
{
// doesn't do anything. Should we throw?
Q_UNUSED(m);
@@ -158,20 +158,20 @@ void QmlListWrapper::put(Managed *m, const StringRef name, const ValueRef value)
void QmlListWrapper::destroy(Managed *that)
{
QmlListWrapper *w = that->as<QmlListWrapper>();
- w->~QmlListWrapper();
+ w->d()->~Data();
}
-void QmlListWrapper::advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, Property *p, PropertyAttributes *attrs)
+void QmlListWrapper::advanceIterator(Managed *m, ObjectIterator *it, String *&name, uint *index, Property *p, PropertyAttributes *attrs)
{
name = (String *)0;
*index = UINT_MAX;
QmlListWrapper *w = m->as<QmlListWrapper>();
- quint32 count = w->property.count ? w->property.count(&w->property) : 0;
+ quint32 count = w->d()->property.count ? w->d()->property.count(&w->d()->property) : 0;
if (it->arrayIndex < count) {
*index = it->arrayIndex;
++it->arrayIndex;
*attrs = QV4::Attr_Data;
- p->value = QV4::QObjectWrapper::wrap(w->engine(), w->property.at(&w->property, *index));
+ p->value = QV4::QObjectWrapper::wrap(w->engine(), w->d()->property.at(&w->d()->property, *index));
return;
}
return QV4::Object::advanceIterator(m, it, name, index, p, attrs);
diff --git a/src/qml/qml/qqmllistwrapper_p.h b/src/qml/qml/qqmllistwrapper_p.h
index a7ce8b30bf..f6aee04487 100644
--- a/src/qml/qml/qqmllistwrapper_p.h
+++ b/src/qml/qml/qqmllistwrapper_p.h
@@ -69,30 +69,26 @@ namespace QV4 {
struct Q_QML_EXPORT QmlListWrapper : Object
{
- V4_OBJECT
-protected:
- QmlListWrapper(QV8Engine *engine);
- ~QmlListWrapper();
-
-public:
+ struct Data : Object::Data {
+ Data(QV8Engine *engine);
+ ~Data();
+ QV8Engine *v8;
+ QPointer<QObject> object;
+ QQmlListProperty<QObject> property;
+ int propertyType;
+ };
+ V4_OBJECT(Object)
static ReturnedValue create(QV8Engine *v8, QObject *object, int propId, int propType);
static ReturnedValue create(QV8Engine *v8, const QQmlListProperty<QObject> &prop, int propType);
QVariant toVariant() const;
- static ReturnedValue get(Managed *m, const StringRef name, bool *hasProperty);
+ static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
- static void put(Managed *m, const StringRef name, const ValueRef value);
- static void advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, Property *p, PropertyAttributes *attributes);
+ static void put(Managed *m, String *name, const ValueRef value);
+ static void advanceIterator(Managed *m, ObjectIterator *it, String *&name, uint *index, Property *p, PropertyAttributes *attributes);
static void destroy(Managed *that);
-
-private:
- QV8Engine *v8;
- QPointer<QObject> object;
- QQmlListProperty<QObject> property;
- int propertyType;
-
};
}
diff --git a/src/qml/qml/qqmllocale.cpp b/src/qml/qml/qqmllocale.cpp
index 178280b27c..b1ce0da8e0 100644
--- a/src/qml/qml/qqmllocale.cpp
+++ b/src/qml/qml/qqmllocale.cpp
@@ -82,171 +82,171 @@ void QQmlDateExtension::registerExtension(QV4::ExecutionEngine *engine)
QV4::ReturnedValue QQmlDateExtension::method_toLocaleString(QV4::CallContext *ctx)
{
- if (ctx->callData->argc > 2)
+ if (ctx->d()->callData->argc > 2)
return QV4::DatePrototype::method_toLocaleString(ctx);
QV4::Scope scope(ctx);
- QV4::DateObject *date = ctx->callData->thisObject.asDateObject();
+ QV4::DateObject *date = ctx->d()->callData->thisObject.asDateObject();
if (!date)
return QV4::DatePrototype::method_toLocaleString(ctx);
QDateTime dt = date->toQDateTime();
- if (ctx->callData->argc == 0) {
+ if (ctx->d()->callData->argc == 0) {
// Use QLocale for standard toLocaleString() function
QLocale locale;
- return ctx->engine->newString(locale.toString(dt))->asReturnedValue();
+ return ctx->d()->engine->newString(locale.toString(dt))->asReturnedValue();
}
- if (!isLocaleObject(ctx->callData->args[0]))
+ if (!isLocaleObject(ctx->d()->callData->args[0]))
return QV4::DatePrototype::method_toLocaleString(ctx); // Use the default Date toLocaleString()
- GET_LOCALE_DATA_RESOURCE(ctx->callData->args[0]);
+ GET_LOCALE_DATA_RESOURCE(ctx->d()->callData->args[0]);
QLocale::FormatType enumFormat = QLocale::LongFormat;
QString formattedDt;
- if (ctx->callData->argc == 2) {
- if (ctx->callData->args[1].isString()) {
- QString format = ctx->callData->args[1].stringValue()->toQString();
- formattedDt = r->locale.toString(dt, format);
- } else if (ctx->callData->args[1].isNumber()) {
- quint32 intFormat = ctx->callData->args[1].toNumber();
+ if (ctx->d()->callData->argc == 2) {
+ if (ctx->d()->callData->args[1].isString()) {
+ QString format = ctx->d()->callData->args[1].stringValue()->toQString();
+ formattedDt = r->d()->locale.toString(dt, format);
+ } else if (ctx->d()->callData->args[1].isNumber()) {
+ quint32 intFormat = ctx->d()->callData->args[1].toNumber();
QLocale::FormatType format = QLocale::FormatType(intFormat);
- formattedDt = r->locale.toString(dt, format);
+ formattedDt = r->d()->locale.toString(dt, format);
} else {
V4THROW_ERROR("Locale: Date.toLocaleString(): Invalid datetime format");
}
} else {
- formattedDt = r->locale.toString(dt, enumFormat);
+ formattedDt = r->d()->locale.toString(dt, enumFormat);
}
- return ctx->engine->newString(formattedDt)->asReturnedValue();
+ return ctx->d()->engine->newString(formattedDt)->asReturnedValue();
}
QV4::ReturnedValue QQmlDateExtension::method_toLocaleTimeString(QV4::CallContext *ctx)
{
- if (ctx->callData->argc > 2)
+ if (ctx->d()->callData->argc > 2)
return QV4::DatePrototype::method_toLocaleTimeString(ctx);
QV4::Scope scope(ctx);
- QV4::DateObject *date = ctx->callData->thisObject.asDateObject();
+ QV4::DateObject *date = ctx->d()->callData->thisObject.asDateObject();
if (!date)
return QV4::DatePrototype::method_toLocaleTimeString(ctx);
QDateTime dt = date->toQDateTime();
QTime time = dt.time();
- if (ctx->callData->argc == 0) {
+ if (ctx->d()->callData->argc == 0) {
// Use QLocale for standard toLocaleString() function
QLocale locale;
- return ctx->engine->newString(locale.toString(time))->asReturnedValue();
+ return ctx->d()->engine->newString(locale.toString(time))->asReturnedValue();
}
- if (!isLocaleObject(ctx->callData->args[0]))
+ if (!isLocaleObject(ctx->d()->callData->args[0]))
return QV4::DatePrototype::method_toLocaleTimeString(ctx); // Use the default Date toLocaleTimeString()
- GET_LOCALE_DATA_RESOURCE(ctx->callData->args[0]);
+ GET_LOCALE_DATA_RESOURCE(ctx->d()->callData->args[0]);
QLocale::FormatType enumFormat = QLocale::LongFormat;
QString formattedTime;
- if (ctx->callData->argc == 2) {
- if (ctx->callData->args[1].isString()) {
- QString format = ctx->callData->args[1].stringValue()->toQString();
- formattedTime = r->locale.toString(time, format);
- } else if (ctx->callData->args[1].isNumber()) {
- quint32 intFormat = ctx->callData->args[1].toNumber();
+ if (ctx->d()->callData->argc == 2) {
+ if (ctx->d()->callData->args[1].isString()) {
+ QString format = ctx->d()->callData->args[1].stringValue()->toQString();
+ formattedTime = r->d()->locale.toString(time, format);
+ } else if (ctx->d()->callData->args[1].isNumber()) {
+ quint32 intFormat = ctx->d()->callData->args[1].toNumber();
QLocale::FormatType format = QLocale::FormatType(intFormat);
- formattedTime = r->locale.toString(time, format);
+ formattedTime = r->d()->locale.toString(time, format);
} else {
V4THROW_ERROR("Locale: Date.toLocaleTimeString(): Invalid time format");
}
} else {
- formattedTime = r->locale.toString(time, enumFormat);
+ formattedTime = r->d()->locale.toString(time, enumFormat);
}
- return ctx->engine->newString(formattedTime)->asReturnedValue();
+ return ctx->d()->engine->newString(formattedTime)->asReturnedValue();
}
QV4::ReturnedValue QQmlDateExtension::method_toLocaleDateString(QV4::CallContext *ctx)
{
- if (ctx->callData->argc > 2)
+ if (ctx->d()->callData->argc > 2)
return QV4::DatePrototype::method_toLocaleDateString(ctx);
QV4::Scope scope(ctx);
- QV4::DateObject *dateObj = ctx->callData->thisObject.asDateObject();
+ QV4::DateObject *dateObj = ctx->d()->callData->thisObject.asDateObject();
if (!dateObj)
return QV4::DatePrototype::method_toLocaleDateString(ctx);
QDateTime dt = dateObj->toQDateTime();
QDate date = dt.date();
- if (ctx->callData->argc == 0) {
+ if (ctx->d()->callData->argc == 0) {
// Use QLocale for standard toLocaleString() function
QLocale locale;
- return ctx->engine->newString(locale.toString(date))->asReturnedValue();
+ return ctx->d()->engine->newString(locale.toString(date))->asReturnedValue();
}
- if (!isLocaleObject(ctx->callData->args[0]))
+ if (!isLocaleObject(ctx->d()->callData->args[0]))
return QV4::DatePrototype::method_toLocaleDateString(ctx); // Use the default Date toLocaleDateString()
- GET_LOCALE_DATA_RESOURCE(ctx->callData->args[0]);
+ GET_LOCALE_DATA_RESOURCE(ctx->d()->callData->args[0]);
QLocale::FormatType enumFormat = QLocale::LongFormat;
QString formattedDate;
- if (ctx->callData->argc == 2) {
- if (ctx->callData->args[1].isString()) {
- QString format = ctx->callData->args[1].stringValue()->toQString();
- formattedDate = r->locale.toString(date, format);
- } else if (ctx->callData->args[1].isNumber()) {
- quint32 intFormat = ctx->callData->args[1].toNumber();
+ if (ctx->d()->callData->argc == 2) {
+ if (ctx->d()->callData->args[1].isString()) {
+ QString format = ctx->d()->callData->args[1].stringValue()->toQString();
+ formattedDate = r->d()->locale.toString(date, format);
+ } else if (ctx->d()->callData->args[1].isNumber()) {
+ quint32 intFormat = ctx->d()->callData->args[1].toNumber();
QLocale::FormatType format = QLocale::FormatType(intFormat);
- formattedDate = r->locale.toString(date, format);
+ formattedDate = r->d()->locale.toString(date, format);
} else {
V4THROW_ERROR("Locale: Date.loLocaleDateString(): Invalid date format");
}
} else {
- formattedDate = r->locale.toString(date, enumFormat);
+ formattedDate = r->d()->locale.toString(date, enumFormat);
}
- return ctx->engine->newString(formattedDate)->asReturnedValue();
+ return ctx->d()->engine->newString(formattedDate)->asReturnedValue();
}
QV4::ReturnedValue QQmlDateExtension::method_fromLocaleString(QV4::CallContext *ctx)
{
- QV4::ExecutionEngine * const engine = ctx->engine;
- if (ctx->callData->argc == 1 && ctx->callData->args[0].isString()) {
+ QV4::ExecutionEngine * const engine = ctx->d()->engine;
+ if (ctx->d()->callData->argc == 1 && ctx->d()->callData->args[0].isString()) {
QLocale locale;
- QString dateString = ctx->callData->args[0].stringValue()->toQString();
+ QString dateString = ctx->d()->callData->args[0].stringValue()->toQString();
QDateTime dt = locale.toDateTime(dateString);
return QV4::Encode(engine->newDateObject(dt));
}
QV4::Scope scope(ctx);
- if (ctx->callData->argc < 1 || ctx->callData->argc > 3 || !isLocaleObject(ctx->callData->args[0]))
+ if (ctx->d()->callData->argc < 1 || ctx->d()->callData->argc > 3 || !isLocaleObject(ctx->d()->callData->args[0]))
V4THROW_ERROR("Locale: Date.fromLocaleString(): Invalid arguments");
- GET_LOCALE_DATA_RESOURCE(ctx->callData->args[0]);
+ GET_LOCALE_DATA_RESOURCE(ctx->d()->callData->args[0]);
QLocale::FormatType enumFormat = QLocale::LongFormat;
QDateTime dt;
- QString dateString = ctx->callData->args[1].toQStringNoThrow();
- if (ctx->callData->argc == 3) {
- if (ctx->callData->args[2].isString()) {
- QString format = ctx->callData->args[2].stringValue()->toQString();
- dt = r->locale.toDateTime(dateString, format);
- } else if (ctx->callData->args[2].isNumber()) {
- quint32 intFormat = ctx->callData->args[2].toNumber();
+ QString dateString = ctx->d()->callData->args[1].toQStringNoThrow();
+ if (ctx->d()->callData->argc == 3) {
+ if (ctx->d()->callData->args[2].isString()) {
+ QString format = ctx->d()->callData->args[2].stringValue()->toQString();
+ dt = r->d()->locale.toDateTime(dateString, format);
+ } else if (ctx->d()->callData->args[2].isNumber()) {
+ quint32 intFormat = ctx->d()->callData->args[2].toNumber();
QLocale::FormatType format = QLocale::FormatType(intFormat);
- dt = r->locale.toDateTime(dateString, format);
+ dt = r->d()->locale.toDateTime(dateString, format);
} else {
V4THROW_ERROR("Locale: Date.fromLocaleString(): Invalid datetime format");
}
} else {
- dt = r->locale.toDateTime(dateString, enumFormat);
+ dt = r->d()->locale.toDateTime(dateString, enumFormat);
}
return QV4::Encode(engine->newDateObject(dt));
@@ -254,40 +254,40 @@ QV4::ReturnedValue QQmlDateExtension::method_fromLocaleString(QV4::CallContext *
QV4::ReturnedValue QQmlDateExtension::method_fromLocaleTimeString(QV4::CallContext *ctx)
{
- QV4::ExecutionEngine * const engine = ctx->engine;
+ QV4::ExecutionEngine * const engine = ctx->d()->engine;
- if (ctx->callData->argc == 1 && ctx->callData->args[0].isString()) {
+ if (ctx->d()->callData->argc == 1 && ctx->d()->callData->args[0].isString()) {
QLocale locale;
- QString timeString = ctx->callData->args[0].stringValue()->toQString();
+ QString timeString = ctx->d()->callData->args[0].stringValue()->toQString();
QTime time = locale.toTime(timeString);
QDateTime dt = QDateTime::currentDateTime();
dt.setTime(time);
return QV4::Encode(engine->newDateObject(dt));
}
- if (ctx->callData->argc < 1 || ctx->callData->argc > 3 || !isLocaleObject(ctx->callData->args[0]))
+ if (ctx->d()->callData->argc < 1 || ctx->d()->callData->argc > 3 || !isLocaleObject(ctx->d()->callData->args[0]))
V4THROW_ERROR("Locale: Date.fromLocaleTimeString(): Invalid arguments");
QV4::Scope scope(ctx);
- GET_LOCALE_DATA_RESOURCE(ctx->callData->args[0]);
+ GET_LOCALE_DATA_RESOURCE(ctx->d()->callData->args[0]);
QLocale::FormatType enumFormat = QLocale::LongFormat;
QTime tm;
- QString dateString = ctx->callData->args[1].toQStringNoThrow();
- if (ctx->callData->argc == 3) {
- if (ctx->callData->args[2].isString()) {
- QString format = ctx->callData->args[2].stringValue()->toQString();
- tm = r->locale.toTime(dateString, format);
- } else if (ctx->callData->args[2].isNumber()) {
- quint32 intFormat = ctx->callData->args[2].toNumber();
+ QString dateString = ctx->d()->callData->args[1].toQStringNoThrow();
+ if (ctx->d()->callData->argc == 3) {
+ if (ctx->d()->callData->args[2].isString()) {
+ QString format = ctx->d()->callData->args[2].stringValue()->toQString();
+ tm = r->d()->locale.toTime(dateString, format);
+ } else if (ctx->d()->callData->args[2].isNumber()) {
+ quint32 intFormat = ctx->d()->callData->args[2].toNumber();
QLocale::FormatType format = QLocale::FormatType(intFormat);
- tm = r->locale.toTime(dateString, format);
+ tm = r->d()->locale.toTime(dateString, format);
} else {
V4THROW_ERROR("Locale: Date.fromLocaleTimeString(): Invalid datetime format");
}
} else {
- tm = r->locale.toTime(dateString, enumFormat);
+ tm = r->d()->locale.toTime(dateString, enumFormat);
}
QDateTime dt;
@@ -301,38 +301,38 @@ QV4::ReturnedValue QQmlDateExtension::method_fromLocaleTimeString(QV4::CallConte
QV4::ReturnedValue QQmlDateExtension::method_fromLocaleDateString(QV4::CallContext *ctx)
{
- QV4::ExecutionEngine * const engine = ctx->engine;
+ QV4::ExecutionEngine * const engine = ctx->d()->engine;
- if (ctx->callData->argc == 1 && ctx->callData->args[0].isString()) {
+ if (ctx->d()->callData->argc == 1 && ctx->d()->callData->args[0].isString()) {
QLocale locale;
- QString dateString = ctx->callData->args[0].stringValue()->toQString();
+ QString dateString = ctx->d()->callData->args[0].stringValue()->toQString();
QDate date = locale.toDate(dateString);
return QV4::Encode(engine->newDateObject(QDateTime(date)));
}
- if (ctx->callData->argc < 1 || ctx->callData->argc > 3 || !isLocaleObject(ctx->callData->args[0]))
+ if (ctx->d()->callData->argc < 1 || ctx->d()->callData->argc > 3 || !isLocaleObject(ctx->d()->callData->args[0]))
V4THROW_ERROR("Locale: Date.fromLocaleDateString(): Invalid arguments");
QV4::Scope scope(ctx);
- GET_LOCALE_DATA_RESOURCE(ctx->callData->args[0]);
+ GET_LOCALE_DATA_RESOURCE(ctx->d()->callData->args[0]);
QLocale::FormatType enumFormat = QLocale::LongFormat;
QDate dt;
- QString dateString = ctx->callData->args[1].toQStringNoThrow();
- if (ctx->callData->argc == 3) {
- if (ctx->callData->args[2].isString()) {
- QString format = ctx->callData->args[2].stringValue()->toQString();
- dt = r->locale.toDate(dateString, format);
- } else if (ctx->callData->args[2].isNumber()) {
- quint32 intFormat = ctx->callData->args[2].toNumber();
+ QString dateString = ctx->d()->callData->args[1].toQStringNoThrow();
+ if (ctx->d()->callData->argc == 3) {
+ if (ctx->d()->callData->args[2].isString()) {
+ QString format = ctx->d()->callData->args[2].stringValue()->toQString();
+ dt = r->d()->locale.toDate(dateString, format);
+ } else if (ctx->d()->callData->args[2].isNumber()) {
+ quint32 intFormat = ctx->d()->callData->args[2].toNumber();
QLocale::FormatType format = QLocale::FormatType(intFormat);
- dt = r->locale.toDate(dateString, format);
+ dt = r->d()->locale.toDate(dateString, format);
} else {
V4THROW_ERROR("Locale: Date.fromLocaleDateString(): Invalid datetime format");
}
} else {
- dt = r->locale.toDate(dateString, enumFormat);
+ dt = r->d()->locale.toDate(dateString, enumFormat);
}
return QV4::Encode(engine->newDateObject(QDateTime(dt)));
@@ -340,7 +340,7 @@ QV4::ReturnedValue QQmlDateExtension::method_fromLocaleDateString(QV4::CallConte
QV4::ReturnedValue QQmlDateExtension::method_timeZoneUpdated(QV4::CallContext *ctx)
{
- if (ctx->callData->argc != 0)
+ if (ctx->d()->callData->argc != 0)
V4THROW_ERROR("Locale: Date.timeZoneUpdated(): Invalid arguments");
QV4::DatePrototype::timezoneUpdated();
@@ -360,75 +360,75 @@ void QQmlNumberExtension::registerExtension(QV4::ExecutionEngine *engine)
QV4::ReturnedValue QQmlNumberExtension::method_toLocaleString(QV4::CallContext *ctx)
{
- if (ctx->callData->argc > 3)
+ if (ctx->d()->callData->argc > 3)
V4THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments");
- double number = ctx->callData->thisObject.toNumber();
+ double number = ctx->d()->callData->thisObject.toNumber();
- if (ctx->callData->argc == 0) {
+ if (ctx->d()->callData->argc == 0) {
// Use QLocale for standard toLocaleString() function
QLocale locale;
- return ctx->engine->newString(locale.toString(number))->asReturnedValue();
+ return ctx->d()->engine->newString(locale.toString(number))->asReturnedValue();
}
- if (!isLocaleObject(ctx->callData->args[0]))
+ if (!isLocaleObject(ctx->d()->callData->args[0]))
return QV4::NumberPrototype::method_toLocaleString(ctx); // Use the default Number toLocaleString()
QV4::Scope scope(ctx);
- GET_LOCALE_DATA_RESOURCE(ctx->callData->args[0]);
+ GET_LOCALE_DATA_RESOURCE(ctx->d()->callData->args[0]);
quint16 format = 'f';
- if (ctx->callData->argc > 1) {
- if (!ctx->callData->args[1].isString())
+ if (ctx->d()->callData->argc > 1) {
+ if (!ctx->d()->callData->args[1].isString())
V4THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments");
- QV4::String *fs = ctx->callData->args[1].toString(ctx);
- if (fs->length())
+ QV4::String *fs = ctx->d()->callData->args[1].toString(ctx);
+ if (fs->d()->length())
format = fs->toQString().at(0).unicode();
}
int prec = 2;
- if (ctx->callData->argc > 2) {
- if (!ctx->callData->args[2].isNumber())
+ if (ctx->d()->callData->argc > 2) {
+ if (!ctx->d()->callData->args[2].isNumber())
V4THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments");
- prec = ctx->callData->args[2].toInt32();
+ prec = ctx->d()->callData->args[2].toInt32();
}
- return ctx->engine->newString(r->locale.toString(number, (char)format, prec))->asReturnedValue();
+ return ctx->d()->engine->newString(r->d()->locale.toString(number, (char)format, prec))->asReturnedValue();
}
QV4::ReturnedValue QQmlNumberExtension::method_toLocaleCurrencyString(QV4::CallContext *ctx)
{
- if (ctx->callData->argc > 2)
+ if (ctx->d()->callData->argc > 2)
V4THROW_ERROR("Locale: Number.toLocaleCurrencyString(): Invalid arguments");
- double number = ctx->callData->thisObject.toNumber();
+ double number = ctx->d()->callData->thisObject.toNumber();
- if (ctx->callData->argc == 0) {
+ if (ctx->d()->callData->argc == 0) {
// Use QLocale for standard toLocaleString() function
QLocale locale;
- return ctx->engine->newString(locale.toString(number))->asReturnedValue();
+ return ctx->d()->engine->newString(locale.toString(number))->asReturnedValue();
}
- if (!isLocaleObject(ctx->callData->args[0]))
+ if (!isLocaleObject(ctx->d()->callData->args[0]))
V4THROW_ERROR("Locale: Number.toLocaleCurrencyString(): Invalid arguments");
QV4::Scope scope(ctx);
- GET_LOCALE_DATA_RESOURCE(ctx->callData->args[0]);
+ GET_LOCALE_DATA_RESOURCE(ctx->d()->callData->args[0]);
QString symbol;
- if (ctx->callData->argc > 1) {
- if (!ctx->callData->args[1].isString())
+ if (ctx->d()->callData->argc > 1) {
+ if (!ctx->d()->callData->args[1].isString())
V4THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments");
- symbol = ctx->callData->args[1].toQStringNoThrow();
+ symbol = ctx->d()->callData->args[1].toQStringNoThrow();
}
- return ctx->engine->newString(r->locale.toCurrencyString(number, symbol))->asReturnedValue();
+ return ctx->d()->engine->newString(r->d()->locale.toCurrencyString(number, symbol))->asReturnedValue();
}
QV4::ReturnedValue QQmlNumberExtension::method_fromLocaleString(QV4::CallContext *ctx)
{
- if (ctx->callData->argc < 1 || ctx->callData->argc > 2)
+ if (ctx->d()->callData->argc < 1 || ctx->d()->callData->argc > 2)
V4THROW_ERROR("Locale: Number.fromLocaleString(): Invalid arguments");
int numberIdx = 0;
@@ -436,18 +436,18 @@ QV4::ReturnedValue QQmlNumberExtension::method_fromLocaleString(QV4::CallContext
QV4::Scope scope(ctx);
- if (ctx->callData->argc == 2) {
- if (!isLocaleObject(ctx->callData->args[0]))
+ if (ctx->d()->callData->argc == 2) {
+ if (!isLocaleObject(ctx->d()->callData->args[0]))
V4THROW_ERROR("Locale: Number.fromLocaleString(): Invalid arguments");
- GET_LOCALE_DATA_RESOURCE(ctx->callData->args[0]);
- locale = r->locale;
+ GET_LOCALE_DATA_RESOURCE(ctx->d()->callData->args[0]);
+ locale = r->d()->locale;
numberIdx = 1;
}
- QV4::String *ns = ctx->callData->args[numberIdx].toString(ctx);
- if (!ns->length())
+ QV4::String *ns = ctx->d()->callData->args[numberIdx].toString(ctx);
+ if (!ns->d()->length())
return QV4::Encode(Q_QNAN);
bool ok = false;
@@ -499,7 +499,7 @@ QV4::ReturnedValue QQmlLocaleData::method_get_weekDays(QV4::CallContext *ctx)
QList<Qt::DayOfWeek> days = locale->weekdays();
- QV4::Scoped<QV4::ArrayObject> result(scope, ctx->engine->newArrayObject());
+ QV4::Scoped<QV4::ArrayObject> result(scope, ctx->d()->engine->newArrayObject());
result->arrayReserve(days.size());
for (int i = 0; i < days.size(); ++i) {
int day = days.at(i);
@@ -520,11 +520,11 @@ QV4::ReturnedValue QQmlLocaleData::method_get_uiLanguages(QV4::CallContext *ctx)
return QV4::Encode::undefined();
QStringList langs = locale->uiLanguages();
- QV4::Scoped<QV4::ArrayObject> result(scope, ctx->engine->newArrayObject());
+ QV4::Scoped<QV4::ArrayObject> result(scope, ctx->d()->engine->newArrayObject());
result->arrayReserve(langs.size());
QV4::ScopedValue v(scope);
for (int i = 0; i < langs.size(); ++i)
- result->arrayPut(i, (v = ctx->engine->newString(langs.at(i))));
+ result->arrayPut(i, (v = ctx->d()->engine->newString(langs.at(i))));
result->setArrayLengthUnchecked(langs.size());
@@ -537,16 +537,16 @@ QV4::ReturnedValue QQmlLocaleData::method_currencySymbol(QV4::CallContext *ctx)
if (!locale)
return QV4::Encode::undefined();
- if (ctx->callData->argc > 1)
+ if (ctx->d()->callData->argc > 1)
V4THROW_ERROR("Locale: currencySymbol(): Invalid arguments");
QLocale::CurrencySymbolFormat format = QLocale::CurrencySymbol;
- if (ctx->callData->argc == 1) {
- quint32 intFormat = ctx->callData->args[0].toNumber();
+ if (ctx->d()->callData->argc == 1) {
+ quint32 intFormat = ctx->d()->callData->args[0].toNumber();
format = QLocale::CurrencySymbolFormat(intFormat);
}
- return ctx->engine->newString(locale->currencySymbol(format))->asReturnedValue();
+ return ctx->d()->engine->newString(locale->currencySymbol(format))->asReturnedValue();
}
#define LOCALE_FORMAT(FUNC) \
@@ -554,14 +554,14 @@ QV4::ReturnedValue QQmlLocaleData::method_ ##FUNC (QV4::CallContext *ctx) { \
QLocale *locale = getThisLocale(ctx); \
if (!locale) \
return QV4::Encode::undefined(); \
- if (ctx->callData->argc > 1) \
+ if (ctx->d()->callData->argc > 1) \
V4THROW_ERROR("Locale: " #FUNC "(): Invalid arguments"); \
QLocale::FormatType format = QLocale::LongFormat;\
- if (ctx->callData->argc == 1) { \
- quint32 intFormat = ctx->callData->args[0].toUInt32(); \
+ if (ctx->d()->callData->argc == 1) { \
+ quint32 intFormat = ctx->d()->callData->args[0].toUInt32(); \
format = QLocale::FormatType(intFormat); \
} \
- return ctx->engine->newString(locale-> FUNC (format))->asReturnedValue(); \
+ return ctx->engine()->newString(locale-> FUNC (format))->asReturnedValue(); \
}
LOCALE_FORMAT(dateTimeFormat)
@@ -574,16 +574,16 @@ QV4::ReturnedValue QQmlLocaleData::method_ ## VARIABLE (QV4::CallContext *ctx) {
QLocale *locale = getThisLocale(ctx); \
if (!locale) \
return QV4::Encode::undefined(); \
- if (ctx->callData->argc < 1 || ctx->callData->argc > 2) \
+ if (ctx->d()->callData->argc < 1 || ctx->d()->callData->argc > 2) \
V4THROW_ERROR("Locale: " #VARIABLE "(): Invalid arguments"); \
QLocale::FormatType enumFormat = QLocale::LongFormat; \
- int idx = ctx->callData->args[0].toInt32() + 1; \
+ int idx = ctx->d()->callData->args[0].toInt32() + 1; \
if (idx < 1 || idx > 12) \
V4THROW_ERROR("Locale: Invalid month"); \
QString name; \
- if (ctx->callData->argc == 2) { \
- if (ctx->callData->args[1].isNumber()) { \
- quint32 intFormat = ctx->callData->args[1].toUInt32(); \
+ if (ctx->d()->callData->argc == 2) { \
+ if (ctx->d()->callData->args[1].isNumber()) { \
+ quint32 intFormat = ctx->d()->callData->args[1].toUInt32(); \
QLocale::FormatType format = QLocale::FormatType(intFormat); \
name = locale-> VARIABLE(idx, format); \
} else { \
@@ -592,7 +592,7 @@ QV4::ReturnedValue QQmlLocaleData::method_ ## VARIABLE (QV4::CallContext *ctx) {
} else { \
name = locale-> VARIABLE(idx, enumFormat); \
} \
- return ctx->engine->newString(name)->asReturnedValue(); \
+ return ctx->engine()->newString(name)->asReturnedValue(); \
}
// 0 -> 7 as Qt::Sunday is 7, but Sunday is 0 in JS Date
@@ -601,17 +601,17 @@ QV4::ReturnedValue QQmlLocaleData::method_ ## VARIABLE (QV4::CallContext *ctx) {
QLocale *locale = getThisLocale(ctx); \
if (!locale) \
return QV4::Encode::undefined(); \
- if (ctx->callData->argc < 1 || ctx->callData->argc > 2) \
+ if (ctx->d()->callData->argc < 1 || ctx->d()->callData->argc > 2) \
V4THROW_ERROR("Locale: " #VARIABLE "(): Invalid arguments"); \
QLocale::FormatType enumFormat = QLocale::LongFormat; \
- int idx = ctx->callData->args[0].toInt32(); \
+ int idx = ctx->d()->callData->args[0].toInt32(); \
if (idx < 0 || idx > 7) \
V4THROW_ERROR("Locale: Invalid day"); \
if (idx == 0) idx = 7; \
QString name; \
- if (ctx->callData->argc == 2) { \
- if (ctx->callData->args[1].isNumber()) { \
- quint32 intFormat = ctx->callData->args[1].toUInt32(); \
+ if (ctx->d()->callData->argc == 2) { \
+ if (ctx->d()->callData->args[1].isNumber()) { \
+ quint32 intFormat = ctx->d()->callData->args[1].toUInt32(); \
QLocale::FormatType format = QLocale::FormatType(intFormat); \
name = locale-> VARIABLE(idx, format); \
} else { \
@@ -620,7 +620,7 @@ QV4::ReturnedValue QQmlLocaleData::method_ ## VARIABLE (QV4::CallContext *ctx) {
} else { \
name = locale-> VARIABLE(idx, enumFormat); \
} \
- return ctx->engine->newString(name)->asReturnedValue(); \
+ return ctx->engine()->newString(name)->asReturnedValue(); \
}
LOCALE_FORMATTED_MONTHNAME(monthName)
@@ -633,7 +633,7 @@ LOCALE_FORMATTED_DAYNAME(standaloneDayName)
QLocale *locale = getThisLocale(ctx); \
if (!locale) \
return QV4::Encode::undefined(); \
- return ctx->engine->newString(locale-> VARIABLE())->asReturnedValue();\
+ return ctx->engine()->newString(locale-> VARIABLE())->asReturnedValue();\
}
LOCALE_STRING_PROPERTY(name)
@@ -814,8 +814,8 @@ QV4::ReturnedValue QQmlLocale::wrap(QV8Engine *engine, const QLocale &locale)
QV8LocaleDataDeletable *d = localeV8Data(engine);
QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
QV4::Scope scope(v4);
- QV4::Scoped<QQmlLocaleData> wrapper(scope, new (v4->memoryManager) QQmlLocaleData(v4));
- wrapper->locale = locale;
+ QV4::Scoped<QQmlLocaleData> wrapper(scope, v4->memoryManager->alloc<QQmlLocaleData>(v4));
+ wrapper->d()->locale = locale;
QV4::ScopedObject p(scope, d->prototype.value());
wrapper->setPrototype(p.getPointer());
return wrapper.asReturnedValue();
@@ -828,14 +828,14 @@ void QQmlLocale::registerStringLocaleCompare(QV4::ExecutionEngine *engine)
QV4::ReturnedValue QQmlLocale::method_localeCompare(QV4::CallContext *ctx)
{
- if (ctx->callData->argc != 1 || (!ctx->callData->args[0].isString() && !ctx->callData->args[0].asStringObject()))
+ if (ctx->d()->callData->argc != 1 || (!ctx->d()->callData->args[0].isString() && !ctx->d()->callData->args[0].asStringObject()))
return QV4::StringPrototype::method_localeCompare(ctx);
- if (!ctx->callData->thisObject.isString() && !ctx->callData->thisObject.asStringObject())
+ if (!ctx->d()->callData->thisObject.isString() && !ctx->d()->callData->thisObject.asStringObject())
return QV4::StringPrototype::method_localeCompare(ctx);
- QString thisString = ctx->callData->thisObject.toQStringNoThrow();
- QString thatString = ctx->callData->args[0].toQStringNoThrow();
+ QString thisString = ctx->d()->callData->thisObject.toQStringNoThrow();
+ QString thatString = ctx->d()->callData->args[0].toQStringNoThrow();
return QV4::Encode(QString::localeAwareCompare(thisString, thatString));
}
diff --git a/src/qml/qml/qqmllocale_p.h b/src/qml/qml/qqmllocale_p.h
index cafe448313..8ec7cbf61f 100644
--- a/src/qml/qml/qqmllocale_p.h
+++ b/src/qml/qml/qqmllocale_p.h
@@ -129,25 +129,25 @@ private:
static QV4::ReturnedValue method_localeCompare(QV4::CallContext *ctx);
};
-class QQmlLocaleData : public QV4::Object
+struct QQmlLocaleData : public QV4::Object
{
- V4_OBJECT
-public:
- QQmlLocaleData(QV4::ExecutionEngine *engine)
- : QV4::Object(engine)
- {
- setVTable(staticVTable());
- }
-
- QLocale locale;
+ struct Data : Object::Data {
+ Data(QV4::ExecutionEngine *engine)
+ : Object::Data(engine)
+ {
+ setVTable(staticVTable());
+ }
+ QLocale locale;
+ };
+ V4_OBJECT(Object)
static QLocale *getThisLocale(QV4::CallContext *ctx) {
- QQmlLocaleData *thisObject = ctx->callData->thisObject.asObject()->as<QQmlLocaleData>();
+ QQmlLocaleData *thisObject = ctx->d()->callData->thisObject.asObject()->as<QQmlLocaleData>();
if (!thisObject) {
ctx->throwTypeError();
return 0;
}
- return &thisObject->locale;
+ return &thisObject->d()->locale;
}
static QV4::ReturnedValue method_currencySymbol(QV4::CallContext *ctx);
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 36c7dfb0e9..9501b705ba 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -183,8 +183,8 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
context = new QQmlContextData;
context->isInternal = true;
- context->url = compiledData->url;
- context->urlString = compiledData->name;
+ context->url = compiledData->url();
+ context->urlString = compiledData->fileName();
context->imports = compiledData->importCache;
context->imports->addref();
context->setParent(parentContext);
@@ -261,7 +261,7 @@ bool QQmlObjectCreator::populateDeferredProperties(QObject *instance)
QV4::ScopedValue scopeObjectProtector(valueScope, declarativeData->jsWrapper.value());
Q_UNUSED(scopeObjectProtector);
QV4::ScopedObject qmlScope(valueScope, QV4::QmlContextWrapper::qmlScope(QV8Engine::get(engine), context, _scopeObject));
- QV4::Scoped<QV4::QmlBindingWrapper> qmlBindingWrapper(valueScope, new (v4->memoryManager) QV4::QmlBindingWrapper(v4->rootContext, qmlScope));
+ QV4::Scoped<QV4::QmlBindingWrapper> qmlBindingWrapper(valueScope, v4->memoryManager->alloc<QV4::QmlBindingWrapper>(v4->rootContext, qmlScope));
QV4::ExecutionContext *qmlContext = qmlBindingWrapper->context();
qSwap(_qmlContext, qmlContext);
@@ -388,7 +388,7 @@ void QQmlObjectCreator::setPropertyValue(QQmlPropertyData *property, const QV4::
QString string = binding->valueAsString(&qmlUnit->header);
// Encoded dir-separators defeat QUrl processing - decode them first
string.replace(QLatin1String("%2f"), QLatin1String("/"), Qt::CaseInsensitive);
- QUrl value = string.isEmpty() ? QUrl() : compiledData->url.resolved(QUrl(string));
+ QUrl value = string.isEmpty() ? QUrl() : compiledData->url().resolved(QUrl(string));
// Apply URL interceptor
if (engine->urlInterceptor())
value = engine->urlInterceptor()->intercept(value, QQmlAbstractUrlInterceptor::UrlString);
@@ -583,7 +583,7 @@ void QQmlObjectCreator::setPropertyValue(QQmlPropertyData *property, const QV4::
} else if (property->propType == qMetaTypeId<QList<QUrl> >()) {
Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_String);
QString urlString = binding->valueAsString(&qmlUnit->header);
- QUrl u = urlString.isEmpty() ? QUrl() : compiledData->url.resolved(QUrl(urlString));
+ QUrl u = urlString.isEmpty() ? QUrl() : compiledData->url().resolved(QUrl(urlString));
QList<QUrl> value;
value.append(u);
argv[0] = reinterpret_cast<void *>(&value);
@@ -1010,7 +1010,7 @@ void QQmlObjectCreator::setupFunctions()
void QQmlObjectCreator::recordError(const QV4::CompiledData::Location &location, const QString &description)
{
QQmlError error;
- error.setUrl(compiledData->url);
+ error.setUrl(compiledData->url());
error.setLine(location.line);
error.setColumn(location.column);
error.setDescription(description);
@@ -1067,7 +1067,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
sharedState->allCreatedObjects.push(instance);
} else {
Q_ASSERT(typeRef->component);
- Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(typeRef->component->name,
+ Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(typeRef->component->fileName(),
context->url, obj->location.line, obj->location.column));
if (typeRef->component->qmlUnit->isSingleton())
{
@@ -1127,10 +1127,19 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
QBitArray bindingsToSkip;
if (customParser) {
- QHash<int, QQmlCompiledData::CustomParserData>::ConstIterator entry = compiledData->customParserData.find(index);
- if (entry != compiledData->customParserData.constEnd()) {
- customParser->setCustomData(instance, entry->compilationArtifact, compiledData);
- bindingsToSkip = entry->bindings;
+ QHash<int, QBitArray>::ConstIterator customParserBindings = compiledData->customParserBindings.find(index);
+ if (customParserBindings != compiledData->customParserBindings.constEnd()) {
+ customParser->imports = compiledData->importCache;
+
+ QList<const QV4::CompiledData::Binding *> bindings;
+ const QV4::CompiledData::Object *obj = qmlUnit->objectAt(index);
+ for (int i = 0; i < customParserBindings->count(); ++i)
+ if (customParserBindings->testBit(i))
+ bindings << obj->bindingTable() + i;
+ customParser->applyBindings(instance, compiledData, bindings);
+
+ customParser->imports = (QQmlTypeNameCache*)0;
+ bindingsToSkip = *customParserBindings;
}
}
@@ -1154,7 +1163,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
QV4::ScopedValue scopeObjectProtector(valueScope, ddata ? ddata->jsWrapper.value() : 0);
Q_UNUSED(scopeObjectProtector);
QV4::ScopedObject qmlScope(valueScope, QV4::QmlContextWrapper::qmlScope(QV8Engine::get(engine), context, _scopeObject));
- QV4::Scoped<QV4::QmlBindingWrapper> qmlBindingWrapper(valueScope, new (v4->memoryManager) QV4::QmlBindingWrapper(v4->rootContext, qmlScope));
+ QV4::Scoped<QV4::QmlBindingWrapper> qmlBindingWrapper(valueScope, v4->memoryManager->alloc<QV4::QmlBindingWrapper>(v4->rootContext, qmlScope));
QV4::ExecutionContext *qmlContext = qmlBindingWrapper->context();
qSwap(_qmlContext, qmlContext);
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index 1075b53c5e..96f303dcb5 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -1427,7 +1427,8 @@ bool QQmlPropertyPrivate::write(QObject *object,
list << value.toInt();
v = QVariant::fromValue<QList<int> >(list);
ok = true;
- } else if (variantType == QVariant::Double && propertyType == qMetaTypeId<QList<qreal> >()) {
+ } else if ((variantType == QVariant::Double || variantType == QVariant::Int)
+ && (propertyType == qMetaTypeId<QList<qreal> >())) {
QList<qreal> list;
list << value.toReal();
v = QVariant::fromValue<QList<qreal> >(list);
@@ -1533,7 +1534,7 @@ bool QQmlPropertyPrivate::writeBinding(QObject *object,
return false;
} else if (isVarProperty) {
QV4::FunctionObject *f = result->asFunctionObject();
- if (f && f->bindingKeyFlag) {
+ if (f && f->bindingKeyFlag()) {
// we explicitly disallow this case to avoid confusion. Users can still store one
// in an array in a var property if they need to, but the common case is user error.
expression->delayedError()->setErrorDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration."));
@@ -1551,7 +1552,7 @@ bool QQmlPropertyPrivate::writeBinding(QObject *object,
writeValueProperty(object, core, QVariant(), context, flags);
} else if (type == qMetaTypeId<QJSValue>()) {
QV4::FunctionObject *f = result->asFunctionObject();
- if (f && f->bindingKeyFlag) {
+ if (f && f->bindingKeyFlag()) {
expression->delayedError()->setErrorDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration."));
expression->delayedError()->setErrorObject(object);
return false;
@@ -1569,7 +1570,7 @@ bool QQmlPropertyPrivate::writeBinding(QObject *object,
expression->delayedError()->setErrorObject(object);
return false;
} else if (QV4::FunctionObject *f = result->asFunctionObject()) {
- if (f->bindingKeyFlag)
+ if (f->bindingKeyFlag())
expression->delayedError()->setErrorDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration."));
else
expression->delayedError()->setErrorDescription(QLatin1String("Unable to assign a function to a property of any type other than var."));
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 7fc08bd114..36dc17a085 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -897,11 +897,20 @@ QQmlDataLoader::QQmlDataLoader(QQmlEngine *engine)
/*! \internal */
QQmlDataLoader::~QQmlDataLoader()
{
+ invalidate();
+}
+
+void QQmlDataLoader::invalidate()
+{
for (NetworkReplies::Iterator iter = m_networkReplies.begin(); iter != m_networkReplies.end(); ++iter)
(*iter)->release();
+ m_networkReplies.clear();
- shutdownThread();
- delete m_thread;
+ if (m_thread) {
+ shutdownThread();
+ delete m_thread;
+ m_thread = 0;
+ }
}
void QQmlDataLoader::lock()
@@ -1228,7 +1237,7 @@ void QQmlDataLoader::setCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::Cached
void QQmlDataLoader::shutdownThread()
{
- if (!m_thread->isShutdown())
+ if (m_thread && !m_thread->isShutdown())
m_thread->shutdown();
}
@@ -2207,7 +2216,7 @@ void QQmlTypeData::dataReceived(const Data &data)
QQmlEngine *qmlEngine = typeLoader()->engine();
m_document.reset(new QmlIR::Document(QV8Engine::getV4(qmlEngine)->debugger != 0));
QmlIR::IRBuilder compiler(QV8Engine::get(qmlEngine)->illegalNames());
- if (!compiler.generateFromQml(code, finalUrlString(), finalUrlString(), m_document.data())) {
+ if (!compiler.generateFromQml(code, finalUrlString(), m_document.data())) {
QList<QQmlError> errors;
foreach (const QQmlJS::DiagnosticMessage &msg, compiler.errors) {
QQmlError e;
@@ -2332,10 +2341,8 @@ void QQmlTypeData::compile()
Q_ASSERT(m_compiledData == 0);
m_compiledData = new QQmlCompiledData(typeLoader()->engine());
- m_compiledData->url = finalUrl();
- m_compiledData->name = finalUrlString();
- QQmlCompilingProfiler prof(QQmlEnginePrivate::get(typeLoader()->engine())->profiler, m_compiledData->name);
+ QQmlCompilingProfiler prof(QQmlEnginePrivate::get(typeLoader()->engine())->profiler, finalUrlString());
QQmlTypeCompiler compiler(QQmlEnginePrivate::get(typeLoader()->engine()), m_compiledData, this, m_document.data());
if (!compiler.compile()) {
@@ -2547,7 +2554,7 @@ void QQmlScriptData::initialize(QQmlEngine *engine)
QV8Engine *v8engine = ep->v8engine();
QV4::ExecutionEngine *v4 = QV8Engine::getV4(v8engine);
- m_program = new QV4::Script(v4, QV4::ObjectRef::null(), m_precompiledScript);
+ m_program = new QV4::Script(v4, 0, m_precompiledScript);
addToEngine(engine);
diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h
index b09ac15861..3d0b77e2a5 100644
--- a/src/qml/qml/qqmltypeloader_p.h
+++ b/src/qml/qml/qqmltypeloader_p.h
@@ -233,6 +233,7 @@ public:
QQmlEngine *engine() const;
void initializeEngine(QQmlExtensionInterface *, const char *);
+ void invalidate();
protected:
void shutdownThread();
diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp
index 573779acab..53afd36437 100644
--- a/src/qml/qml/qqmltypewrapper.cpp
+++ b/src/qml/qml/qqmltypewrapper.cpp
@@ -56,14 +56,15 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(QmlTypeWrapper);
-QmlTypeWrapper::QmlTypeWrapper(QV8Engine *engine)
- : Object(QV8Engine::getV4(engine)),
- v8(engine), mode(IncludeEnums), type(0), typeNamespace(0), importNamespace(0)
+QmlTypeWrapper::Data::Data(QV8Engine *engine)
+ : Object::Data(QV8Engine::getV4(engine))
+ , v8(engine)
+ , mode(IncludeEnums)
{
setVTable(staticVTable());
}
-QmlTypeWrapper::~QmlTypeWrapper()
+QmlTypeWrapper::Data::~Data()
{
if (typeNamespace)
typeNamespace->release();
@@ -71,14 +72,14 @@ QmlTypeWrapper::~QmlTypeWrapper()
bool QmlTypeWrapper::isSingleton() const
{
- return type && type->isSingleton();
+ return d()->type && d()->type->isSingleton();
}
QVariant QmlTypeWrapper::toVariant() const
{
- if (type && type->isSingleton()) {
- QQmlEngine *e = v8->engine();
- QQmlType::SingletonInstanceInfo *siinfo = type->singletonInstanceInfo();
+ if (d()->type && d()->type->isSingleton()) {
+ QQmlEngine *e = d()->v8->engine();
+ QQmlType::SingletonInstanceInfo *siinfo = d()->type->singletonInstanceInfo();
siinfo->init(e); // note: this will also create QJSValue singleton which isn't strictly required.
QObject *qobjectSingleton = siinfo->qobjectApi(e);
if (qobjectSingleton) {
@@ -98,8 +99,8 @@ ReturnedValue QmlTypeWrapper::create(QV8Engine *v8, QObject *o, QQmlType *t, Typ
ExecutionEngine *v4 = QV8Engine::getV4(v8);
Scope scope(v4);
- Scoped<QmlTypeWrapper> w(scope, new (v4->memoryManager) QmlTypeWrapper(v8));
- w->mode = mode; w->object = o; w->type = t;
+ Scoped<QmlTypeWrapper> w(scope, v4->memoryManager->alloc<QmlTypeWrapper>(v8));
+ w->d()->mode = mode; w->d()->object = o; w->d()->type = t;
return w.asReturnedValue();
}
@@ -112,14 +113,14 @@ ReturnedValue QmlTypeWrapper::create(QV8Engine *v8, QObject *o, QQmlTypeNameCach
ExecutionEngine *v4 = QV8Engine::getV4(v8);
Scope scope(v4);
- Scoped<QmlTypeWrapper> w(scope, new (v4->memoryManager) QmlTypeWrapper(v8));
- w->mode = mode; w->object = o; w->typeNamespace = t; w->importNamespace = importNamespace;
+ Scoped<QmlTypeWrapper> w(scope, v4->memoryManager->alloc<QmlTypeWrapper>(v8));
+ w->d()->mode = mode; w->d()->object = o; w->d()->typeNamespace = t; w->d()->importNamespace = importNamespace;
t->addref();
return w.asReturnedValue();
}
-ReturnedValue QmlTypeWrapper::get(Managed *m, const StringRef name, bool *hasProperty)
+ReturnedValue QmlTypeWrapper::get(Managed *m, String *name, bool *hasProperty)
{
QV4::ExecutionEngine *v4 = m->engine();
QV4::Scope scope(v4);
@@ -132,13 +133,13 @@ ReturnedValue QmlTypeWrapper::get(Managed *m, const StringRef name, bool *hasPro
if (hasProperty)
*hasProperty = true;
- QV8Engine *v8engine = w->v8;
+ QV8Engine *v8engine = w->d()->v8;
QQmlContextData *context = v8engine->callingContext();
- QObject *object = w->object;
+ QObject *object = w->d()->object;
- if (w->type) {
- QQmlType *type = w->type;
+ if (w->d()->type) {
+ QQmlType *type = w->d()->type;
// singleton types are handled differently to other types.
if (type->isSingleton()) {
@@ -150,7 +151,7 @@ ReturnedValue QmlTypeWrapper::get(Managed *m, const StringRef name, bool *hasPro
if (qobjectSingleton) {
// check for enum value
if (name->startsWithUpper()) {
- if (w->mode == IncludeEnums) {
+ if (w->d()->mode == IncludeEnums) {
// ### Optimize
QByteArray enumName = name->toQString().toUtf8();
const QMetaObject *metaObject = qobjectSingleton->metaObject();
@@ -165,7 +166,7 @@ ReturnedValue QmlTypeWrapper::get(Managed *m, const StringRef name, bool *hasPro
}
// check for property.
- return QV4::QObjectWrapper::getQmlProperty(v4->currentContext(), context, qobjectSingleton, name.getPointer(), QV4::QObjectWrapper::IgnoreRevision, hasProperty);
+ return QV4::QObjectWrapper::getQmlProperty(v4->currentContext(), context, qobjectSingleton, name, QV4::QObjectWrapper::IgnoreRevision, hasProperty);
} else if (!siinfo->scriptApi(e).isUndefined()) {
// NOTE: if used in a binding, changes will not trigger re-evaluation since non-NOTIFYable.
QV4::ScopedObject o(scope, QJSValuePrivate::get(siinfo->scriptApi(e))->getValue(v4));
@@ -185,10 +186,10 @@ ReturnedValue QmlTypeWrapper::get(Managed *m, const StringRef name, bool *hasPro
// Fall through to base implementation
- } else if (w->object) {
+ } else if (w->d()->object) {
QObject *ao = qmlAttachedPropertiesObjectById(type->attachedPropertiesId(), object);
if (ao)
- return QV4::QObjectWrapper::getQmlProperty(v4->currentContext(), context, ao, name.getPointer(), QV4::QObjectWrapper::IgnoreRevision, hasProperty);
+ return QV4::QObjectWrapper::getQmlProperty(v4->currentContext(), context, ao, name, QV4::QObjectWrapper::IgnoreRevision, hasProperty);
// Fall through to base implementation
}
@@ -198,19 +199,19 @@ ReturnedValue QmlTypeWrapper::get(Managed *m, const StringRef name, bool *hasPro
// Fall through to base implementation
- } else if (w->typeNamespace) {
- Q_ASSERT(w->importNamespace);
- QQmlTypeNameCache::Result r = w->typeNamespace->query(name, w->importNamespace);
+ } else if (w->d()->typeNamespace) {
+ Q_ASSERT(w->d()->importNamespace);
+ QQmlTypeNameCache::Result r = w->d()->typeNamespace->query(name, w->d()->importNamespace);
if (r.isValid()) {
QQmlContextData *context = v8engine->callingContext();
if (r.type) {
- return create(w->v8, object, r.type, w->mode);
+ return create(w->d()->v8, object, r.type, w->d()->mode);
} else if (r.scriptIndex != -1) {
QV4::ScopedObject scripts(scope, context->importedScripts);
return scripts->getIndexed(r.scriptIndex);
} else if (r.importNamespace) {
- return create(w->v8, object, context->imports, r.importNamespace);
+ return create(w->d()->v8, object, context->imports, r.importNamespace);
}
return QV4::Encode::undefined();
@@ -229,7 +230,7 @@ ReturnedValue QmlTypeWrapper::get(Managed *m, const StringRef name, bool *hasPro
}
-void QmlTypeWrapper::put(Managed *m, const StringRef name, const ValueRef value)
+void QmlTypeWrapper::put(Managed *m, String *name, const ValueRef value)
{
QmlTypeWrapper *w = m->as<QmlTypeWrapper>();
QV4::ExecutionEngine *v4 = m->engine();
@@ -244,12 +245,12 @@ void QmlTypeWrapper::put(Managed *m, const StringRef name, const ValueRef value)
QV8Engine *v8engine = v4->v8Engine;
QQmlContextData *context = v8engine->callingContext();
- QQmlType *type = w->type;
- if (type && !type->isSingleton() && w->object) {
- QObject *object = w->object;
+ QQmlType *type = w->d()->type;
+ if (type && !type->isSingleton() && w->d()->object) {
+ QObject *object = w->d()->object;
QObject *ao = qmlAttachedPropertiesObjectById(type->attachedPropertiesId(), object);
if (ao)
- QV4::QObjectWrapper::setQmlProperty(v4->currentContext(), context, ao, name.getPointer(), QV4::QObjectWrapper::IgnoreRevision, value);
+ QV4::QObjectWrapper::setQmlProperty(v4->currentContext(), context, ao, name, QV4::QObjectWrapper::IgnoreRevision, value);
} else if (type && type->isSingleton()) {
QQmlEngine *e = v8engine->engine();
QQmlType::SingletonInstanceInfo *siinfo = type->singletonInstanceInfo();
@@ -257,7 +258,7 @@ void QmlTypeWrapper::put(Managed *m, const StringRef name, const ValueRef value)
QObject *qobjectSingleton = siinfo->qobjectApi(e);
if (qobjectSingleton) {
- QV4::QObjectWrapper::setQmlProperty(v4->currentContext(), context, qobjectSingleton, name.getPointer(), QV4::QObjectWrapper::IgnoreRevision, value);
+ QV4::QObjectWrapper::setQmlProperty(v4->currentContext(), context, qobjectSingleton, name, QV4::QObjectWrapper::IgnoreRevision, value);
} else if (!siinfo->scriptApi(e).isUndefined()) {
QV4::ScopedObject apiprivate(scope, QJSValuePrivate::get(siinfo->scriptApi(e))->value);
if (!apiprivate) {
@@ -271,19 +272,17 @@ void QmlTypeWrapper::put(Managed *m, const StringRef name, const ValueRef value)
}
}
-PropertyAttributes QmlTypeWrapper::query(const Managed *m, StringRef name)
+PropertyAttributes QmlTypeWrapper::query(const Managed *m, String *name)
{
// ### Implement more efficiently.
- Scope scope(m->engine());
- ScopedString n(scope, name);
bool hasProperty = false;
- static_cast<Object *>(const_cast<Managed*>(m))->get(n, &hasProperty);
+ static_cast<Object *>(const_cast<Managed*>(m))->get(name, &hasProperty);
return hasProperty ? Attr_Data : Attr_Invalid;
}
void QmlTypeWrapper::destroy(Managed *that)
{
- static_cast<QmlTypeWrapper *>(that)->~QmlTypeWrapper();
+ static_cast<QmlTypeWrapper *>(that)->d()->~Data();
}
bool QmlTypeWrapper::isEqualTo(Managed *a, Managed *b)
diff --git a/src/qml/qml/qqmltypewrapper_p.h b/src/qml/qml/qqmltypewrapper_p.h
index 355a6751a9..27ecac991e 100644
--- a/src/qml/qml/qqmltypewrapper_p.h
+++ b/src/qml/qml/qqmltypewrapper_p.h
@@ -68,13 +68,23 @@ namespace QV4 {
struct Q_QML_EXPORT QmlTypeWrapper : Object
{
- V4_OBJECT
+ enum TypeNameMode { IncludeEnums, ExcludeEnums };
+
+ struct Data : Object::Data {
+ Data(QV8Engine *engine);
+ ~Data();
+ QV8Engine *v8;
+ TypeNameMode mode;
+ QPointer<QObject> object;
+
+ QQmlType *type;
+ QQmlTypeNameCache *typeNamespace;
+ const void *importNamespace;
+ };
+ V4_OBJECT(Object)
private:
- QmlTypeWrapper(QV8Engine *engine);
- ~QmlTypeWrapper();
public:
- enum TypeNameMode { IncludeEnums, ExcludeEnums };
bool isSingleton() const;
@@ -84,22 +94,13 @@ public:
static ReturnedValue create(QV8Engine *, QObject *, QQmlTypeNameCache *, const void *, TypeNameMode = IncludeEnums);
- static ReturnedValue get(Managed *m, const StringRef name, bool *hasProperty);
- static void put(Managed *m, const StringRef name, const ValueRef value);
- static PropertyAttributes query(const Managed *, StringRef name);
+ static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
+ static void put(Managed *m, String *name, const ValueRef value);
+ static PropertyAttributes query(const Managed *, String *name);
static void destroy(Managed *that);
-protected:
static bool isEqualTo(Managed *that, Managed *o);
-private:
- QV8Engine *v8;
- TypeNameMode mode;
- QPointer<QObject> object;
-
- QQmlType *type;
- QQmlTypeNameCache *typeNamespace;
- const void *importNamespace;
};
}
diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp
index 9a87493e54..1de596b4d3 100644
--- a/src/qml/qml/qqmlvaluetypewrapper.cpp
+++ b/src/qml/qml/qqmlvaluetypewrapper.cpp
@@ -59,41 +59,46 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(QmlValueTypeWrapper);
-class QmlValueTypeReference : public QmlValueTypeWrapper
+struct QmlValueTypeReference : public QmlValueTypeWrapper
{
-public:
- QmlValueTypeReference(QV8Engine *engine);
-
- QPointer<QObject> object;
- int property;
+ struct Data : QmlValueTypeWrapper::Data
+ {
+ Data(QV8Engine *engine);
+ QPointer<QObject> object;
+ int property;
+ };
+ V4_OBJECT(QmlValueTypeWrapper)
};
-class QmlValueTypeCopy : public QmlValueTypeWrapper
-{
-public:
- QmlValueTypeCopy(QV8Engine *engine);
+DEFINE_OBJECT_VTABLE(QmlValueTypeReference);
- QVariant value;
+struct QmlValueTypeCopy : public QmlValueTypeWrapper
+{
+ struct Data : QmlValueTypeWrapper::Data
+ {
+ Data(QV8Engine *engine);
+ QVariant value;
+ };
+ V4_OBJECT(QmlValueTypeWrapper)
};
-QmlValueTypeWrapper::QmlValueTypeWrapper(QV8Engine *engine, ObjectType objectType)
- : Object(QV8Engine::getV4(engine)), objectType(objectType)
-{
- v8 = engine;
- setVTable(staticVTable());
-}
+DEFINE_OBJECT_VTABLE(QmlValueTypeCopy);
-QmlValueTypeWrapper::~QmlValueTypeWrapper()
+QmlValueTypeWrapper::Data::Data(QV8Engine *engine, ObjectType objectType)
+ : Object::Data(QV8Engine::getV4(engine))
+ , v8(engine)
+ , objectType(objectType)
{
+ setVTable(staticVTable());
}
-QmlValueTypeReference::QmlValueTypeReference(QV8Engine *engine)
-: QmlValueTypeWrapper(engine, Reference)
+QmlValueTypeReference::Data::Data(QV8Engine *engine)
+ : QmlValueTypeWrapper::Data(engine, Reference)
{
}
-QmlValueTypeCopy::QmlValueTypeCopy(QV8Engine *engine)
-: QmlValueTypeWrapper(engine, Copy)
+QmlValueTypeCopy::Data::Data(QV8Engine *engine)
+ : QmlValueTypeWrapper::Data(engine, Copy)
{
}
@@ -102,30 +107,30 @@ static bool readReferenceValue(const QmlValueTypeReference *reference)
{
// A reference resource may be either a "true" reference (eg, to a QVector3D property)
// or a "variant" reference (eg, to a QVariant property which happens to contain a value-type).
- QMetaProperty writebackProperty = reference->object->metaObject()->property(reference->property);
+ QMetaProperty writebackProperty = reference->d()->object->metaObject()->property(reference->d()->property);
if (writebackProperty.userType() == QMetaType::QVariant) {
// variant-containing-value-type reference
QVariant variantReferenceValue;
- reference->type->readVariantValue(reference->object, reference->property, &variantReferenceValue);
+ reference->d()->type->readVariantValue(reference->d()->object, reference->d()->property, &variantReferenceValue);
int variantReferenceType = variantReferenceValue.userType();
- if (variantReferenceType != reference->type->userType()) {
+ if (variantReferenceType != reference->d()->type->userType()) {
// This is a stale VariantReference. That is, the variant has been
// overwritten with a different type in the meantime.
// We need to modify this reference to the updated value type, if
// possible, or return false if it is not a value type.
if (QQmlValueTypeFactory::isValueType(variantReferenceType)) {
- reference->type = QQmlValueTypeFactory::valueType(variantReferenceType);
- if (!reference->type) {
+ reference->d()->type = QQmlValueTypeFactory::valueType(variantReferenceType);
+ if (!reference->d()->type) {
return false;
}
} else {
return false;
}
}
- reference->type->setValue(variantReferenceValue);
+ reference->d()->type->setValue(variantReferenceValue);
} else {
// value-type reference
- reference->type->read(reference->object, reference->property);
+ reference->d()->type->read(reference->d()->object, reference->d()->property);
}
return true;
}
@@ -147,10 +152,10 @@ ReturnedValue QmlValueTypeWrapper::create(QV8Engine *v8, QObject *object, int pr
Scope scope(v4);
initProto(v4);
- Scoped<QmlValueTypeReference> r(scope, new (v4->memoryManager) QmlValueTypeReference(v8));
- r->setPrototype(v4->qmlExtensions()->valueTypeWrapperPrototype);
- r->type = type; r->object = object; r->property = property;
- return r.asReturnedValue();
+ QmlValueTypeReference *r = v4->memoryManager->alloc<QmlValueTypeReference>(v8);
+ r->d()->internalClass = r->d()->internalClass->changePrototype(v4->qmlExtensions()->valueTypeWrapperPrototype);
+ r->d()->type = type; r->d()->object = object; r->d()->property = property;
+ return r->asReturnedValue();
}
ReturnedValue QmlValueTypeWrapper::create(QV8Engine *v8, const QVariant &value, QQmlValueType *type)
@@ -159,45 +164,44 @@ ReturnedValue QmlValueTypeWrapper::create(QV8Engine *v8, const QVariant &value,
Scope scope(v4);
initProto(v4);
- Scoped<QmlValueTypeCopy> r(scope, new (v4->memoryManager) QmlValueTypeCopy(v8));
- r->setPrototype(v4->qmlExtensions()->valueTypeWrapperPrototype);
- r->type = type; r->value = value;
- return r.asReturnedValue();
+ QmlValueTypeCopy *r = v4->memoryManager->alloc<QmlValueTypeCopy>(v8);
+ r->d()->internalClass = r->d()->internalClass->changePrototype(v4->qmlExtensions()->valueTypeWrapperPrototype);
+ r->d()->type = type; r->d()->value = value;
+ return r->asReturnedValue();
}
QVariant QmlValueTypeWrapper::toVariant() const
{
- if (objectType == QmlValueTypeWrapper::Reference) {
+ if (d()->objectType == QmlValueTypeWrapper::Reference) {
const QmlValueTypeReference *reference = static_cast<const QmlValueTypeReference *>(this);
- if (reference->object && readReferenceValue(reference)) {
- return reference->type->value();
+ if (reference->d()->object && readReferenceValue(reference)) {
+ return reference->d()->type->value();
} else {
return QVariant();
}
} else {
- Q_ASSERT(objectType == QmlValueTypeWrapper::Copy);
- return static_cast<const QmlValueTypeCopy *>(this)->value;
+ Q_ASSERT(d()->objectType == QmlValueTypeWrapper::Copy);
+ return static_cast<const QmlValueTypeCopy *>(this)->d()->value;
}
}
void QmlValueTypeWrapper::destroy(Managed *that)
{
QmlValueTypeWrapper *w = that->as<QmlValueTypeWrapper>();
- assert(w);
- if (w->objectType == Reference)
- static_cast<QmlValueTypeReference *>(w)->~QmlValueTypeReference();
+ if (w->d()->objectType == Reference)
+ static_cast<QmlValueTypeReference *>(w)->d()->~Data();
else
- static_cast<QmlValueTypeCopy *>(w)->~QmlValueTypeCopy();
+ static_cast<QmlValueTypeCopy *>(w)->d()->~Data();
}
bool QmlValueTypeWrapper::isEqualTo(Managed *m, Managed *other)
{
QV4::QmlValueTypeWrapper *lv = m->as<QmlValueTypeWrapper>();
- assert(lv);
+ Q_ASSERT(lv);
if (QV4::VariantObject *rv = other->as<VariantObject>())
- return lv->isEqual(rv->data);
+ return lv->isEqual(rv->d()->data);
if (QV4::QmlValueTypeWrapper *v = other->as<QmlValueTypeWrapper>())
return lv->isEqual(v->toVariant());
@@ -205,7 +209,7 @@ bool QmlValueTypeWrapper::isEqualTo(Managed *m, Managed *other)
return false;
}
-PropertyAttributes QmlValueTypeWrapper::query(const Managed *m, StringRef name)
+PropertyAttributes QmlValueTypeWrapper::query(const Managed *m, String *name)
{
const QmlValueTypeWrapper *r = m->as<const QmlValueTypeWrapper>();
QV4::ExecutionEngine *v4 = m->engine();
@@ -217,59 +221,59 @@ PropertyAttributes QmlValueTypeWrapper::query(const Managed *m, StringRef name)
QQmlPropertyData local;
QQmlPropertyData *result = 0;
{
- QQmlData *ddata = QQmlData::get(r->type, false);
+ QQmlData *ddata = QQmlData::get(r->d()->type, false);
if (ddata && ddata->propertyCache)
- result = ddata->propertyCache->property(name.getPointer(), 0, 0);
+ result = ddata->propertyCache->property(name, 0, 0);
else
- result = QQmlPropertyCache::property(r->v8->engine(), r->type, name.getPointer(), 0, local);
+ result = QQmlPropertyCache::property(r->d()->v8->engine(), r->d()->type, name, 0, local);
}
return result ? Attr_Data : Attr_Invalid;
}
bool QmlValueTypeWrapper::isEqual(const QVariant& value)
{
- if (objectType == QmlValueTypeWrapper::Reference) {
+ if (d()->objectType == QmlValueTypeWrapper::Reference) {
QmlValueTypeReference *reference = static_cast<QmlValueTypeReference *>(this);
- if (reference->object && readReferenceValue(reference)) {
- return reference->type->isEqual(value);
+ if (reference->d()->object && readReferenceValue(reference)) {
+ return reference->d()->type->isEqual(value);
} else {
return false;
}
} else {
- Q_ASSERT(objectType == QmlValueTypeWrapper::Copy);
+ Q_ASSERT(d()->objectType == QmlValueTypeWrapper::Copy);
QmlValueTypeCopy *copy = static_cast<QmlValueTypeCopy *>(this);
- type->setValue(copy->value);
- if (type->isEqual(value))
+ d()->type->setValue(copy->d()->value);
+ if (d()->type->isEqual(value))
return true;
- return (value == copy->value);
+ return (value == copy->d()->value);
}
}
ReturnedValue QmlValueTypeWrapper::method_toString(CallContext *ctx)
{
- Object *o = ctx->callData->thisObject.asObject();
+ Object *o = ctx->d()->callData->thisObject.asObject();
if (!o)
return ctx->throwTypeError();
QmlValueTypeWrapper *w = o->as<QmlValueTypeWrapper>();
if (!w)
return ctx->throwTypeError();
- if (w->objectType == QmlValueTypeWrapper::Reference) {
+ if (w->d()->objectType == QmlValueTypeWrapper::Reference) {
QmlValueTypeReference *reference = static_cast<QmlValueTypeReference *>(w);
- if (reference->object && readReferenceValue(reference)) {
- return w->v8->toString(w->type->toString());
+ if (reference->d()->object && readReferenceValue(reference)) {
+ return w->d()->v8->toString(w->d()->type->toString());
} else {
return QV4::Encode::undefined();
}
} else {
- Q_ASSERT(w->objectType == QmlValueTypeWrapper::Copy);
+ Q_ASSERT(w->d()->objectType == QmlValueTypeWrapper::Copy);
QmlValueTypeCopy *copy = static_cast<QmlValueTypeCopy *>(w);
- w->type->setValue(copy->value);
- return w->v8->toString(w->type->toString());
+ w->d()->type->setValue(copy->d()->value);
+ return w->d()->v8->toString(w->d()->type->toString());
}
}
-ReturnedValue QmlValueTypeWrapper::get(Managed *m, const StringRef name, bool *hasProperty)
+ReturnedValue QmlValueTypeWrapper::get(Managed *m, String *name, bool *hasProperty)
{
QmlValueTypeWrapper *r = m->as<QmlValueTypeWrapper>();
QV4::ExecutionEngine *v4 = m->engine();
@@ -277,28 +281,28 @@ ReturnedValue QmlValueTypeWrapper::get(Managed *m, const StringRef name, bool *h
return v4->currentContext()->throwTypeError();
// Note: readReferenceValue() can change the reference->type.
- if (r->objectType == QmlValueTypeWrapper::Reference) {
+ if (r->d()->objectType == QmlValueTypeWrapper::Reference) {
QmlValueTypeReference *reference = static_cast<QmlValueTypeReference *>(r);
- if (!reference->object || !readReferenceValue(reference))
+ if (!reference->d()->object || !readReferenceValue(reference))
return Primitive::undefinedValue().asReturnedValue();
} else {
- Q_ASSERT(r->objectType == QmlValueTypeWrapper::Copy);
+ Q_ASSERT(r->d()->objectType == QmlValueTypeWrapper::Copy);
QmlValueTypeCopy *copy = static_cast<QmlValueTypeCopy *>(r);
- r->type->setValue(copy->value);
+ r->d()->type->setValue(copy->d()->value);
}
QQmlPropertyData local;
QQmlPropertyData *result = 0;
{
- QQmlData *ddata = QQmlData::get(r->type, false);
+ QQmlData *ddata = QQmlData::get(r->d()->type, false);
if (ddata && ddata->propertyCache)
- result = ddata->propertyCache->property(name.getPointer(), 0, 0);
+ result = ddata->propertyCache->property(name, 0, 0);
else
- result = QQmlPropertyCache::property(r->v8->engine(), r->type, name, 0, local);
+ result = QQmlPropertyCache::property(r->d()->v8->engine(), r->d()->type, name, 0, local);
}
if (!result)
@@ -307,31 +311,31 @@ ReturnedValue QmlValueTypeWrapper::get(Managed *m, const StringRef name, bool *h
if (result->isFunction()) {
// calling a Q_INVOKABLE function of a value type
QQmlContextData *qmlContext = QV4::QmlContextWrapper::callingContext(v4);
- return QV4::QObjectWrapper::getQmlProperty(v4->currentContext(), qmlContext, r->type, name.getPointer(), QV4::QObjectWrapper::IgnoreRevision);
+ return QV4::QObjectWrapper::getQmlProperty(v4->currentContext(), qmlContext, r->d()->type, name, QV4::QObjectWrapper::IgnoreRevision);
}
#define VALUE_TYPE_LOAD(metatype, cpptype, constructor) \
if (result->propType == metatype) { \
cpptype v; \
void *args[] = { &v, 0 }; \
- r->type->qt_metacall(QMetaObject::ReadProperty, result->coreIndex, args); \
+ r->d()->type->qt_metacall(QMetaObject::ReadProperty, result->coreIndex, args); \
return constructor(v); \
}
// These four types are the most common used by the value type wrappers
VALUE_TYPE_LOAD(QMetaType::QReal, qreal, QV4::Encode);
VALUE_TYPE_LOAD(QMetaType::Int, int, QV4::Encode);
- VALUE_TYPE_LOAD(QMetaType::QString, QString, r->v8->toString);
+ VALUE_TYPE_LOAD(QMetaType::QString, QString, r->d()->v8->toString);
VALUE_TYPE_LOAD(QMetaType::Bool, bool, QV4::Encode);
QVariant v(result->propType, (void *)0);
void *args[] = { v.data(), 0 };
- r->type->qt_metacall(QMetaObject::ReadProperty, result->coreIndex, args);
- return r->v8->fromVariant(v);
+ r->d()->type->qt_metacall(QMetaObject::ReadProperty, result->coreIndex, args);
+ return r->d()->v8->fromVariant(v);
#undef VALUE_TYPE_ACCESSOR
}
-void QmlValueTypeWrapper::put(Managed *m, const StringRef name, const ValueRef value)
+void QmlValueTypeWrapper::put(Managed *m, String *name, const ValueRef value)
{
ExecutionEngine *v4 = m->engine();
Scope scope(v4);
@@ -345,38 +349,38 @@ void QmlValueTypeWrapper::put(Managed *m, const StringRef name, const ValueRef v
}
QByteArray propName = name->toQString().toUtf8();
- if (r->objectType == QmlValueTypeWrapper::Reference) {
+ if (r->d()->objectType == QmlValueTypeWrapper::Reference) {
QmlValueTypeReference *reference = static_cast<QmlValueTypeReference *>(r.getPointer());
- QMetaProperty writebackProperty = reference->object->metaObject()->property(reference->property);
+ QMetaProperty writebackProperty = reference->d()->object->metaObject()->property(reference->d()->property);
- if (!reference->object || !writebackProperty.isWritable() || !readReferenceValue(reference))
+ if (!reference->d()->object || !writebackProperty.isWritable() || !readReferenceValue(reference))
return;
// we lookup the index after readReferenceValue() since it can change the reference->type.
- int index = r->type->metaObject()->indexOfProperty(propName.constData());
+ int index = r->d()->type->metaObject()->indexOfProperty(propName.constData());
if (index == -1)
return;
- QMetaProperty p = r->type->metaObject()->property(index);
+ QMetaProperty p = r->d()->type->metaObject()->property(index);
QQmlBinding *newBinding = 0;
QV4::ScopedFunctionObject f(scope, value);
if (f) {
- if (!f->bindingKeyFlag) {
+ if (!f->bindingKeyFlag()) {
// assigning a JS function to a non-var-property is not allowed.
QString error = QLatin1String("Cannot assign JavaScript function to value-type property");
- Scoped<String> e(scope, r->v8->toString(error));
+ Scoped<String> e(scope, r->d()->v8->toString(error));
v4->currentContext()->throwError(e);
return;
}
- QQmlContextData *context = r->v8->callingContext();
+ QQmlContextData *context = r->d()->v8->callingContext();
QQmlPropertyData cacheData;
cacheData.setFlags(QQmlPropertyData::IsWritable |
QQmlPropertyData::IsValueTypeVirtual);
- cacheData.propType = reference->object->metaObject()->property(reference->property).userType();
- cacheData.coreIndex = reference->property;
+ cacheData.propType = reference->d()->object->metaObject()->property(reference->d()->property).userType();
+ cacheData.coreIndex = reference->d()->property;
cacheData.valueTypeFlags = 0;
cacheData.valueTypeCoreIndex = index;
cacheData.valueTypePropType = p.userType();
@@ -384,46 +388,46 @@ void QmlValueTypeWrapper::put(Managed *m, const StringRef name, const ValueRef v
QV4::Scoped<QQmlBindingFunction> bindingFunction(scope, f);
bindingFunction->initBindingLocation();
- newBinding = new QQmlBinding(value, reference->object, context);
- newBinding->setTarget(reference->object, cacheData, context);
+ newBinding = new QQmlBinding(value, reference->d()->object, context);
+ newBinding->setTarget(reference->d()->object, cacheData, context);
}
QQmlAbstractBinding *oldBinding =
- QQmlPropertyPrivate::setBinding(reference->object, reference->property, index, newBinding);
+ QQmlPropertyPrivate::setBinding(reference->d()->object, reference->d()->property, index, newBinding);
if (oldBinding)
oldBinding->destroy();
if (!f) {
- QVariant v = r->v8->toVariant(value, -1);
+ QVariant v = r->d()->v8->toVariant(value, -1);
if (p.isEnumType() && (QMetaType::Type)v.type() == QMetaType::Double)
v = v.toInt();
- p.write(reference->type, v);
+ p.write(reference->d()->type, v);
if (writebackProperty.userType() == QMetaType::QVariant) {
- QVariant variantReferenceValue = r->type->value();
- reference->type->writeVariantValue(reference->object, reference->property, 0, &variantReferenceValue);
+ QVariant variantReferenceValue = r->d()->type->value();
+ reference->d()->type->writeVariantValue(reference->d()->object, reference->d()->property, 0, &variantReferenceValue);
} else {
- reference->type->write(reference->object, reference->property, 0);
+ reference->d()->type->write(reference->d()->object, reference->d()->property, 0);
}
}
} else {
- Q_ASSERT(r->objectType == QmlValueTypeWrapper::Copy);
+ Q_ASSERT(r->d()->objectType == QmlValueTypeWrapper::Copy);
QmlValueTypeCopy *copy = static_cast<QmlValueTypeCopy *>(r.getPointer());
- int index = r->type->metaObject()->indexOfProperty(propName.constData());
+ int index = r->d()->type->metaObject()->indexOfProperty(propName.constData());
if (index == -1)
return;
- QVariant v = r->v8->toVariant(value, -1);
+ QVariant v = r->d()->v8->toVariant(value, -1);
- r->type->setValue(copy->value);
- QMetaProperty p = r->type->metaObject()->property(index);
- p.write(r->type, v);
- copy->value = r->type->value();
+ r->d()->type->setValue(copy->d()->value);
+ QMetaProperty p = r->d()->type->metaObject()->property(index);
+ p.write(r->d()->type, v);
+ copy->d()->value = r->d()->type->value();
}
}
diff --git a/src/qml/qml/qqmlvaluetypewrapper_p.h b/src/qml/qml/qqmlvaluetypewrapper_p.h
index d66dbbba0c..53d5ae95af 100644
--- a/src/qml/qml/qqmlvaluetypewrapper_p.h
+++ b/src/qml/qml/qqmlvaluetypewrapper_p.h
@@ -68,11 +68,14 @@ namespace QV4 {
struct Q_QML_EXPORT QmlValueTypeWrapper : Object
{
- V4_OBJECT
-protected:
enum ObjectType { Reference, Copy };
- QmlValueTypeWrapper(QV8Engine *engine, ObjectType type);
- ~QmlValueTypeWrapper();
+ struct Data : Object::Data {
+ Data(QV8Engine *engine, ObjectType type);
+ QV8Engine *v8;
+ ObjectType objectType;
+ mutable QQmlValueType *type;
+ };
+ V4_OBJECT(Object)
public:
@@ -82,19 +85,14 @@ public:
QVariant toVariant() const;
bool isEqual(const QVariant& value);
-
- static ReturnedValue get(Managed *m, const StringRef name, bool *hasProperty);
- static void put(Managed *m, const StringRef name, const ValueRef value);
+ static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
+ static void put(Managed *m, String *name, const ValueRef value);
static void destroy(Managed *that);
static bool isEqualTo(Managed *m, Managed *other);
- static PropertyAttributes query(const Managed *, StringRef name);
+ static PropertyAttributes query(const Managed *, String *name);
static QV4::ReturnedValue method_toString(CallContext *ctx);
- QV8Engine *v8;
- ObjectType objectType;
- mutable QQmlValueType *type;
-
static void initProto(ExecutionEngine *v4);
};
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index 1ff95a245d..2f04984264 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -1087,7 +1087,7 @@ void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value)
// And, if the new value is a scarce resource, we need to ensure that it does not get
// automatically released by the engine until no other references to it exist.
QV4::ScopedValue newv(scope, QQmlEnginePrivate::get(ctxt->engine)->v8engine()->fromVariant(value));
- QV4::VariantObjectRef v = newv;
+ QV4::Scoped<QV4::VariantObject> v(scope, newv);
if (!!v)
v->addVmePropertyReference();
diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp
index d89dc92b68..e7bea80a18 100644
--- a/src/qml/qml/qqmlxmlhttprequest.cpp
+++ b/src/qml/qml/qqmlxmlhttprequest.cpp
@@ -72,7 +72,7 @@ using namespace QV4;
#ifndef QT_NO_XMLSTREAMREADER
#define V4THROW_REFERENCE(string) { \
- Scoped<Object> error(scope, ctx->engine->newReferenceErrorObject(QStringLiteral(string))); \
+ Scoped<Object> error(scope, ctx->engine()->newReferenceErrorObject(QStringLiteral(string))); \
return ctx->throwError(error); \
}
@@ -105,9 +105,9 @@ static ReturnedValue constructMeObject(const ValueRef thisObj, QV8Engine *e)
ExecutionEngine *v4 = QV8Engine::getV4(e);
Scope scope(v4);
Scoped<Object> meObj(scope, v4->newObject());
- meObj->put(ScopedString(scope, v4->newString(QStringLiteral("ThisObject"))), thisObj);
+ meObj->put(ScopedString(scope, v4->newString(QStringLiteral("ThisObject"))).getPointer(), thisObj);
ScopedValue v(scope, QmlContextWrapper::qmlScope(e, e->callingContext(), 0));
- meObj->put(ScopedString(scope, v4->newString(QStringLiteral("ActivationObject"))), v);
+ meObj->put(ScopedString(scope, v4->newString(QStringLiteral("ActivationObject"))).getPointer(), v);
return meObj.asReturnedValue();
}
@@ -185,96 +185,101 @@ public:
class NamedNodeMap : public Object
{
- V4_OBJECT
public:
- NamedNodeMap(ExecutionEngine *engine, NodeImpl *data, const QList<NodeImpl *> &list)
- : Object(engine)
- , list(list)
- , d(data)
- {
- setVTable(staticVTable());
+ struct Data : Object::Data {
+ Data(ExecutionEngine *engine, NodeImpl *data, const QList<NodeImpl *> &list)
+ : Object::Data(engine)
+ , list(list)
+ , d(data)
+ {
+ setVTable(staticVTable());
- if (d)
- d->addref();
- }
- ~NamedNodeMap() {
- if (d)
- d->release();
- }
+ if (d)
+ d->addref();
+ }
+ ~Data() {
+ if (d)
+ d->release();
+ }
+ QList<NodeImpl *> list; // Only used in NamedNodeMap
+ NodeImpl *d;
+ };
+ V4_OBJECT(Object)
// C++ API
static ReturnedValue create(QV8Engine *, NodeImpl *, const QList<NodeImpl *> &);
// JS API
static void destroy(Managed *that) {
- that->as<NamedNodeMap>()->~NamedNodeMap();
+ that->as<NamedNodeMap>()->d()->~Data();
}
- static ReturnedValue get(Managed *m, const StringRef name, bool *hasProperty);
+ static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
-
- QList<NodeImpl *> list; // Only used in NamedNodeMap
- NodeImpl *d;
};
DEFINE_OBJECT_VTABLE(NamedNodeMap);
class NodeList : public Object
{
- V4_OBJECT
public:
- NodeList(ExecutionEngine *engine, NodeImpl *data)
- : Object(engine)
- , d(data)
- {
- setVTable(staticVTable());
+ struct Data : Object::Data {
+ Data(ExecutionEngine *engine, NodeImpl *data)
+ : Object::Data(engine)
+ , d(data)
+ {
+ setVTable(staticVTable());
- if (d)
- d->addref();
- }
- ~NodeList() {
- if (d)
- d->release();
- }
+ if (d)
+ d->addref();
+ }
+ ~Data() {
+ if (d)
+ d->release();
+ }
+ NodeImpl *d;
+ };
+ V4_OBJECT(Object)
// JS API
static void destroy(Managed *that) {
- that->as<NodeList>()->~NodeList();
+ that->as<NodeList>()->d()->~Data();
}
- static ReturnedValue get(Managed *m, const StringRef name, bool *hasProperty);
+ static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
// C++ API
static ReturnedValue create(QV8Engine *, NodeImpl *);
- NodeImpl *d;
};
DEFINE_OBJECT_VTABLE(NodeList);
class NodePrototype : public Object
{
- V4_OBJECT
public:
- NodePrototype(ExecutionEngine *engine)
- : Object(engine)
- {
- setVTable(staticVTable());
-
- Scope scope(engine);
- ScopedObject protectThis(scope, this);
-
- defineAccessorProperty(QStringLiteral("nodeName"), method_get_nodeName, 0);
- defineAccessorProperty(QStringLiteral("nodeValue"), method_get_nodeValue, 0);
- defineAccessorProperty(QStringLiteral("nodeType"), method_get_nodeType, 0);
-
- defineAccessorProperty(QStringLiteral("parentNode"), method_get_parentNode, 0);
- defineAccessorProperty(QStringLiteral("childNodes"), method_get_childNodes, 0);
- defineAccessorProperty(QStringLiteral("firstChild"), method_get_firstChild, 0);
- defineAccessorProperty(QStringLiteral("lastChild"), method_get_lastChild, 0);
- defineAccessorProperty(QStringLiteral("previousSibling"), method_get_previousSibling, 0);
- defineAccessorProperty(QStringLiteral("nextSibling"), method_get_nextSibling, 0);
- defineAccessorProperty(QStringLiteral("attributes"), method_get_attributes, 0);
- }
+ struct Data : Object::Data {
+ Data(ExecutionEngine *engine)
+ : Object::Data(engine)
+ {
+ setVTable(staticVTable());
+
+ Scope scope(engine);
+ ScopedObject o(scope, this);
+
+ o->defineAccessorProperty(QStringLiteral("nodeName"), method_get_nodeName, 0);
+ o->defineAccessorProperty(QStringLiteral("nodeValue"), method_get_nodeValue, 0);
+ o->defineAccessorProperty(QStringLiteral("nodeType"), method_get_nodeType, 0);
+
+ o->defineAccessorProperty(QStringLiteral("parentNode"), method_get_parentNode, 0);
+ o->defineAccessorProperty(QStringLiteral("childNodes"), method_get_childNodes, 0);
+ o->defineAccessorProperty(QStringLiteral("firstChild"), method_get_firstChild, 0);
+ o->defineAccessorProperty(QStringLiteral("lastChild"), method_get_lastChild, 0);
+ o->defineAccessorProperty(QStringLiteral("previousSibling"), method_get_previousSibling, 0);
+ o->defineAccessorProperty(QStringLiteral("nextSibling"), method_get_nextSibling, 0);
+ o->defineAccessorProperty(QStringLiteral("attributes"), method_get_attributes, 0);
+ }
+ };
+ V4_OBJECT(Object)
static void initClass(ExecutionEngine *engine);
@@ -304,39 +309,40 @@ public:
DEFINE_OBJECT_VTABLE(NodePrototype);
-class Node : public Object
+struct Node : public Object
{
- V4_OBJECT
+ struct Data : Object::Data {
+ Data(ExecutionEngine *engine, NodeImpl *data)
+ : Object::Data(engine)
+ , d(data)
+ {
+ setVTable(staticVTable());
- Node(ExecutionEngine *engine, NodeImpl *data)
- : Object(engine)
- , d(data)
- {
- setVTable(staticVTable());
+ if (d)
+ d->addref();
+ }
+ ~Data() {
+ if (d)
+ d->release();
+ }
+ NodeImpl *d;
+ };
+ V4_OBJECT(Object)
- if (d)
- d->addref();
- }
- ~Node() {
- if (d)
- d->release();
- }
// JS API
static void destroy(Managed *that) {
- that->as<Node>()->~Node();
+ that->as<Node>()->d()->~Data();
}
// C++ API
static ReturnedValue create(QV8Engine *, NodeImpl *);
- Node(const Node &o);
bool isNull() const;
- NodeImpl *d;
-
private:
Node &operator=(const Node &);
+ Node(const Node &o);
};
DEFINE_OBJECT_VTABLE(Node);
@@ -420,12 +426,12 @@ void NodeImpl::release()
ReturnedValue NodePrototype::method_get_nodeName(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Node> r(scope, ctx->callData->thisObject.as<Node>());
+ Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
if (!r)
return ctx->throwTypeError();
QString name;
- switch (r->d->type) {
+ switch (r->d()->d->type) {
case NodeImpl::Document:
name = QStringLiteral("#document");
break;
@@ -436,52 +442,52 @@ ReturnedValue NodePrototype::method_get_nodeName(CallContext *ctx)
name = QStringLiteral("#text");
break;
default:
- name = r->d->name;
+ name = r->d()->d->name;
break;
}
- return Encode(ctx->engine->newString(name));
+ return Encode(ctx->d()->engine->newString(name));
}
ReturnedValue NodePrototype::method_get_nodeValue(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Node> r(scope, ctx->callData->thisObject.as<Node>());
+ Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
if (!r)
return ctx->throwTypeError();
- if (r->d->type == NodeImpl::Document ||
- r->d->type == NodeImpl::DocumentFragment ||
- r->d->type == NodeImpl::DocumentType ||
- r->d->type == NodeImpl::Element ||
- r->d->type == NodeImpl::Entity ||
- r->d->type == NodeImpl::EntityReference ||
- r->d->type == NodeImpl::Notation)
+ if (r->d()->d->type == NodeImpl::Document ||
+ r->d()->d->type == NodeImpl::DocumentFragment ||
+ r->d()->d->type == NodeImpl::DocumentType ||
+ r->d()->d->type == NodeImpl::Element ||
+ r->d()->d->type == NodeImpl::Entity ||
+ r->d()->d->type == NodeImpl::EntityReference ||
+ r->d()->d->type == NodeImpl::Notation)
return Encode::null();
- return Encode(ctx->engine->newString(r->d->data));
+ return Encode(ctx->d()->engine->newString(r->d()->d->data));
}
ReturnedValue NodePrototype::method_get_nodeType(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Node> r(scope, ctx->callData->thisObject.as<Node>());
+ Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
if (!r)
return ctx->throwTypeError();
- return Encode(r->d->type);
+ return Encode(r->d()->d->type);
}
ReturnedValue NodePrototype::method_get_parentNode(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Node> r(scope, ctx->callData->thisObject.as<Node>());
+ Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
if (!r)
return ctx->throwTypeError();
- QV8Engine *engine = ctx->engine->v8Engine;
+ QV8Engine *engine = ctx->d()->engine->v8Engine;
- if (r->d->parent)
- return Node::create(engine, r->d->parent);
+ if (r->d()->d->parent)
+ return Node::create(engine, r->d()->d->parent);
else
return Encode::null();
}
@@ -489,63 +495,63 @@ ReturnedValue NodePrototype::method_get_parentNode(CallContext *ctx)
ReturnedValue NodePrototype::method_get_childNodes(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Node> r(scope, ctx->callData->thisObject.as<Node>());
+ Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
if (!r)
return ctx->throwTypeError();
- QV8Engine *engine = ctx->engine->v8Engine;
+ QV8Engine *engine = ctx->d()->engine->v8Engine;
- return NodeList::create(engine, r->d);
+ return NodeList::create(engine, r->d()->d);
}
ReturnedValue NodePrototype::method_get_firstChild(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Node> r(scope, ctx->callData->thisObject.as<Node>());
+ Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
if (!r)
return ctx->throwTypeError();
- QV8Engine *engine = ctx->engine->v8Engine;
+ QV8Engine *engine = ctx->d()->engine->v8Engine;
- if (r->d->children.isEmpty())
+ if (r->d()->d->children.isEmpty())
return Encode::null();
else
- return Node::create(engine, r->d->children.first());
+ return Node::create(engine, r->d()->d->children.first());
}
ReturnedValue NodePrototype::method_get_lastChild(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Node> r(scope, ctx->callData->thisObject.as<Node>());
+ Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
if (!r)
return ctx->throwTypeError();
- QV8Engine *engine = ctx->engine->v8Engine;
+ QV8Engine *engine = ctx->d()->engine->v8Engine;
- if (r->d->children.isEmpty())
+ if (r->d()->d->children.isEmpty())
return Encode::null();
else
- return Node::create(engine, r->d->children.last());
+ return Node::create(engine, r->d()->d->children.last());
}
ReturnedValue NodePrototype::method_get_previousSibling(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Node> r(scope, ctx->callData->thisObject.as<Node>());
+ Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
if (!r)
return ctx->throwTypeError();
- QV8Engine *engine = ctx->engine->v8Engine;
+ QV8Engine *engine = ctx->d()->engine->v8Engine;
- if (!r->d->parent)
+ if (!r->d()->d->parent)
return Encode::null();
- for (int ii = 0; ii < r->d->parent->children.count(); ++ii) {
- if (r->d->parent->children.at(ii) == r->d) {
+ for (int ii = 0; ii < r->d()->d->parent->children.count(); ++ii) {
+ if (r->d()->d->parent->children.at(ii) == r->d()->d) {
if (ii == 0)
return Encode::null();
else
- return Node::create(engine, r->d->parent->children.at(ii - 1));
+ return Node::create(engine, r->d()->d->parent->children.at(ii - 1));
}
}
@@ -555,21 +561,21 @@ ReturnedValue NodePrototype::method_get_previousSibling(CallContext *ctx)
ReturnedValue NodePrototype::method_get_nextSibling(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Node> r(scope, ctx->callData->thisObject.as<Node>());
+ Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
if (!r)
return ctx->throwTypeError();
- QV8Engine *engine = ctx->engine->v8Engine;
+ QV8Engine *engine = ctx->d()->engine->v8Engine;
- if (!r->d->parent)
+ if (!r->d()->d->parent)
return Encode::null();
- for (int ii = 0; ii < r->d->parent->children.count(); ++ii) {
- if (r->d->parent->children.at(ii) == r->d) {
- if ((ii + 1) == r->d->parent->children.count())
+ for (int ii = 0; ii < r->d()->d->parent->children.count(); ++ii) {
+ if (r->d()->d->parent->children.at(ii) == r->d()->d) {
+ if ((ii + 1) == r->d()->d->parent->children.count())
return Encode::null();
else
- return Node::create(engine, r->d->parent->children.at(ii + 1));
+ return Node::create(engine, r->d()->d->parent->children.at(ii + 1));
}
}
@@ -579,16 +585,16 @@ ReturnedValue NodePrototype::method_get_nextSibling(CallContext *ctx)
ReturnedValue NodePrototype::method_get_attributes(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Node> r(scope, ctx->callData->thisObject.as<Node>());
+ Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
if (!r)
return ctx->throwTypeError();
- QV8Engine *engine = ctx->engine->v8Engine;
+ QV8Engine *engine = ctx->d()->engine->v8Engine;
- if (r->d->type != NodeImpl::Element)
+ if (r->d()->d->type != NodeImpl::Element)
return Encode::null();
else
- return NamedNodeMap::create(engine, r->d, r->d->attributes);
+ return NamedNodeMap::create(engine, r->d()->d, r->d()->d->attributes);
}
ReturnedValue NodePrototype::getProto(ExecutionEngine *v4)
@@ -596,7 +602,7 @@ ReturnedValue NodePrototype::getProto(ExecutionEngine *v4)
Scope scope(v4);
QQmlXMLHttpRequestData *d = xhrdata(v4->v8Engine);
if (d->nodePrototype.isUndefined()) {
- ScopedObject p(scope, new (v4->memoryManager) NodePrototype(v4));
+ ScopedObject p(scope, v4->memoryManager->alloc<NodePrototype>(v4));
d->nodePrototype = p;
v4->v8Engine->freezeObject(p);
}
@@ -608,7 +614,7 @@ ReturnedValue Node::create(QV8Engine *engine, NodeImpl *data)
ExecutionEngine *v4 = QV8Engine::getV4(engine);
Scope scope(v4);
- Scoped<Node> instance(scope, new (v4->memoryManager) Node(v4, data));
+ Scoped<Node> instance(scope, v4->memoryManager->alloc<Node>(v4, data));
ScopedObject p(scope);
switch (data->type) {
@@ -673,45 +679,45 @@ ReturnedValue Attr::prototype(ExecutionEngine *engine)
ReturnedValue Attr::method_name(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Node> r(scope, ctx->callData->thisObject.as<Node>());
+ Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
if (!r)
return Encode::undefined();
- QV8Engine *engine = ctx->engine->v8Engine;
+ QV8Engine *engine = ctx->d()->engine->v8Engine;
- return engine->toString(r->d->name);
+ return engine->toString(r->d()->d->name);
}
ReturnedValue Attr::method_value(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Node> r(scope, ctx->callData->thisObject.as<Node>());
+ Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
if (!r)
return Encode::undefined();
- QV8Engine *engine = ctx->engine->v8Engine;
+ QV8Engine *engine = ctx->d()->engine->v8Engine;
- return engine->toString(r->d->data);
+ return engine->toString(r->d()->d->data);
}
ReturnedValue Attr::method_ownerElement(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Node> r(scope, ctx->callData->thisObject.as<Node>());
+ Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
if (!r)
return Encode::undefined();
- QV8Engine *engine = ctx->engine->v8Engine;
+ QV8Engine *engine = ctx->d()->engine->v8Engine;
- return Node::create(engine, r->d->parent);
+ return Node::create(engine, r->d()->d->parent);
}
ReturnedValue CharacterData::method_length(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Node> r(scope, ctx->callData->thisObject.as<Node>());
+ Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
if (!r)
return Encode::undefined();
- QV8Engine *engine = ctx->engine->v8Engine;
+ QV8Engine *engine = ctx->d()->engine->v8Engine;
Q_UNUSED(engine)
- return Encode(r->d->data.length());
+ return Encode(r->d()->d->data.length());
}
ReturnedValue CharacterData::prototype(ExecutionEngine *v4)
@@ -733,21 +739,21 @@ ReturnedValue CharacterData::prototype(ExecutionEngine *v4)
ReturnedValue Text::method_isElementContentWhitespace(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Node> r(scope, ctx->callData->thisObject.as<Node>());
+ Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
if (!r) return Encode::undefined();
- return Encode(r->d->data.trimmed().isEmpty());
+ return Encode(r->d()->d->data.trimmed().isEmpty());
}
ReturnedValue Text::method_wholeText(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Node> r(scope, ctx->callData->thisObject.as<Node>());
+ Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
if (!r)
return Encode::undefined();
- QV8Engine *engine = ctx->engine->v8Engine;
+ QV8Engine *engine = ctx->d()->engine->v8Engine;
- return engine->toString(r->d->data);
+ return engine->toString(r->d()->d->data);
}
ReturnedValue Text::prototype(ExecutionEngine *v4)
@@ -883,22 +889,15 @@ ReturnedValue Document::load(QV8Engine *engine, const QByteArray &data)
return Encode::null();
}
- ScopedObject instance(scope, new (v4->memoryManager) Node(v4, document));
+ ScopedObject instance(scope, v4->memoryManager->alloc<Node>(v4, document));
ScopedObject p(scope);
instance->setPrototype((p = Document::prototype(v4)).getPointer());
return instance.asReturnedValue();
}
-Node::Node(const Node &o)
- : Object(o.engine()), d(o.d)
-{
- if (d)
- d->addref();
-}
-
bool Node::isNull() const
{
- return d == 0;
+ return d()->d == 0;
}
ReturnedValue NamedNodeMap::getIndexed(Managed *m, uint index, bool *hasProperty)
@@ -913,17 +912,17 @@ ReturnedValue NamedNodeMap::getIndexed(Managed *m, uint index, bool *hasProperty
QV8Engine *engine = v4->v8Engine;
- if ((int)index < r->list.count()) {
+ if ((int)index < r->d()->list.count()) {
if (hasProperty)
*hasProperty = true;
- return Node::create(engine, r->list.at(index));
+ return Node::create(engine, r->d()->list.at(index));
}
if (hasProperty)
*hasProperty = false;
return Encode::undefined();
}
-ReturnedValue NamedNodeMap::get(Managed *m, const StringRef name, bool *hasProperty)
+ReturnedValue NamedNodeMap::get(Managed *m, String *name, bool *hasProperty)
{
NamedNodeMap *r = m->as<NamedNodeMap>();
QV4::ExecutionEngine *v4 = m->engine();
@@ -932,16 +931,16 @@ ReturnedValue NamedNodeMap::get(Managed *m, const StringRef name, bool *hasPrope
name->makeIdentifier();
if (name->equals(v4->id_length))
- return Primitive::fromInt32(r->list.count()).asReturnedValue();
+ return Primitive::fromInt32(r->d()->list.count()).asReturnedValue();
QV8Engine *engine = v4->v8Engine;
QString str = name->toQString();
- for (int ii = 0; ii < r->list.count(); ++ii) {
- if (r->list.at(ii)->name == str) {
+ for (int ii = 0; ii < r->d()->list.count(); ++ii) {
+ if (r->d()->list.at(ii)->name == str) {
if (hasProperty)
*hasProperty = true;
- return Node::create(engine, r->list.at(ii));
+ return Node::create(engine, r->d()->list.at(ii));
}
}
@@ -953,10 +952,7 @@ ReturnedValue NamedNodeMap::get(Managed *m, const StringRef name, bool *hasPrope
ReturnedValue NamedNodeMap::create(QV8Engine *engine, NodeImpl *data, const QList<NodeImpl *> &list)
{
ExecutionEngine *v4 = QV8Engine::getV4(engine);
- Scope scope(v4);
-
- Scoped<NamedNodeMap> instance(scope, new (v4->memoryManager) NamedNodeMap(v4, data, list));
- return instance.asReturnedValue();
+ return (v4->memoryManager->alloc<NamedNodeMap>(v4, data, list))->asReturnedValue();
}
ReturnedValue NodeList::getIndexed(Managed *m, uint index, bool *hasProperty)
@@ -971,17 +967,17 @@ ReturnedValue NodeList::getIndexed(Managed *m, uint index, bool *hasProperty)
QV8Engine *engine = v4->v8Engine;
- if ((int)index < r->d->children.count()) {
+ if ((int)index < r->d()->d->children.count()) {
if (hasProperty)
*hasProperty = true;
- return Node::create(engine, r->d->children.at(index));
+ return Node::create(engine, r->d()->d->children.at(index));
}
if (hasProperty)
*hasProperty = false;
return Encode::undefined();
}
-ReturnedValue NodeList::get(Managed *m, const StringRef name, bool *hasProperty)
+ReturnedValue NodeList::get(Managed *m, String *name, bool *hasProperty)
{
QV4::ExecutionEngine *v4 = m->engine();
NodeList *r = m->as<NodeList>();
@@ -991,60 +987,58 @@ ReturnedValue NodeList::get(Managed *m, const StringRef name, bool *hasProperty)
name->makeIdentifier();
if (name->equals(v4->id_length))
- return Primitive::fromInt32(r->d->children.count()).asReturnedValue();
+ return Primitive::fromInt32(r->d()->d->children.count()).asReturnedValue();
return Object::get(m, name, hasProperty);
}
ReturnedValue NodeList::create(QV8Engine *engine, NodeImpl *data)
{
ExecutionEngine *v4 = QV8Engine::getV4(engine);
- Scope scope(v4);
- Scoped<NodeList> instance(scope, new (v4->memoryManager) NodeList(v4, data));
- return instance.asReturnedValue();
+ return (v4->memoryManager->alloc<NodeList>(v4, data))->asReturnedValue();
}
ReturnedValue Document::method_documentElement(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Node> r(scope, ctx->callData->thisObject.as<Node>());
- if (!r || r->d->type != NodeImpl::Document)
+ Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
+ if (!r || r->d()->d->type != NodeImpl::Document)
return Encode::undefined();
- QV8Engine *engine = ctx->engine->v8Engine;
+ QV8Engine *engine = ctx->d()->engine->v8Engine;
- return Node::create(engine, static_cast<DocumentImpl *>(r->d)->root);
+ return Node::create(engine, static_cast<DocumentImpl *>(r->d()->d)->root);
}
ReturnedValue Document::method_xmlStandalone(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Node> r(scope, ctx->callData->thisObject.as<Node>());
- if (!r || r->d->type != NodeImpl::Document)
+ Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
+ if (!r || r->d()->d->type != NodeImpl::Document)
return Encode::undefined();
- QV8Engine *engine = ctx->engine->v8Engine;
+ QV8Engine *engine = ctx->d()->engine->v8Engine;
Q_UNUSED(engine)
- return Encode(static_cast<DocumentImpl *>(r->d)->isStandalone);
+ return Encode(static_cast<DocumentImpl *>(r->d()->d)->isStandalone);
}
ReturnedValue Document::method_xmlVersion(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Node> r(scope, ctx->callData->thisObject.as<Node>());
- if (!r || r->d->type != NodeImpl::Document)
+ Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
+ if (!r || r->d()->d->type != NodeImpl::Document)
return Encode::undefined();
- QV8Engine *engine = ctx->engine->v8Engine;
+ QV8Engine *engine = ctx->d()->engine->v8Engine;
- return engine->toString(static_cast<DocumentImpl *>(r->d)->version);
+ return engine->toString(static_cast<DocumentImpl *>(r->d()->d)->version);
}
ReturnedValue Document::method_xmlEncoding(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Node> r(scope, ctx->callData->thisObject.as<Node>());
- if (!r || r->d->type != NodeImpl::Document)
+ Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
+ if (!r || r->d()->d->type != NodeImpl::Document)
return Encode::undefined();
- QV8Engine *engine = ctx->engine->v8Engine;
+ QV8Engine *engine = ctx->d()->engine->v8Engine;
- return engine->toString(static_cast<DocumentImpl *>(r->d)->encoding);
+ return engine->toString(static_cast<DocumentImpl *>(r->d()->d)->encoding);
}
class QQmlXMLHttpRequest : public QObject
@@ -1551,21 +1545,21 @@ void QQmlXMLHttpRequest::dispatchCallbackImpl(const ValueRef me)
}
ScopedString s(scope, v4->newString(QStringLiteral("ThisObject")));
- Scoped<Object> thisObj(scope, o->get(s));
+ Scoped<Object> thisObj(scope, o->get(s.getPointer()));
if (!thisObj) {
ctx->throwError(QStringLiteral("QQmlXMLHttpRequest: internal error: empty ThisObject"));
return;
}
s = v4->newString(QStringLiteral("onreadystatechange"));
- Scoped<FunctionObject> callback(scope, thisObj->get(s));
+ Scoped<FunctionObject> callback(scope, thisObj->get(s.getPointer()));
if (!callback) {
// not an error, but no onreadystatechange function to call.
return;
}
s = v4->newString(QStringLiteral("ActivationObject"));
- Scoped<Object> activationObject(scope, o->get(s));
+ Scoped<Object> activationObject(scope, o->get(s.getPointer()));
if (!activationObject) {
v4->currentContext()->throwError(QStringLiteral("QQmlXMLHttpRequest: internal error: empty ActivationObject"));
return;
@@ -1607,56 +1601,54 @@ void QQmlXMLHttpRequest::destroyNetwork()
struct QQmlXMLHttpRequestWrapper : public Object
{
- V4_OBJECT
- QQmlXMLHttpRequestWrapper(ExecutionEngine *engine, QQmlXMLHttpRequest *request)
- : Object(engine)
- , request(request)
- {
- setVTable(staticVTable());
- }
- ~QQmlXMLHttpRequestWrapper() {
- delete request;
- }
+ struct Data : Object::Data {
+ Data(ExecutionEngine *engine, QQmlXMLHttpRequest *request)
+ : Object::Data(engine)
+ , request(request)
+ {
+ setVTable(staticVTable());
+ }
+ ~Data() {
+ delete request;
+ }
+ QQmlXMLHttpRequest *request;
+ };
+ V4_OBJECT(Object)
static void destroy(Managed *that) {
- that->as<QQmlXMLHttpRequestWrapper>()->~QQmlXMLHttpRequestWrapper();
+ that->as<QQmlXMLHttpRequestWrapper>()->d()->~Data();
}
-
- QQmlXMLHttpRequest *request;
};
DEFINE_OBJECT_VTABLE(QQmlXMLHttpRequestWrapper);
struct QQmlXMLHttpRequestCtor : public FunctionObject
{
- V4_OBJECT
- QQmlXMLHttpRequestCtor(ExecutionEngine *engine)
- : FunctionObject(engine->rootContext, QStringLiteral("XMLHttpRequest"))
- {
- setVTable(staticVTable());
- Scope scope(engine);
- ScopedValue protectThis(scope, this);
-
- defineReadonlyProperty(QStringLiteral("UNSENT"), Primitive::fromInt32(0));
- defineReadonlyProperty(QStringLiteral("OPENED"), Primitive::fromInt32(1));
- defineReadonlyProperty(QStringLiteral("HEADERS_RECEIVED"), Primitive::fromInt32(2));
- defineReadonlyProperty(QStringLiteral("LOADING"), Primitive::fromInt32(3));
- defineReadonlyProperty(QStringLiteral("DONE"), Primitive::fromInt32(4));
- if (!proto)
- setupProto();
- ScopedString s(scope, engine->id_prototype);
- defineDefaultProperty(s, ScopedObject(scope, proto));
- }
- ~QQmlXMLHttpRequestCtor()
- {}
-
- static void destroy(Managed *that) {
- that->as<QQmlXMLHttpRequestCtor>()->~QQmlXMLHttpRequestCtor();
- }
+ struct Data : FunctionObject::Data {
+ Data(ExecutionEngine *engine)
+ : FunctionObject::Data(engine->rootContext, QStringLiteral("XMLHttpRequest"))
+ {
+ setVTable(staticVTable());
+ Scope scope(engine);
+ Scoped<QQmlXMLHttpRequestCtor> ctor(scope, this);
+
+ ctor->defineReadonlyProperty(QStringLiteral("UNSENT"), Primitive::fromInt32(0));
+ ctor->defineReadonlyProperty(QStringLiteral("OPENED"), Primitive::fromInt32(1));
+ ctor->defineReadonlyProperty(QStringLiteral("HEADERS_RECEIVED"), Primitive::fromInt32(2));
+ ctor->defineReadonlyProperty(QStringLiteral("LOADING"), Primitive::fromInt32(3));
+ ctor->defineReadonlyProperty(QStringLiteral("DONE"), Primitive::fromInt32(4));
+ if (!ctor->d()->proto)
+ ctor->setupProto();
+ ScopedString s(scope, engine->id_prototype);
+ ctor->defineDefaultProperty(s.getPointer(), ScopedObject(scope, ctor->d()->proto));
+ }
+ Object *proto;
+ };
+ V4_OBJECT(FunctionObject)
static void markObjects(Managed *that, ExecutionEngine *e) {
QQmlXMLHttpRequestCtor *c = that->as<QQmlXMLHttpRequestCtor>();
- if (c->proto)
- c->proto->mark(e);
+ if (c->d()->proto)
+ c->d()->proto->mark(e);
FunctionObject::markObjects(that, e);
}
static ReturnedValue construct(Managed *that, QV4::CallData *)
@@ -1668,8 +1660,8 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject
QV8Engine *engine = that->engine()->v8Engine;
QQmlXMLHttpRequest *r = new QQmlXMLHttpRequest(engine, engine->networkAccessManager());
- Scoped<QQmlXMLHttpRequestWrapper> w(scope, new (that->engine()->memoryManager) QQmlXMLHttpRequestWrapper(that->engine(), r));
- w->setPrototype(ctor->proto);
+ Scoped<QQmlXMLHttpRequestWrapper> w(scope, that->engine()->memoryManager->alloc<QQmlXMLHttpRequestWrapper>(that->engine(), r));
+ w->setPrototype(ctor->d()->proto);
return w.asReturnedValue();
}
@@ -1691,9 +1683,6 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject
static ReturnedValue method_get_statusText(CallContext *ctx);
static ReturnedValue method_get_responseText(CallContext *ctx);
static ReturnedValue method_get_responseXML(CallContext *ctx);
-
-
- Object *proto;
};
DEFINE_OBJECT_VTABLE(QQmlXMLHttpRequestCtor);
@@ -1703,29 +1692,29 @@ void QQmlXMLHttpRequestCtor::setupProto()
ExecutionEngine *v4 = engine();
Scope scope(v4);
Scoped<Object> p(scope, v4->newObject());
- proto = p.getPointer();
+ d()->proto = p.getPointer();
// Methods
- proto->defineDefaultProperty(QStringLiteral("open"), method_open);
- proto->defineDefaultProperty(QStringLiteral("setRequestHeader"), method_setRequestHeader);
- proto->defineDefaultProperty(QStringLiteral("send"), method_send);
- proto->defineDefaultProperty(QStringLiteral("abort"), method_abort);
- proto->defineDefaultProperty(QStringLiteral("getResponseHeader"), method_getResponseHeader);
- proto->defineDefaultProperty(QStringLiteral("getAllResponseHeaders"), method_getAllResponseHeaders);
+ d()->proto->defineDefaultProperty(QStringLiteral("open"), method_open);
+ d()->proto->defineDefaultProperty(QStringLiteral("setRequestHeader"), method_setRequestHeader);
+ d()->proto->defineDefaultProperty(QStringLiteral("send"), method_send);
+ d()->proto->defineDefaultProperty(QStringLiteral("abort"), method_abort);
+ d()->proto->defineDefaultProperty(QStringLiteral("getResponseHeader"), method_getResponseHeader);
+ d()->proto->defineDefaultProperty(QStringLiteral("getAllResponseHeaders"), method_getAllResponseHeaders);
// Read-only properties
- proto->defineAccessorProperty(QStringLiteral("readyState"), method_get_readyState, 0);
- proto->defineAccessorProperty(QStringLiteral("status"),method_get_status, 0);
- proto->defineAccessorProperty(QStringLiteral("statusText"),method_get_statusText, 0);
- proto->defineAccessorProperty(QStringLiteral("responseText"),method_get_responseText, 0);
- proto->defineAccessorProperty(QStringLiteral("responseXML"),method_get_responseXML, 0);
+ d()->proto->defineAccessorProperty(QStringLiteral("readyState"), method_get_readyState, 0);
+ d()->proto->defineAccessorProperty(QStringLiteral("status"),method_get_status, 0);
+ d()->proto->defineAccessorProperty(QStringLiteral("statusText"),method_get_statusText, 0);
+ d()->proto->defineAccessorProperty(QStringLiteral("responseText"),method_get_responseText, 0);
+ d()->proto->defineAccessorProperty(QStringLiteral("responseXML"),method_get_responseXML, 0);
// State values
- proto->defineReadonlyProperty(QStringLiteral("UNSENT"), Primitive::fromInt32(0));
- proto->defineReadonlyProperty(QStringLiteral("OPENED"), Primitive::fromInt32(1));
- proto->defineReadonlyProperty(QStringLiteral("HEADERS_RECEIVED"), Primitive::fromInt32(2));
- proto->defineReadonlyProperty(QStringLiteral("LOADING"), Primitive::fromInt32(3));
- proto->defineReadonlyProperty(QStringLiteral("DONE"), Primitive::fromInt32(4));
+ d()->proto->defineReadonlyProperty(QStringLiteral("UNSENT"), Primitive::fromInt32(0));
+ d()->proto->defineReadonlyProperty(QStringLiteral("OPENED"), Primitive::fromInt32(1));
+ d()->proto->defineReadonlyProperty(QStringLiteral("HEADERS_RECEIVED"), Primitive::fromInt32(2));
+ d()->proto->defineReadonlyProperty(QStringLiteral("LOADING"), Primitive::fromInt32(3));
+ d()->proto->defineReadonlyProperty(QStringLiteral("DONE"), Primitive::fromInt32(4));
}
@@ -1733,18 +1722,18 @@ void QQmlXMLHttpRequestCtor::setupProto()
ReturnedValue QQmlXMLHttpRequestCtor::method_open(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->callData->thisObject.as<QQmlXMLHttpRequestWrapper>());
+ Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->d()->callData->thisObject.as<QQmlXMLHttpRequestWrapper>());
if (!w)
V4THROW_REFERENCE("Not an XMLHttpRequest object");
- QQmlXMLHttpRequest *r = w->request;
+ QQmlXMLHttpRequest *r = w->d()->request;
- if (ctx->callData->argc < 2 || ctx->callData->argc > 5)
+ if (ctx->d()->callData->argc < 2 || ctx->d()->callData->argc > 5)
V4THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count");
- QV8Engine *engine = ctx->engine->v8Engine;
+ QV8Engine *engine = ctx->d()->engine->v8Engine;
// Argument 0 - Method
- QString method = ctx->callData->args[0].toQStringNoThrow().toUpper();
+ QString method = ctx->d()->callData->args[0].toQStringNoThrow().toUpper();
if (method != QLatin1String("GET") &&
method != QLatin1String("PUT") &&
method != QLatin1String("HEAD") &&
@@ -1753,21 +1742,21 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_open(CallContext *ctx)
V4THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Unsupported HTTP method type");
// Argument 1 - URL
- QUrl url = QUrl(ctx->callData->args[1].toQStringNoThrow());
+ QUrl url = QUrl(ctx->d()->callData->args[1].toQStringNoThrow());
if (url.isRelative())
url = engine->callingContext()->resolvedUrl(url);
// Argument 2 - async (optional)
- if (ctx->callData->argc > 2 && !ctx->callData->args[2].booleanValue())
+ if (ctx->d()->callData->argc > 2 && !ctx->d()->callData->args[2].booleanValue())
V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "Synchronous XMLHttpRequest calls are not supported");
// Argument 3/4 - user/pass (optional)
QString username, password;
- if (ctx->callData->argc > 3)
- username = ctx->callData->args[3].toQStringNoThrow();
- if (ctx->callData->argc > 4)
- password = ctx->callData->args[4].toQStringNoThrow();
+ if (ctx->d()->callData->argc > 3)
+ username = ctx->d()->callData->args[3].toQStringNoThrow();
+ if (ctx->d()->callData->argc > 4)
+ password = ctx->d()->callData->args[4].toQStringNoThrow();
// Clear the fragment (if any)
url.setFragment(QString());
@@ -1776,26 +1765,26 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_open(CallContext *ctx)
if (!username.isNull()) url.setUserName(username);
if (!password.isNull()) url.setPassword(password);
- ScopedValue meObject(scope, constructMeObject(ctx->callData->thisObject, engine));
+ ScopedValue meObject(scope, constructMeObject(ctx->d()->callData->thisObject, engine));
return r->open(meObject, method, url);
}
ReturnedValue QQmlXMLHttpRequestCtor::method_setRequestHeader(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->callData->thisObject.as<QQmlXMLHttpRequestWrapper>());
+ Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->d()->callData->thisObject.as<QQmlXMLHttpRequestWrapper>());
if (!w)
V4THROW_REFERENCE("Not an XMLHttpRequest object");
- QQmlXMLHttpRequest *r = w->request;
+ QQmlXMLHttpRequest *r = w->d()->request;
- if (ctx->callData->argc != 2)
+ if (ctx->d()->callData->argc != 2)
V4THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count");
if (r->readyState() != QQmlXMLHttpRequest::Opened || r->sendFlag())
V4THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
- QString name = ctx->callData->args[0].toQStringNoThrow();
- QString value = ctx->callData->args[1].toQStringNoThrow();
+ QString name = ctx->d()->callData->args[0].toQStringNoThrow();
+ QString value = ctx->d()->callData->args[1].toQStringNoThrow();
// ### Check that name and value are well formed
@@ -1830,48 +1819,48 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_setRequestHeader(CallContext *ctx)
ReturnedValue QQmlXMLHttpRequestCtor::method_send(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->callData->thisObject.as<QQmlXMLHttpRequestWrapper>());
+ Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->d()->callData->thisObject.as<QQmlXMLHttpRequestWrapper>());
if (!w)
V4THROW_REFERENCE("Not an XMLHttpRequest object");
- QQmlXMLHttpRequest *r = w->request;
+ QQmlXMLHttpRequest *r = w->d()->request;
- QV8Engine *engine = ctx->engine->v8Engine;
+ QV8Engine *engine = ctx->d()->engine->v8Engine;
if (r->readyState() != QQmlXMLHttpRequest::Opened ||
r->sendFlag())
V4THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
QByteArray data;
- if (ctx->callData->argc > 0)
- data = ctx->callData->args[0].toQStringNoThrow().toUtf8();
+ if (ctx->d()->callData->argc > 0)
+ data = ctx->d()->callData->args[0].toQStringNoThrow().toUtf8();
- ScopedValue meObject(scope, constructMeObject(ctx->callData->thisObject, engine));
+ ScopedValue meObject(scope, constructMeObject(ctx->d()->callData->thisObject, engine));
return r->send(meObject, data);
}
ReturnedValue QQmlXMLHttpRequestCtor::method_abort(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->callData->thisObject.as<QQmlXMLHttpRequestWrapper>());
+ Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->d()->callData->thisObject.as<QQmlXMLHttpRequestWrapper>());
if (!w)
V4THROW_REFERENCE("Not an XMLHttpRequest object");
- QQmlXMLHttpRequest *r = w->request;
+ QQmlXMLHttpRequest *r = w->d()->request;
- ScopedValue meObject(scope, constructMeObject(ctx->callData->thisObject, ctx->engine->v8Engine));
+ ScopedValue meObject(scope, constructMeObject(ctx->d()->callData->thisObject, ctx->d()->engine->v8Engine));
return r->abort(meObject);
}
ReturnedValue QQmlXMLHttpRequestCtor::method_getResponseHeader(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->callData->thisObject.as<QQmlXMLHttpRequestWrapper>());
+ Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->d()->callData->thisObject.as<QQmlXMLHttpRequestWrapper>());
if (!w)
V4THROW_REFERENCE("Not an XMLHttpRequest object");
- QQmlXMLHttpRequest *r = w->request;
+ QQmlXMLHttpRequest *r = w->d()->request;
- QV8Engine *engine = ctx->engine->v8Engine;
+ QV8Engine *engine = ctx->d()->engine->v8Engine;
- if (ctx->callData->argc != 1)
+ if (ctx->d()->callData->argc != 1)
V4THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count");
if (r->readyState() != QQmlXMLHttpRequest::Loading &&
@@ -1879,20 +1868,20 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_getResponseHeader(CallContext *ctx)
r->readyState() != QQmlXMLHttpRequest::HeadersReceived)
V4THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
- return engine->toString(r->header(ctx->callData->args[0].toQStringNoThrow()));
+ return engine->toString(r->header(ctx->d()->callData->args[0].toQStringNoThrow()));
}
ReturnedValue QQmlXMLHttpRequestCtor::method_getAllResponseHeaders(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->callData->thisObject.as<QQmlXMLHttpRequestWrapper>());
+ Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->d()->callData->thisObject.as<QQmlXMLHttpRequestWrapper>());
if (!w)
V4THROW_REFERENCE("Not an XMLHttpRequest object");
- QQmlXMLHttpRequest *r = w->request;
+ QQmlXMLHttpRequest *r = w->d()->request;
- QV8Engine *engine = ctx->engine->v8Engine;
+ QV8Engine *engine = ctx->d()->engine->v8Engine;
- if (ctx->callData->argc != 0)
+ if (ctx->d()->callData->argc != 0)
V4THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count");
if (r->readyState() != QQmlXMLHttpRequest::Loading &&
@@ -1907,10 +1896,10 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_getAllResponseHeaders(CallContext *
ReturnedValue QQmlXMLHttpRequestCtor::method_get_readyState(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->callData->thisObject.as<QQmlXMLHttpRequestWrapper>());
+ Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->d()->callData->thisObject.as<QQmlXMLHttpRequestWrapper>());
if (!w)
V4THROW_REFERENCE("Not an XMLHttpRequest object");
- QQmlXMLHttpRequest *r = w->request;
+ QQmlXMLHttpRequest *r = w->d()->request;
return Encode(r->readyState());
}
@@ -1918,10 +1907,10 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_get_readyState(CallContext *ctx)
ReturnedValue QQmlXMLHttpRequestCtor::method_get_status(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->callData->thisObject.as<QQmlXMLHttpRequestWrapper>());
+ Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->d()->callData->thisObject.as<QQmlXMLHttpRequestWrapper>());
if (!w)
V4THROW_REFERENCE("Not an XMLHttpRequest object");
- QQmlXMLHttpRequest *r = w->request;
+ QQmlXMLHttpRequest *r = w->d()->request;
if (r->readyState() == QQmlXMLHttpRequest::Unsent ||
r->readyState() == QQmlXMLHttpRequest::Opened)
@@ -1936,12 +1925,12 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_get_status(CallContext *ctx)
ReturnedValue QQmlXMLHttpRequestCtor::method_get_statusText(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->callData->thisObject.as<QQmlXMLHttpRequestWrapper>());
+ Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->d()->callData->thisObject.as<QQmlXMLHttpRequestWrapper>());
if (!w)
V4THROW_REFERENCE("Not an XMLHttpRequest object");
- QQmlXMLHttpRequest *r = w->request;
+ QQmlXMLHttpRequest *r = w->d()->request;
- QV8Engine *engine = ctx->engine->v8Engine;
+ QV8Engine *engine = ctx->d()->engine->v8Engine;
if (r->readyState() == QQmlXMLHttpRequest::Unsent ||
r->readyState() == QQmlXMLHttpRequest::Opened)
@@ -1956,12 +1945,12 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_get_statusText(CallContext *ctx)
ReturnedValue QQmlXMLHttpRequestCtor::method_get_responseText(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->callData->thisObject.as<QQmlXMLHttpRequestWrapper>());
+ Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->d()->callData->thisObject.as<QQmlXMLHttpRequestWrapper>());
if (!w)
V4THROW_REFERENCE("Not an XMLHttpRequest object");
- QQmlXMLHttpRequest *r = w->request;
+ QQmlXMLHttpRequest *r = w->d()->request;
- QV8Engine *engine = ctx->engine->v8Engine;
+ QV8Engine *engine = ctx->d()->engine->v8Engine;
if (r->readyState() != QQmlXMLHttpRequest::Loading &&
r->readyState() != QQmlXMLHttpRequest::Done)
@@ -1973,17 +1962,17 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_get_responseText(CallContext *ctx)
ReturnedValue QQmlXMLHttpRequestCtor::method_get_responseXML(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->callData->thisObject.as<QQmlXMLHttpRequestWrapper>());
+ Scoped<QQmlXMLHttpRequestWrapper> w(scope, ctx->d()->callData->thisObject.as<QQmlXMLHttpRequestWrapper>());
if (!w)
V4THROW_REFERENCE("Not an XMLHttpRequest object");
- QQmlXMLHttpRequest *r = w->request;
+ QQmlXMLHttpRequest *r = w->d()->request;
if (!r->receivedXml() ||
(r->readyState() != QQmlXMLHttpRequest::Loading &&
r->readyState() != QQmlXMLHttpRequest::Done)) {
return Encode::null();
} else {
- return Document::load(ctx->engine->v8Engine, r->rawResponseBody());
+ return Document::load(ctx->d()->engine->v8Engine, r->rawResponseBody());
}
}
@@ -1998,9 +1987,9 @@ void *qt_add_qmlxmlhttprequest(QV8Engine *engine)
ExecutionEngine *v4 = QV8Engine::getV4(engine);
Scope scope(v4);
- Scoped<QQmlXMLHttpRequestCtor> ctor(scope, new (v4->memoryManager) QQmlXMLHttpRequestCtor(v4));
+ Scoped<QQmlXMLHttpRequestCtor> ctor(scope, v4->memoryManager->alloc<QQmlXMLHttpRequestCtor>(v4));
ScopedString s(scope, v4->newString(QStringLiteral("XMLHttpRequest")));
- v4->globalObject->defineReadonlyProperty(s, ctor);
+ v4->globalObject->defineReadonlyProperty(s.getPointer(), ctor);
QQmlXMLHttpRequestData *data = new QQmlXMLHttpRequestData;
return data;
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index a7db7d214e..e07d97e67c 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -47,6 +47,7 @@
#include <private/qqmlstringconverters_p.h>
#include <private/qqmllocale_p.h>
#include <private/qv8engine_p.h>
+#include <QFileInfo>
#include <private/qqmlprofilerservice_p.h>
#include <private/qqmlglobal_p.h>
@@ -85,15 +86,13 @@ struct StaticQtMetaObject : public QObject
{ return &staticQtMetaObject; }
};
-QV4::QtObject::QtObject(ExecutionEngine *v4, QQmlEngine *qmlEngine)
- : Object(v4)
- , m_platform(0)
- , m_application(0)
+QV4::QtObject::Data::Data(ExecutionEngine *v4, QQmlEngine *qmlEngine)
+ : Object::Data(v4)
{
setVTable(staticVTable());
Scope scope(v4);
- ScopedObject protectThis(scope, this);
+ ScopedObject o(scope, this);
// Set all the enums from the "Qt" namespace
const QMetaObject *qtMetaObject = StaticQtMetaObject::get();
@@ -102,54 +101,54 @@ QV4::QtObject::QtObject(ExecutionEngine *v4, QQmlEngine *qmlEngine)
for (int ii = 0; ii < qtMetaObject->enumeratorCount(); ++ii) {
QMetaEnum enumerator = qtMetaObject->enumerator(ii);
for (int jj = 0; jj < enumerator.keyCount(); ++jj) {
- put((str = v4->newString(QString::fromUtf8(enumerator.key(jj)))), (v = QV4::Primitive::fromInt32(enumerator.value(jj))));
+ o->put((str = v4->newString(QString::fromUtf8(enumerator.key(jj)))).getPointer(), (v = QV4::Primitive::fromInt32(enumerator.value(jj))));
}
}
- put((str = v4->newString(QStringLiteral("Asynchronous"))), (v = QV4::Primitive::fromInt32(0)));
- put((str = v4->newString(QStringLiteral("Synchronous"))), (v = QV4::Primitive::fromInt32(1)));
-
- defineDefaultProperty(QStringLiteral("include"), QV4Include::method_include);
- defineDefaultProperty(QStringLiteral("isQtObject"), method_isQtObject);
- defineDefaultProperty(QStringLiteral("rgba"), method_rgba);
- defineDefaultProperty(QStringLiteral("hsla"), method_hsla);
- defineDefaultProperty(QStringLiteral("colorEqual"), method_colorEqual);
- defineDefaultProperty(QStringLiteral("rect"), method_rect);
- defineDefaultProperty(QStringLiteral("point"), method_point);
- defineDefaultProperty(QStringLiteral("size"), method_size);
- defineDefaultProperty(QStringLiteral("font"), method_font);
-
- defineDefaultProperty(QStringLiteral("vector2d"), method_vector2d);
- defineDefaultProperty(QStringLiteral("vector3d"), method_vector3d);
- defineDefaultProperty(QStringLiteral("vector4d"), method_vector4d);
- defineDefaultProperty(QStringLiteral("quaternion"), method_quaternion);
- defineDefaultProperty(QStringLiteral("matrix4x4"), method_matrix4x4);
-
- defineDefaultProperty(QStringLiteral("formatDate"), method_formatDate);
- defineDefaultProperty(QStringLiteral("formatTime"), method_formatTime);
- defineDefaultProperty(QStringLiteral("formatDateTime"), method_formatDateTime);
-
- defineDefaultProperty(QStringLiteral("openUrlExternally"), method_openUrlExternally);
- defineDefaultProperty(QStringLiteral("fontFamilies"), method_fontFamilies);
- defineDefaultProperty(QStringLiteral("md5"), method_md5);
- defineDefaultProperty(QStringLiteral("btoa"), method_btoa);
- defineDefaultProperty(QStringLiteral("atob"), method_atob);
- defineDefaultProperty(QStringLiteral("resolvedUrl"), method_resolvedUrl);
- defineDefaultProperty(QStringLiteral("locale"), method_locale);
- defineDefaultProperty(QStringLiteral("binding"), method_binding);
+ o->put((str = v4->newString(QStringLiteral("Asynchronous"))).getPointer(), (v = QV4::Primitive::fromInt32(0)));
+ o->put((str = v4->newString(QStringLiteral("Synchronous"))).getPointer(), (v = QV4::Primitive::fromInt32(1)));
+
+ o->defineDefaultProperty(QStringLiteral("include"), QV4Include::method_include);
+ o->defineDefaultProperty(QStringLiteral("isQtObject"), method_isQtObject);
+ o->defineDefaultProperty(QStringLiteral("rgba"), method_rgba);
+ o->defineDefaultProperty(QStringLiteral("hsla"), method_hsla);
+ o->defineDefaultProperty(QStringLiteral("colorEqual"), method_colorEqual);
+ o->defineDefaultProperty(QStringLiteral("rect"), method_rect);
+ o->defineDefaultProperty(QStringLiteral("point"), method_point);
+ o->defineDefaultProperty(QStringLiteral("size"), method_size);
+ o->defineDefaultProperty(QStringLiteral("font"), method_font);
+
+ o->defineDefaultProperty(QStringLiteral("vector2d"), method_vector2d);
+ o->defineDefaultProperty(QStringLiteral("vector3d"), method_vector3d);
+ o->defineDefaultProperty(QStringLiteral("vector4d"), method_vector4d);
+ o->defineDefaultProperty(QStringLiteral("quaternion"), method_quaternion);
+ o->defineDefaultProperty(QStringLiteral("matrix4x4"), method_matrix4x4);
+
+ o->defineDefaultProperty(QStringLiteral("formatDate"), method_formatDate);
+ o->defineDefaultProperty(QStringLiteral("formatTime"), method_formatTime);
+ o->defineDefaultProperty(QStringLiteral("formatDateTime"), method_formatDateTime);
+
+ o->defineDefaultProperty(QStringLiteral("openUrlExternally"), method_openUrlExternally);
+ o->defineDefaultProperty(QStringLiteral("fontFamilies"), method_fontFamilies);
+ o->defineDefaultProperty(QStringLiteral("md5"), method_md5);
+ o->defineDefaultProperty(QStringLiteral("btoa"), method_btoa);
+ o->defineDefaultProperty(QStringLiteral("atob"), method_atob);
+ o->defineDefaultProperty(QStringLiteral("resolvedUrl"), method_resolvedUrl);
+ o->defineDefaultProperty(QStringLiteral("locale"), method_locale);
+ o->defineDefaultProperty(QStringLiteral("binding"), method_binding);
if (qmlEngine) {
- defineDefaultProperty(QStringLiteral("lighter"), method_lighter);
- defineDefaultProperty(QStringLiteral("darker"), method_darker);
- defineDefaultProperty(QStringLiteral("tint"), method_tint);
- defineDefaultProperty(QStringLiteral("quit"), method_quit);
- defineDefaultProperty(QStringLiteral("createQmlObject"), method_createQmlObject);
- defineDefaultProperty(QStringLiteral("createComponent"), method_createComponent);
+ o->defineDefaultProperty(QStringLiteral("lighter"), method_lighter);
+ o->defineDefaultProperty(QStringLiteral("darker"), method_darker);
+ o->defineDefaultProperty(QStringLiteral("tint"), method_tint);
+ o->defineDefaultProperty(QStringLiteral("quit"), method_quit);
+ o->defineDefaultProperty(QStringLiteral("createQmlObject"), method_createQmlObject);
+ o->defineDefaultProperty(QStringLiteral("createComponent"), method_createComponent);
}
- defineAccessorProperty(QStringLiteral("platform"), method_get_platform, 0);
- defineAccessorProperty(QStringLiteral("application"), method_get_application, 0);
+ o->defineAccessorProperty(QStringLiteral("platform"), method_get_platform, 0);
+ o->defineAccessorProperty(QStringLiteral("application"), method_get_application, 0);
#ifndef QT_NO_IM
- defineAccessorProperty(QStringLiteral("inputMethod"), method_get_inputMethod, 0);
+ o->defineAccessorProperty(QStringLiteral("inputMethod"), method_get_inputMethod, 0);
#endif
}
@@ -160,10 +159,10 @@ Returns true if \c object is a valid reference to a Qt or QML object, otherwise
*/
ReturnedValue QtObject::method_isQtObject(QV4::CallContext *ctx)
{
- if (ctx->callData->argc == 0)
+ if (ctx->d()->callData->argc == 0)
return QV4::Encode(false);
- return QV4::Encode(ctx->callData->args[0].as<QV4::QObjectWrapper>() != 0);
+ return QV4::Encode(ctx->d()->callData->args[0].as<QV4::QObjectWrapper>() != 0);
}
/*!
@@ -174,14 +173,14 @@ All components should be in the range 0-1 inclusive.
*/
ReturnedValue QtObject::method_rgba(QV4::CallContext *ctx)
{
- int argCount = ctx->callData->argc;
+ int argCount = ctx->d()->callData->argc;
if (argCount < 3 || argCount > 4)
V4THROW_ERROR("Qt.rgba(): Invalid arguments");
- double r = ctx->callData->args[0].toNumber();
- double g = ctx->callData->args[1].toNumber();
- double b = ctx->callData->args[2].toNumber();
- double a = (argCount == 4) ? ctx->callData->args[3].toNumber() : 1;
+ double r = ctx->d()->callData->args[0].toNumber();
+ double g = ctx->d()->callData->args[1].toNumber();
+ double b = ctx->d()->callData->args[2].toNumber();
+ double a = (argCount == 4) ? ctx->d()->callData->args[3].toNumber() : 1;
if (r < 0.0) r=0.0;
if (r > 1.0) r=1.0;
@@ -192,7 +191,7 @@ ReturnedValue QtObject::method_rgba(QV4::CallContext *ctx)
if (a < 0.0) a=0.0;
if (a > 1.0) a=1.0;
- return ctx->engine->v8Engine->fromVariant(QQml_colorProvider()->fromRgbF(r, g, b, a));
+ return ctx->d()->engine->v8Engine->fromVariant(QQml_colorProvider()->fromRgbF(r, g, b, a));
}
/*!
@@ -203,14 +202,14 @@ All components should be in the range 0-1 inclusive.
*/
ReturnedValue QtObject::method_hsla(QV4::CallContext *ctx)
{
- int argCount = ctx->callData->argc;
+ int argCount = ctx->d()->callData->argc;
if (argCount < 3 || argCount > 4)
V4THROW_ERROR("Qt.hsla(): Invalid arguments");
- double h = ctx->callData->args[0].toNumber();
- double s = ctx->callData->args[1].toNumber();
- double l = ctx->callData->args[2].toNumber();
- double a = (argCount == 4) ? ctx->callData->args[3].toNumber() : 1;
+ double h = ctx->d()->callData->args[0].toNumber();
+ double s = ctx->d()->callData->args[1].toNumber();
+ double l = ctx->d()->callData->args[2].toNumber();
+ double a = (argCount == 4) ? ctx->d()->callData->args[3].toNumber() : 1;
if (h < 0.0) h=0.0;
if (h > 1.0) h=1.0;
@@ -221,7 +220,7 @@ ReturnedValue QtObject::method_hsla(QV4::CallContext *ctx)
if (a < 0.0) a=0.0;
if (a > 1.0) a=1.0;
- return ctx->engine->v8Engine->fromVariant(QQml_colorProvider()->fromHslF(h, s, l, a));
+ return ctx->d()->engine->v8Engine->fromVariant(QQml_colorProvider()->fromHslF(h, s, l, a));
}
/*!
@@ -234,14 +233,14 @@ basic type.
*/
ReturnedValue QtObject::method_colorEqual(QV4::CallContext *ctx)
{
- if (ctx->callData->argc != 2)
+ if (ctx->d()->callData->argc != 2)
V4THROW_ERROR("Qt.colorEqual(): Invalid arguments");
bool ok = false;
- QV8Engine *v8engine = ctx->engine->v8Engine;
+ QV8Engine *v8engine = ctx->d()->engine->v8Engine;
- QVariant lhs = v8engine->toVariant(ctx->callData->args[0], -1);
+ QVariant lhs = v8engine->toVariant(ctx->d()->callData->args[0], -1);
if (lhs.userType() == QVariant::String) {
lhs = QQmlStringConverters::colorFromString(lhs.toString(), &ok);
if (!ok) {
@@ -251,7 +250,7 @@ ReturnedValue QtObject::method_colorEqual(QV4::CallContext *ctx)
V4THROW_ERROR("Qt.colorEqual(): Invalid arguments");
}
- QVariant rhs = v8engine->toVariant(ctx->callData->args[1], -1);
+ QVariant rhs = v8engine->toVariant(ctx->d()->callData->args[1], -1);
if (rhs.userType() == QVariant::String) {
rhs = QQmlStringConverters::colorFromString(rhs.toString(), &ok);
if (!ok) {
@@ -274,15 +273,15 @@ The returned object has \c x, \c y, \c width and \c height attributes with the g
*/
ReturnedValue QtObject::method_rect(QV4::CallContext *ctx)
{
- if (ctx->callData->argc != 4)
+ if (ctx->d()->callData->argc != 4)
V4THROW_ERROR("Qt.rect(): Invalid arguments");
- double x = ctx->callData->args[0].toNumber();
- double y = ctx->callData->args[1].toNumber();
- double w = ctx->callData->args[2].toNumber();
- double h = ctx->callData->args[3].toNumber();
+ double x = ctx->d()->callData->args[0].toNumber();
+ double y = ctx->d()->callData->args[1].toNumber();
+ double w = ctx->d()->callData->args[2].toNumber();
+ double h = ctx->d()->callData->args[3].toNumber();
- return ctx->engine->v8Engine->fromVariant(QVariant::fromValue(QRectF(x, y, w, h)));
+ return ctx->d()->engine->v8Engine->fromVariant(QVariant::fromValue(QRectF(x, y, w, h)));
}
/*!
@@ -291,13 +290,13 @@ Returns a Point with the specified \c x and \c y coordinates.
*/
ReturnedValue QtObject::method_point(QV4::CallContext *ctx)
{
- if (ctx->callData->argc != 2)
+ if (ctx->d()->callData->argc != 2)
V4THROW_ERROR("Qt.point(): Invalid arguments");
- double x = ctx->callData->args[0].toNumber();
- double y = ctx->callData->args[1].toNumber();
+ double x = ctx->d()->callData->args[0].toNumber();
+ double y = ctx->d()->callData->args[1].toNumber();
- return ctx->engine->v8Engine->fromVariant(QVariant::fromValue(QPointF(x, y)));
+ return ctx->d()->engine->v8Engine->fromVariant(QVariant::fromValue(QPointF(x, y)));
}
/*!
@@ -306,13 +305,13 @@ Returns a Size with the specified \c width and \c height.
*/
ReturnedValue QtObject::method_size(QV4::CallContext *ctx)
{
- if (ctx->callData->argc != 2)
+ if (ctx->d()->callData->argc != 2)
V4THROW_ERROR("Qt.size(): Invalid arguments");
- double w = ctx->callData->args[0].toNumber();
- double h = ctx->callData->args[1].toNumber();
+ double w = ctx->d()->callData->args[0].toNumber();
+ double h = ctx->d()->callData->args[1].toNumber();
- return ctx->engine->v8Engine->fromVariant(QVariant::fromValue(QSizeF(w, h)));
+ return ctx->d()->engine->v8Engine->fromVariant(QVariant::fromValue(QSizeF(w, h)));
}
/*!
@@ -325,12 +324,12 @@ Invalid keys will be ignored.
*/
ReturnedValue QtObject::method_font(QV4::CallContext *ctx)
{
- if (ctx->callData->argc != 1 || !ctx->callData->args[0].isObject())
+ if (ctx->d()->callData->argc != 1 || !ctx->d()->callData->args[0].isObject())
V4THROW_ERROR("Qt.font(): Invalid arguments");
- QV8Engine *v8engine = ctx->engine->v8Engine;
+ QV8Engine *v8engine = ctx->d()->engine->v8Engine;
bool ok = false;
- QVariant v = QQml_valueTypeProvider()->createVariantFromJsObject(QMetaType::QFont, QQmlV4Handle(ctx->callData->args[0]), v8engine, &ok);
+ QVariant v = QQml_valueTypeProvider()->createVariantFromJsObject(QMetaType::QFont, QQmlV4Handle(ctx->d()->callData->args[0]), v8engine, &ok);
if (!ok)
V4THROW_ERROR("Qt.font(): Invalid argument: no valid font subproperties specified");
return v8engine->fromVariant(v);
@@ -344,15 +343,15 @@ Returns a Vector2D with the specified \c x and \c y.
*/
ReturnedValue QtObject::method_vector2d(QV4::CallContext *ctx)
{
- if (ctx->callData->argc != 2)
+ if (ctx->d()->callData->argc != 2)
V4THROW_ERROR("Qt.vector2d(): Invalid arguments");
float xy[3]; // qvector2d uses float internally
- xy[0] = ctx->callData->args[0].toNumber();
- xy[1] = ctx->callData->args[1].toNumber();
+ xy[0] = ctx->d()->callData->args[0].toNumber();
+ xy[1] = ctx->d()->callData->args[1].toNumber();
const void *params[] = { xy };
- QV8Engine *v8engine = ctx->engine->v8Engine;
+ QV8Engine *v8engine = ctx->d()->engine->v8Engine;
return v8engine->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QVector2D, 1, params));
}
@@ -362,16 +361,16 @@ Returns a Vector3D with the specified \c x, \c y and \c z.
*/
ReturnedValue QtObject::method_vector3d(QV4::CallContext *ctx)
{
- if (ctx->callData->argc != 3)
+ if (ctx->d()->callData->argc != 3)
V4THROW_ERROR("Qt.vector3d(): Invalid arguments");
float xyz[3]; // qvector3d uses float internally
- xyz[0] = ctx->callData->args[0].toNumber();
- xyz[1] = ctx->callData->args[1].toNumber();
- xyz[2] = ctx->callData->args[2].toNumber();
+ xyz[0] = ctx->d()->callData->args[0].toNumber();
+ xyz[1] = ctx->d()->callData->args[1].toNumber();
+ xyz[2] = ctx->d()->callData->args[2].toNumber();
const void *params[] = { xyz };
- QV8Engine *v8engine = ctx->engine->v8Engine;
+ QV8Engine *v8engine = ctx->d()->engine->v8Engine;
return v8engine->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QVector3D, 1, params));
}
@@ -381,17 +380,17 @@ Returns a Vector4D with the specified \c x, \c y, \c z and \c w.
*/
ReturnedValue QtObject::method_vector4d(QV4::CallContext *ctx)
{
- if (ctx->callData->argc != 4)
+ if (ctx->d()->callData->argc != 4)
V4THROW_ERROR("Qt.vector4d(): Invalid arguments");
float xyzw[4]; // qvector4d uses float internally
- xyzw[0] = ctx->callData->args[0].toNumber();
- xyzw[1] = ctx->callData->args[1].toNumber();
- xyzw[2] = ctx->callData->args[2].toNumber();
- xyzw[3] = ctx->callData->args[3].toNumber();
+ xyzw[0] = ctx->d()->callData->args[0].toNumber();
+ xyzw[1] = ctx->d()->callData->args[1].toNumber();
+ xyzw[2] = ctx->d()->callData->args[2].toNumber();
+ xyzw[3] = ctx->d()->callData->args[3].toNumber();
const void *params[] = { xyzw };
- QV8Engine *v8engine = ctx->engine->v8Engine;
+ QV8Engine *v8engine = ctx->d()->engine->v8Engine;
return v8engine->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QVector4D, 1, params));
}
@@ -401,17 +400,17 @@ Returns a Quaternion with the specified \c scalar, \c x, \c y, and \c z.
*/
ReturnedValue QtObject::method_quaternion(QV4::CallContext *ctx)
{
- if (ctx->callData->argc != 4)
+ if (ctx->d()->callData->argc != 4)
V4THROW_ERROR("Qt.quaternion(): Invalid arguments");
qreal sxyz[4]; // qquaternion uses qreal internally
- sxyz[0] = ctx->callData->args[0].toNumber();
- sxyz[1] = ctx->callData->args[1].toNumber();
- sxyz[2] = ctx->callData->args[2].toNumber();
- sxyz[3] = ctx->callData->args[3].toNumber();
+ sxyz[0] = ctx->d()->callData->args[0].toNumber();
+ sxyz[1] = ctx->d()->callData->args[1].toNumber();
+ sxyz[2] = ctx->d()->callData->args[2].toNumber();
+ sxyz[3] = ctx->d()->callData->args[3].toNumber();
const void *params[] = { sxyz };
- QV8Engine *v8engine = ctx->engine->v8Engine;
+ QV8Engine *v8engine = ctx->d()->engine->v8Engine;
return v8engine->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QQuaternion, 1, params));
}
@@ -424,36 +423,36 @@ matrix values.
*/
ReturnedValue QtObject::method_matrix4x4(QV4::CallContext *ctx)
{
- QV8Engine *v8engine = ctx->engine->v8Engine;
+ QV8Engine *v8engine = ctx->d()->engine->v8Engine;
- if (ctx->callData->argc == 1 && ctx->callData->args[0].isObject()) {
+ if (ctx->d()->callData->argc == 1 && ctx->d()->callData->args[0].isObject()) {
bool ok = false;
- QVariant v = QQml_valueTypeProvider()->createVariantFromJsObject(QMetaType::QMatrix4x4, QQmlV4Handle(ctx->callData->args[0]), v8engine, &ok);
+ QVariant v = QQml_valueTypeProvider()->createVariantFromJsObject(QMetaType::QMatrix4x4, QQmlV4Handle(ctx->d()->callData->args[0]), v8engine, &ok);
if (!ok)
V4THROW_ERROR("Qt.matrix4x4(): Invalid argument: not a valid matrix4x4 values array");
return v8engine->fromVariant(v);
}
- if (ctx->callData->argc != 16)
+ if (ctx->d()->callData->argc != 16)
V4THROW_ERROR("Qt.matrix4x4(): Invalid arguments");
qreal vals[16]; // qmatrix4x4 uses qreal internally
- vals[0] = ctx->callData->args[0].toNumber();
- vals[1] = ctx->callData->args[1].toNumber();
- vals[2] = ctx->callData->args[2].toNumber();
- vals[3] = ctx->callData->args[3].toNumber();
- vals[4] = ctx->callData->args[4].toNumber();
- vals[5] = ctx->callData->args[5].toNumber();
- vals[6] = ctx->callData->args[6].toNumber();
- vals[7] = ctx->callData->args[7].toNumber();
- vals[8] = ctx->callData->args[8].toNumber();
- vals[9] = ctx->callData->args[9].toNumber();
- vals[10] = ctx->callData->args[10].toNumber();
- vals[11] = ctx->callData->args[11].toNumber();
- vals[12] = ctx->callData->args[12].toNumber();
- vals[13] = ctx->callData->args[13].toNumber();
- vals[14] = ctx->callData->args[14].toNumber();
- vals[15] = ctx->callData->args[15].toNumber();
+ vals[0] = ctx->d()->callData->args[0].toNumber();
+ vals[1] = ctx->d()->callData->args[1].toNumber();
+ vals[2] = ctx->d()->callData->args[2].toNumber();
+ vals[3] = ctx->d()->callData->args[3].toNumber();
+ vals[4] = ctx->d()->callData->args[4].toNumber();
+ vals[5] = ctx->d()->callData->args[5].toNumber();
+ vals[6] = ctx->d()->callData->args[6].toNumber();
+ vals[7] = ctx->d()->callData->args[7].toNumber();
+ vals[8] = ctx->d()->callData->args[8].toNumber();
+ vals[9] = ctx->d()->callData->args[9].toNumber();
+ vals[10] = ctx->d()->callData->args[10].toNumber();
+ vals[11] = ctx->d()->callData->args[11].toNumber();
+ vals[12] = ctx->d()->callData->args[12].toNumber();
+ vals[13] = ctx->d()->callData->args[13].toNumber();
+ vals[14] = ctx->d()->callData->args[14].toNumber();
+ vals[15] = ctx->d()->callData->args[15].toNumber();
const void *params[] = { vals };
return v8engine->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QMatrix4x4, 1, params));
@@ -475,11 +474,11 @@ If \c factor is not supplied, returns a color 50% lighter than \c baseColor (fac
*/
ReturnedValue QtObject::method_lighter(QV4::CallContext *ctx)
{
- if (ctx->callData->argc != 1 && ctx->callData->argc != 2)
+ if (ctx->d()->callData->argc != 1 && ctx->d()->callData->argc != 2)
V4THROW_ERROR("Qt.lighter(): Invalid arguments");
- QV8Engine *v8engine = ctx->engine->v8Engine;
- QVariant v = v8engine->toVariant(ctx->callData->args[0], -1);
+ QV8Engine *v8engine = ctx->d()->engine->v8Engine;
+ QVariant v = v8engine->toVariant(ctx->d()->callData->args[0], -1);
if (v.userType() == QVariant::String) {
bool ok = false;
v = QQmlStringConverters::colorFromString(v.toString(), &ok);
@@ -491,8 +490,8 @@ ReturnedValue QtObject::method_lighter(QV4::CallContext *ctx)
}
qreal factor = 1.5;
- if (ctx->callData->argc == 2)
- factor = ctx->callData->args[1].toNumber();
+ if (ctx->d()->callData->argc == 2)
+ factor = ctx->d()->callData->args[1].toNumber();
return v8engine->fromVariant(QQml_colorProvider()->lighter(v, factor));
}
@@ -514,11 +513,11 @@ If \c factor is not supplied, returns a color 50% darker than \c baseColor (fact
*/
ReturnedValue QtObject::method_darker(QV4::CallContext *ctx)
{
- if (ctx->callData->argc != 1 && ctx->callData->argc != 2)
+ if (ctx->d()->callData->argc != 1 && ctx->d()->callData->argc != 2)
V4THROW_ERROR("Qt.darker(): Invalid arguments");
- QV8Engine *v8engine = ctx->engine->v8Engine;
- QVariant v = v8engine->toVariant(ctx->callData->args[0], -1);
+ QV8Engine *v8engine = ctx->d()->engine->v8Engine;
+ QVariant v = v8engine->toVariant(ctx->d()->callData->args[0], -1);
if (v.userType() == QVariant::String) {
bool ok = false;
v = QQmlStringConverters::colorFromString(v.toString(), &ok);
@@ -530,8 +529,8 @@ ReturnedValue QtObject::method_darker(QV4::CallContext *ctx)
}
qreal factor = 2.0;
- if (ctx->callData->argc == 2)
- factor = ctx->callData->args[1].toNumber();
+ if (ctx->d()->callData->argc == 2)
+ factor = ctx->d()->callData->args[1].toNumber();
return v8engine->fromVariant(QQml_colorProvider()->darker(v, factor));
}
@@ -562,13 +561,13 @@ ReturnedValue QtObject::method_darker(QV4::CallContext *ctx)
*/
ReturnedValue QtObject::method_tint(QV4::CallContext *ctx)
{
- if (ctx->callData->argc != 2)
+ if (ctx->d()->callData->argc != 2)
V4THROW_ERROR("Qt.tint(): Invalid arguments");
- QV8Engine *v8engine = ctx->engine->v8Engine;
+ QV8Engine *v8engine = ctx->d()->engine->v8Engine;
// base color
- QVariant v1 = v8engine->toVariant(ctx->callData->args[0], -1);
+ QVariant v1 = v8engine->toVariant(ctx->d()->callData->args[0], -1);
if (v1.userType() == QVariant::String) {
bool ok = false;
v1 = QQmlStringConverters::colorFromString(v1.toString(), &ok);
@@ -580,7 +579,7 @@ ReturnedValue QtObject::method_tint(QV4::CallContext *ctx)
}
// tint color
- QVariant v2 = v8engine->toVariant(ctx->callData->args[1], -1);
+ QVariant v2 = v8engine->toVariant(ctx->d()->callData->args[1], -1);
if (v2.userType() == QVariant::String) {
bool ok = false;
v2 = QQmlStringConverters::colorFromString(v2.toString(), &ok);
@@ -612,22 +611,22 @@ If \a format is not specified, \a date is formatted using
*/
ReturnedValue QtObject::method_formatDate(QV4::CallContext *ctx)
{
- if (ctx->callData->argc < 1 || ctx->callData->argc > 2)
+ if (ctx->d()->callData->argc < 1 || ctx->d()->callData->argc > 2)
V4THROW_ERROR("Qt.formatDate(): Invalid arguments");
QV4::Scope scope(ctx);
- QV8Engine *v8engine = ctx->engine->v8Engine;
+ QV8Engine *v8engine = ctx->d()->engine->v8Engine;
Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
- QDate date = v8engine->toVariant(ctx->callData->args[0], -1).toDateTime().date();
+ QDate date = v8engine->toVariant(ctx->d()->callData->args[0], -1).toDateTime().date();
QString formattedDate;
- if (ctx->callData->argc == 2) {
- QV4::ScopedString s(scope, ctx->callData->args[1]);
+ if (ctx->d()->callData->argc == 2) {
+ QV4::ScopedString s(scope, ctx->d()->callData->args[1]);
if (s) {
QString format = s->toQString();
formattedDate = date.toString(format);
- } else if (ctx->callData->args[1].isNumber()) {
- quint32 intFormat = ctx->callData->args[1].asDouble();
+ } else if (ctx->d()->callData->args[1].isNumber()) {
+ quint32 intFormat = ctx->d()->callData->args[1].asDouble();
Qt::DateFormat format = Qt::DateFormat(intFormat);
formattedDate = date.toString(format);
} else {
@@ -637,7 +636,7 @@ ReturnedValue QtObject::method_formatDate(QV4::CallContext *ctx)
formattedDate = date.toString(enumFormat);
}
- return ctx->engine->newString(formattedDate)->asReturnedValue();
+ return ctx->d()->engine->newString(formattedDate)->asReturnedValue();
}
/*!
@@ -657,28 +656,28 @@ If \a format is not specified, \a time is formatted using
*/
ReturnedValue QtObject::method_formatTime(QV4::CallContext *ctx)
{
- if (ctx->callData->argc < 1 || ctx->callData->argc > 2)
+ if (ctx->d()->callData->argc < 1 || ctx->d()->callData->argc > 2)
V4THROW_ERROR("Qt.formatTime(): Invalid arguments");
QV4::Scope scope(ctx);
- QV8Engine *v8engine = ctx->engine->v8Engine;
+ QV8Engine *v8engine = ctx->d()->engine->v8Engine;
- QVariant argVariant = v8engine->toVariant(ctx->callData->args[0], -1);
+ QVariant argVariant = v8engine->toVariant(ctx->d()->callData->args[0], -1);
QTime time;
- if (ctx->callData->args[0].asDateObject() || (argVariant.type() == QVariant::String))
+ if (ctx->d()->callData->args[0].asDateObject() || (argVariant.type() == QVariant::String))
time = argVariant.toDateTime().time();
else // if (argVariant.type() == QVariant::Time), or invalid.
time = argVariant.toTime();
Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
QString formattedTime;
- if (ctx->callData->argc == 2) {
- QV4::ScopedString s(scope, ctx->callData->args[1]);
+ if (ctx->d()->callData->argc == 2) {
+ QV4::ScopedString s(scope, ctx->d()->callData->args[1]);
if (s) {
QString format = s->toQString();
formattedTime = time.toString(format);
- } else if (ctx->callData->args[1].isNumber()) {
- quint32 intFormat = ctx->callData->args[1].asDouble();
+ } else if (ctx->d()->callData->args[1].isNumber()) {
+ quint32 intFormat = ctx->d()->callData->args[1].asDouble();
Qt::DateFormat format = Qt::DateFormat(intFormat);
formattedTime = time.toString(format);
} else {
@@ -688,7 +687,7 @@ ReturnedValue QtObject::method_formatTime(QV4::CallContext *ctx)
formattedTime = time.toString(enumFormat);
}
- return ctx->engine->newString(formattedTime)->asReturnedValue();
+ return ctx->d()->engine->newString(formattedTime)->asReturnedValue();
}
/*!
@@ -783,22 +782,22 @@ with the \a format values below to produce the following results:
*/
ReturnedValue QtObject::method_formatDateTime(QV4::CallContext *ctx)
{
- if (ctx->callData->argc < 1 || ctx->callData->argc > 2)
+ if (ctx->d()->callData->argc < 1 || ctx->d()->callData->argc > 2)
V4THROW_ERROR("Qt.formatDateTime(): Invalid arguments");
QV4::Scope scope(ctx);
- QV8Engine *v8engine = ctx->engine->v8Engine;
+ QV8Engine *v8engine = ctx->d()->engine->v8Engine;
Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
- QDateTime dt = v8engine->toVariant(ctx->callData->args[0], -1).toDateTime();
+ QDateTime dt = v8engine->toVariant(ctx->d()->callData->args[0], -1).toDateTime();
QString formattedDt;
- if (ctx->callData->argc == 2) {
- QV4::ScopedString s(scope, ctx->callData->args[1]);
+ if (ctx->d()->callData->argc == 2) {
+ QV4::ScopedString s(scope, ctx->d()->callData->args[1]);
if (s) {
QString format = s->toQString();
formattedDt = dt.toString(format);
- } else if (ctx->callData->args[1].isNumber()) {
- quint32 intFormat = ctx->callData->args[1].asDouble();
+ } else if (ctx->d()->callData->args[1].isNumber()) {
+ quint32 intFormat = ctx->d()->callData->args[1].asDouble();
Qt::DateFormat format = Qt::DateFormat(intFormat);
formattedDt = dt.toString(format);
} else {
@@ -808,7 +807,7 @@ ReturnedValue QtObject::method_formatDateTime(QV4::CallContext *ctx)
formattedDt = dt.toString(enumFormat);
}
- return ctx->engine->newString(formattedDt)->asReturnedValue();
+ return ctx->d()->engine->newString(formattedDt)->asReturnedValue();
}
/*!
@@ -817,10 +816,10 @@ Attempts to open the specified \c target url in an external application, based o
*/
ReturnedValue QtObject::method_openUrlExternally(QV4::CallContext *ctx)
{
- if (ctx->callData->argc != 1)
+ if (ctx->d()->callData->argc != 1)
return QV4::Encode(false);
- QV8Engine *v8engine = ctx->engine->v8Engine;
+ QV8Engine *v8engine = ctx->d()->engine->v8Engine;
QUrl url(Value::fromReturnedValue(method_resolvedUrl(ctx)).toQStringNoThrow());
return v8engine->fromVariant(QQml_guiProvider()->openUrlExternally(url));
@@ -832,21 +831,21 @@ ReturnedValue QtObject::method_openUrlExternally(QV4::CallContext *ctx)
*/
ReturnedValue QtObject::method_resolvedUrl(QV4::CallContext *ctx)
{
- QV8Engine *v8engine = ctx->engine->v8Engine;
+ QV8Engine *v8engine = ctx->d()->engine->v8Engine;
- QUrl url = v8engine->toVariant(ctx->callData->args[0], -1).toUrl();
+ QUrl url = v8engine->toVariant(ctx->d()->callData->args[0], -1).toUrl();
QQmlEngine *e = v8engine->engine();
QQmlEnginePrivate *p = 0;
if (e) p = QQmlEnginePrivate::get(e);
if (p) {
QQmlContextData *ctxt = v8engine->callingContext();
if (ctxt)
- return ctx->engine->newString(ctxt->resolvedUrl(url).toString())->asReturnedValue();
+ return ctx->d()->engine->newString(ctxt->resolvedUrl(url).toString())->asReturnedValue();
else
- return ctx->engine->newString(url.toString())->asReturnedValue();
+ return ctx->d()->engine->newString(url.toString())->asReturnedValue();
}
- return ctx->engine->newString(e->baseUrl().resolved(url).toString())->asReturnedValue();
+ return ctx->d()->engine->newString(e->baseUrl().resolved(url).toString())->asReturnedValue();
}
/*!
@@ -855,10 +854,10 @@ Returns a list of the font families available to the application.
*/
ReturnedValue QtObject::method_fontFamilies(CallContext *ctx)
{
- if (ctx->callData->argc != 0)
+ if (ctx->d()->callData->argc != 0)
V4THROW_ERROR("Qt.fontFamilies(): Invalid arguments");
- QV8Engine *v8engine = ctx->engine->v8Engine;
+ QV8Engine *v8engine = ctx->d()->engine->v8Engine;
return v8engine->fromVariant(QVariant(QQml_guiProvider()->fontFamilies()));
}
@@ -868,12 +867,12 @@ Returns a hex string of the md5 hash of \c data.
*/
ReturnedValue QtObject::method_md5(CallContext *ctx)
{
- if (ctx->callData->argc != 1)
+ if (ctx->d()->callData->argc != 1)
V4THROW_ERROR("Qt.md5(): Invalid arguments");
- QByteArray data = ctx->callData->args[0].toQStringNoThrow().toUtf8();
+ QByteArray data = ctx->d()->callData->args[0].toQStringNoThrow().toUtf8();
QByteArray result = QCryptographicHash::hash(data, QCryptographicHash::Md5);
- return ctx->engine->newString(QLatin1String(result.toHex()))->asReturnedValue();
+ return ctx->d()->engine->newString(QLatin1String(result.toHex()))->asReturnedValue();
}
/*!
@@ -882,12 +881,12 @@ Binary to ASCII - this function returns a base64 encoding of \c data.
*/
ReturnedValue QtObject::method_btoa(CallContext *ctx)
{
- if (ctx->callData->argc != 1)
+ if (ctx->d()->callData->argc != 1)
V4THROW_ERROR("Qt.btoa(): Invalid arguments");
- QByteArray data = ctx->callData->args[0].toQStringNoThrow().toUtf8();
+ QByteArray data = ctx->d()->callData->args[0].toQStringNoThrow().toUtf8();
- return ctx->engine->newString(QLatin1String(data.toBase64()))->asReturnedValue();
+ return ctx->d()->engine->newString(QLatin1String(data.toBase64()))->asReturnedValue();
}
/*!
@@ -896,12 +895,12 @@ ASCII to binary - this function returns a base64 decoding of \c data.
*/
ReturnedValue QtObject::method_atob(CallContext *ctx)
{
- if (ctx->callData->argc != 1)
+ if (ctx->d()->callData->argc != 1)
V4THROW_ERROR("Qt.atob(): Invalid arguments");
- QByteArray data = ctx->callData->args[0].toQStringNoThrow().toLatin1();
+ QByteArray data = ctx->d()->callData->args[0].toQStringNoThrow().toLatin1();
- return ctx->engine->newString(QString::fromUtf8(QByteArray::fromBase64(data)))->asReturnedValue();
+ return ctx->d()->engine->newString(QString::fromUtf8(QByteArray::fromBase64(data)))->asReturnedValue();
}
/*!
@@ -913,7 +912,7 @@ QQmlEngine::quit() signal to the QCoreApplication::quit() slot.
*/
ReturnedValue QtObject::method_quit(CallContext *ctx)
{
- QV8Engine *v8engine = ctx->engine->v8Engine;
+ QV8Engine *v8engine = ctx->d()->engine->v8Engine;
QQmlEnginePrivate::get(v8engine->engine())->sendQuit();
return QV4::Encode::undefined();
@@ -946,7 +945,7 @@ See \l {Dynamic QML Object Creation from JavaScript} for more information on usi
ReturnedValue QtObject::method_createQmlObject(CallContext *ctx)
{
Scope scope(ctx);
- if (ctx->callData->argc < 2 || ctx->callData->argc > 3)
+ if (ctx->d()->callData->argc < 2 || ctx->d()->callData->argc > 3)
V4THROW_ERROR("Qt.createQmlObject(): Invalid arguments");
struct Error {
@@ -962,21 +961,21 @@ ReturnedValue QtObject::method_createQmlObject(CallContext *ctx)
const QQmlError &error = errors.at(ii);
errorstr += QLatin1String("\n ") + error.toString();
qmlerror = v4->newObject();
- qmlerror->put((s = v4->newString(QStringLiteral("lineNumber"))), (v = QV4::Primitive::fromInt32(error.line())));
- qmlerror->put((s = v4->newString(QStringLiteral("columnNumber"))), (v = QV4::Primitive::fromInt32(error.column())));
- qmlerror->put((s = v4->newString(QStringLiteral("fileName"))), (v = v4->newString(error.url().toString())));
- qmlerror->put((s = v4->newString(QStringLiteral("message"))), (v = v4->newString(error.description())));
+ qmlerror->put((s = v4->newString(QStringLiteral("lineNumber"))).getPointer(), (v = QV4::Primitive::fromInt32(error.line())));
+ qmlerror->put((s = v4->newString(QStringLiteral("columnNumber"))).getPointer(), (v = QV4::Primitive::fromInt32(error.column())));
+ qmlerror->put((s = v4->newString(QStringLiteral("fileName"))).getPointer(), (v = v4->newString(error.url().toString())));
+ qmlerror->put((s = v4->newString(QStringLiteral("message"))).getPointer(), (v = v4->newString(error.description())));
qmlerrors->putIndexed(ii, qmlerror);
}
v = v4->newString(errorstr);
Scoped<Object> errorObject(scope, v4->newErrorObject(v));
- errorObject->put((s = v4->newString(QStringLiteral("qmlErrors"))), qmlerrors);
+ errorObject->put((s = v4->newString(QStringLiteral("qmlErrors"))).getPointer(), qmlerrors);
return errorObject.asReturnedValue();
}
};
- QV8Engine *v8engine = ctx->engine->v8Engine;
+ QV8Engine *v8engine = ctx->d()->engine->v8Engine;
QQmlEngine *engine = v8engine->engine();
QQmlContextData *context = v8engine->callingContext();
@@ -988,13 +987,13 @@ ReturnedValue QtObject::method_createQmlObject(CallContext *ctx)
effectiveContext = context->asQQmlContext();
Q_ASSERT(effectiveContext);
- QString qml = ctx->callData->args[0].toQStringNoThrow();
+ QString qml = ctx->d()->callData->args[0].toQStringNoThrow();
if (qml.isEmpty())
return QV4::Encode::null();
QUrl url;
- if (ctx->callData->argc > 2)
- url = QUrl(ctx->callData->args[2].toQStringNoThrow());
+ if (ctx->d()->callData->argc > 2)
+ url = QUrl(ctx->d()->callData->args[2].toQStringNoThrow());
else
url = QUrl(QLatin1String("inline"));
@@ -1002,7 +1001,7 @@ ReturnedValue QtObject::method_createQmlObject(CallContext *ctx)
url = context->resolvedUrl(url);
QObject *parentArg = 0;
- QV4::Scoped<QV4::QObjectWrapper> qobjectWrapper(scope, ctx->callData->args[1]);
+ QV4::Scoped<QV4::QObjectWrapper> qobjectWrapper(scope, ctx->d()->callData->args[1]);
if (!!qobjectWrapper)
parentArg = qobjectWrapper->object();
if (!parentArg)
@@ -1012,7 +1011,7 @@ ReturnedValue QtObject::method_createQmlObject(CallContext *ctx)
component.setData(qml.toUtf8(), url);
if (component.isError()) {
- ScopedValue v(scope, Error::create(ctx->engine, component.errors()));
+ ScopedValue v(scope, Error::create(ctx->d()->engine, component.errors()));
return ctx->throwError(v);
}
@@ -1036,13 +1035,13 @@ ReturnedValue QtObject::method_createQmlObject(CallContext *ctx)
component.completeCreate();
if (component.isError()) {
- ScopedValue v(scope, Error::create(ctx->engine, component.errors()));
+ ScopedValue v(scope, Error::create(ctx->d()->engine, component.errors()));
return ctx->throwError(v);
}
Q_ASSERT(obj);
- return QV4::QObjectWrapper::wrap(ctx->engine, obj);
+ return QV4::QObjectWrapper::wrap(ctx->d()->engine, obj);
}
/*!
@@ -1078,12 +1077,12 @@ use \l{QtQml::Qt::createQmlObject()}{Qt.createQmlObject()}.
*/
ReturnedValue QtObject::method_createComponent(CallContext *ctx)
{
- if (ctx->callData->argc < 1 || ctx->callData->argc > 3)
+ if (ctx->d()->callData->argc < 1 || ctx->d()->callData->argc > 3)
return ctx->throwError(QStringLiteral("Qt.createComponent(): Invalid arguments"));
Scope scope(ctx);
- QV8Engine *v8engine = ctx->engine->v8Engine;
+ QV8Engine *v8engine = ctx->d()->engine->v8Engine;
QQmlEngine *engine = v8engine->engine();
QQmlContextData *context = v8engine->callingContext();
@@ -1092,7 +1091,7 @@ ReturnedValue QtObject::method_createComponent(CallContext *ctx)
if (context->isPragmaLibraryContext)
effectiveContext = 0;
- QString arg = ctx->callData->args[0].toQStringNoThrow();
+ QString arg = ctx->d()->callData->args[0].toQStringNoThrow();
if (arg.isEmpty())
return QV4::Encode::null();
@@ -1100,23 +1099,23 @@ ReturnedValue QtObject::method_createComponent(CallContext *ctx)
QObject *parentArg = 0;
int consumedCount = 1;
- if (ctx->callData->argc > 1) {
- ScopedValue lastArg(scope, ctx->callData->args[ctx->callData->argc-1]);
+ if (ctx->d()->callData->argc > 1) {
+ ScopedValue lastArg(scope, ctx->d()->callData->args[ctx->d()->callData->argc-1]);
// The second argument could be the mode enum
- if (ctx->callData->args[1].isInteger()) {
- int mode = ctx->callData->args[1].integerValue();
+ if (ctx->d()->callData->args[1].isInteger()) {
+ int mode = ctx->d()->callData->args[1].integerValue();
if (mode != int(QQmlComponent::PreferSynchronous) && mode != int(QQmlComponent::Asynchronous))
return ctx->throwError(QStringLiteral("Qt.createComponent(): Invalid arguments"));
compileMode = QQmlComponent::CompilationMode(mode);
consumedCount += 1;
} else {
// The second argument could be the parent only if there are exactly two args
- if ((ctx->callData->argc != 2) || !(lastArg->isObject() || lastArg->isNull()))
+ if ((ctx->d()->callData->argc != 2) || !(lastArg->isObject() || lastArg->isNull()))
return ctx->throwError(QStringLiteral("Qt.createComponent(): Invalid arguments"));
}
- if (consumedCount < ctx->callData->argc) {
+ if (consumedCount < ctx->d()->callData->argc) {
if (lastArg->isObject()) {
Scoped<QObjectWrapper> qobjectWrapper(scope, lastArg);
if (qobjectWrapper)
@@ -1137,7 +1136,7 @@ ReturnedValue QtObject::method_createComponent(CallContext *ctx)
QQmlData::get(c, true)->explicitIndestructibleSet = false;
QQmlData::get(c)->indestructible = false;
- return QV4::QObjectWrapper::wrap(ctx->engine, c);
+ return QV4::QObjectWrapper::wrap(ctx->d()->engine, c);
}
/*!
@@ -1163,20 +1162,20 @@ ReturnedValue QtObject::method_createComponent(CallContext *ctx)
ReturnedValue QtObject::method_locale(CallContext *ctx)
{
QString code;
- if (ctx->callData->argc > 1)
+ if (ctx->d()->callData->argc > 1)
V4THROW_ERROR("locale() requires 0 or 1 argument");
- if (ctx->callData->argc == 1 && !ctx->callData->args[0].isString())
+ if (ctx->d()->callData->argc == 1 && !ctx->d()->callData->args[0].isString())
V4THROW_TYPE("locale(): argument (locale code) must be a string");
- QV8Engine *v8engine = ctx->engine->v8Engine;
- if (ctx->callData->argc == 1)
- code = ctx->callData->args[0].toQStringNoThrow();
+ QV8Engine *v8engine = ctx->d()->engine->v8Engine;
+ if (ctx->d()->callData->argc == 1)
+ code = ctx->d()->callData->args[0].toQStringNoThrow();
return QQmlLocale::locale(v8engine, code);
}
-QQmlBindingFunction::QQmlBindingFunction(FunctionObject *originalFunction)
- : QV4::FunctionObject(originalFunction->scope, originalFunction->name())
+QQmlBindingFunction::Data::Data(FunctionObject *originalFunction)
+ : QV4::FunctionObject::Data(originalFunction->scope(), originalFunction->name())
, originalFunction(originalFunction)
{
setVTable(staticVTable());
@@ -1186,20 +1185,20 @@ QQmlBindingFunction::QQmlBindingFunction(FunctionObject *originalFunction)
void QQmlBindingFunction::initBindingLocation()
{
QV4::StackFrame frame = engine()->currentStackFrame();
- bindingLocation.sourceFile = frame.source;
- bindingLocation.line = frame.line;
+ d()->bindingLocation.sourceFile = frame.source;
+ d()->bindingLocation.line = frame.line;
}
ReturnedValue QQmlBindingFunction::call(Managed *that, CallData *callData)
{
QQmlBindingFunction *This = static_cast<QQmlBindingFunction*>(that);
- return This->originalFunction->call(callData);
+ return This->d()->originalFunction->call(callData);
}
void QQmlBindingFunction::markObjects(Managed *that, ExecutionEngine *e)
{
QQmlBindingFunction *This = static_cast<QQmlBindingFunction*>(that);
- This->originalFunction->mark(e);
+ This->d()->originalFunction->mark(e);
QV4::FunctionObject::markObjects(that, e);
}
@@ -1251,48 +1250,48 @@ DEFINE_OBJECT_VTABLE(QQmlBindingFunction);
*/
ReturnedValue QtObject::method_binding(CallContext *ctx)
{
- if (ctx->callData->argc != 1)
+ if (ctx->d()->callData->argc != 1)
V4THROW_ERROR("binding() requires 1 argument");
- QV4::FunctionObject *f = ctx->callData->args[0].asFunctionObject();
+ QV4::FunctionObject *f = ctx->d()->callData->args[0].asFunctionObject();
if (!f)
V4THROW_TYPE("binding(): argument (binding expression) must be a function");
- return (new (ctx->engine->memoryManager) QQmlBindingFunction(f))->asReturnedValue();
+ return (ctx->d()->engine->memoryManager->alloc<QQmlBindingFunction>(f))->asReturnedValue();
}
ReturnedValue QtObject::method_get_platform(CallContext *ctx)
{
// ### inefficient. Should be just a value based getter
- Object *o = ctx->callData->thisObject.asObject();
+ Object *o = ctx->d()->callData->thisObject.asObject();
if (!o)
return ctx->throwTypeError();
QtObject *qt = o->as<QtObject>();
if (!qt)
return ctx->throwTypeError();
- if (!qt->m_platform)
+ if (!qt->d()->platform)
// Only allocate a platform object once
- qt->m_platform = new QQmlPlatform(ctx->engine->v8Engine->publicEngine());
+ qt->d()->platform = new QQmlPlatform(ctx->d()->engine->v8Engine->publicEngine());
- return QV4::QObjectWrapper::wrap(ctx->engine, qt->m_platform);
+ return QV4::QObjectWrapper::wrap(ctx->d()->engine, qt->d()->platform);
}
ReturnedValue QtObject::method_get_application(CallContext *ctx)
{
// ### inefficient. Should be just a value based getter
- Object *o = ctx->callData->thisObject.asObject();
+ Object *o = ctx->d()->callData->thisObject.asObject();
if (!o)
return ctx->throwTypeError();
QtObject *qt = o->as<QtObject>();
if (!qt)
return ctx->throwTypeError();
- if (!qt->m_application)
+ if (!qt->d()->application)
// Only allocate an application object once
- qt->m_application = QQml_guiProvider()->application(ctx->engine->v8Engine->publicEngine());
+ qt->d()->application = QQml_guiProvider()->application(ctx->d()->engine->v8Engine->publicEngine());
- return QV4::QObjectWrapper::wrap(ctx->engine, qt->m_application);
+ return QV4::QObjectWrapper::wrap(ctx->d()->engine, qt->d()->application);
}
#ifndef QT_NO_IM
@@ -1300,31 +1299,31 @@ ReturnedValue QtObject::method_get_inputMethod(CallContext *ctx)
{
QObject *o = QQml_guiProvider()->inputMethod();
QQmlEngine::setObjectOwnership(o, QQmlEngine::CppOwnership);
- return QV4::QObjectWrapper::wrap(ctx->engine, o);
+ return QV4::QObjectWrapper::wrap(ctx->d()->engine, o);
}
#endif
-QV4::ConsoleObject::ConsoleObject(ExecutionEngine *v4)
- : Object(v4)
+QV4::ConsoleObject::Data::Data(ExecutionEngine *v4)
+ : Object::Data(v4)
{
QV4::Scope scope(v4);
- QV4::ScopedObject protectThis(scope, this);
-
- defineDefaultProperty(QStringLiteral("debug"), method_log);
- defineDefaultProperty(QStringLiteral("log"), method_log);
- defineDefaultProperty(QStringLiteral("info"), method_log);
- defineDefaultProperty(QStringLiteral("warn"), method_warn);
- defineDefaultProperty(QStringLiteral("error"), method_error);
- defineDefaultProperty(QStringLiteral("assert"), method_assert);
-
- defineDefaultProperty(QStringLiteral("count"), method_count);
- defineDefaultProperty(QStringLiteral("profile"), method_profile);
- defineDefaultProperty(QStringLiteral("profileEnd"), method_profileEnd);
- defineDefaultProperty(QStringLiteral("time"), method_time);
- defineDefaultProperty(QStringLiteral("timeEnd"), method_timeEnd);
- defineDefaultProperty(QStringLiteral("trace"), method_trace);
- defineDefaultProperty(QStringLiteral("exception"), method_exception);
+ QV4::ScopedObject o(scope, this);
+
+ o->defineDefaultProperty(QStringLiteral("debug"), method_log);
+ o->defineDefaultProperty(QStringLiteral("log"), method_log);
+ o->defineDefaultProperty(QStringLiteral("info"), method_log);
+ o->defineDefaultProperty(QStringLiteral("warn"), method_warn);
+ o->defineDefaultProperty(QStringLiteral("error"), method_error);
+ o->defineDefaultProperty(QStringLiteral("assert"), method_assert);
+
+ o->defineDefaultProperty(QStringLiteral("count"), method_count);
+ o->defineDefaultProperty(QStringLiteral("profile"), method_profile);
+ o->defineDefaultProperty(QStringLiteral("profileEnd"), method_profileEnd);
+ o->defineDefaultProperty(QStringLiteral("time"), method_time);
+ o->defineDefaultProperty(QStringLiteral("timeEnd"), method_timeEnd);
+ o->defineDefaultProperty(QStringLiteral("trace"), method_trace);
+ o->defineDefaultProperty(QStringLiteral("exception"), method_exception);
}
@@ -1364,16 +1363,16 @@ static QV4::ReturnedValue writeToConsole(ConsoleLogTypes logType, CallContext *c
bool printStack = false)
{
QString result;
- QV4::ExecutionEngine *v4 = ctx->engine;
+ QV4::ExecutionEngine *v4 = ctx->d()->engine;
- for (int i = 0; i < ctx->callData->argc; ++i) {
+ for (int i = 0; i < ctx->d()->callData->argc; ++i) {
if (i != 0)
result.append(QLatin1Char(' '));
- if (ctx->callData->args[i].asArrayObject())
- result.append(QStringLiteral("[") + ctx->callData->args[i].toQStringNoThrow() + QStringLiteral("]"));
+ if (ctx->d()->callData->args[i].asArrayObject())
+ result.append(QStringLiteral("[") + ctx->d()->callData->args[i].toQStringNoThrow() + QStringLiteral("]"));
else
- result.append(ctx->callData->args[i].toQStringNoThrow());
+ result.append(ctx->d()->callData->args[i].toQStringNoThrow());
}
if (printStack) {
@@ -1423,7 +1422,7 @@ QV4::ReturnedValue ConsoleObject::method_log(CallContext *ctx)
QV4::ReturnedValue ConsoleObject::method_profile(CallContext *ctx)
{
- QV4::ExecutionEngine *v4 = ctx->engine;
+ QV4::ExecutionEngine *v4 = ctx->d()->engine;
QV4::StackFrame frame = v4->currentStackFrame();
const QByteArray baSource = frame.source.toUtf8();
@@ -1441,7 +1440,7 @@ QV4::ReturnedValue ConsoleObject::method_profile(CallContext *ctx)
QV4::ReturnedValue ConsoleObject::method_profileEnd(CallContext *ctx)
{
- QV4::ExecutionEngine *v4 = ctx->engine;
+ QV4::ExecutionEngine *v4 = ctx->d()->engine;
QV4::StackFrame frame = v4->currentStackFrame();
const QByteArray baSource = frame.source.toUtf8();
@@ -1460,24 +1459,24 @@ QV4::ReturnedValue ConsoleObject::method_profileEnd(CallContext *ctx)
QV4::ReturnedValue ConsoleObject::method_time(CallContext *ctx)
{
- if (ctx->callData->argc != 1)
+ if (ctx->d()->callData->argc != 1)
V4THROW_ERROR("console.time(): Invalid arguments");
- QV8Engine *v8engine = ctx->engine->v8Engine;
+ QV8Engine *v8engine = ctx->d()->engine->v8Engine;
- QString name = ctx->callData->args[0].toQStringNoThrow();
+ QString name = ctx->d()->callData->args[0].toQStringNoThrow();
v8engine->startTimer(name);
return QV4::Encode::undefined();
}
QV4::ReturnedValue ConsoleObject::method_timeEnd(CallContext *ctx)
{
- if (ctx->callData->argc != 1)
+ if (ctx->d()->callData->argc != 1)
V4THROW_ERROR("console.time(): Invalid arguments");
- QV8Engine *v8engine = ctx->engine->v8Engine;
+ QV8Engine *v8engine = ctx->d()->engine->v8Engine;
- QString name = ctx->callData->args[0].toQStringNoThrow();
+ QString name = ctx->d()->callData->args[0].toQStringNoThrow();
bool wasRunning;
qint64 elapsed = v8engine->stopTimer(name, &wasRunning);
if (wasRunning) {
@@ -1490,11 +1489,11 @@ QV4::ReturnedValue ConsoleObject::method_count(CallContext *ctx)
{
// first argument: name to print. Ignore any additional arguments
QString name;
- if (ctx->callData->argc > 0)
- name = ctx->callData->args[0].toQStringNoThrow();
+ if (ctx->d()->callData->argc > 0)
+ name = ctx->d()->callData->args[0].toQStringNoThrow();
- QV4::ExecutionEngine *v4 = ctx->engine;
- QV8Engine *v8engine = ctx->engine->v8Engine;
+ QV4::ExecutionEngine *v4 = ctx->d()->engine;
+ QV8Engine *v8engine = ctx->d()->engine->v8Engine;
QV4::StackFrame frame = v4->currentStackFrame();
@@ -1512,10 +1511,10 @@ QV4::ReturnedValue ConsoleObject::method_count(CallContext *ctx)
QV4::ReturnedValue ConsoleObject::method_trace(CallContext *ctx)
{
- if (ctx->callData->argc != 0)
+ if (ctx->d()->callData->argc != 0)
V4THROW_ERROR("console.trace(): Invalid arguments");
- QV4::ExecutionEngine *v4 = ctx->engine;
+ QV4::ExecutionEngine *v4 = ctx->d()->engine;
QString stack = jsStack(v4);
@@ -1534,18 +1533,18 @@ QV4::ReturnedValue ConsoleObject::method_warn(CallContext *ctx)
QV4::ReturnedValue ConsoleObject::method_assert(CallContext *ctx)
{
- if (ctx->callData->argc == 0)
+ if (ctx->d()->callData->argc == 0)
V4THROW_ERROR("console.assert(): Missing argument");
- QV4::ExecutionEngine *v4 = ctx->engine;
+ QV4::ExecutionEngine *v4 = ctx->d()->engine;
- if (!ctx->callData->args[0].toBoolean()) {
+ if (!ctx->d()->callData->args[0].toBoolean()) {
QString message;
- for (int i = 1; i < ctx->callData->argc; ++i) {
+ for (int i = 1; i < ctx->d()->callData->argc; ++i) {
if (i != 1)
message.append(QLatin1Char(' '));
- message.append(ctx->callData->args[i].toQStringNoThrow());
+ message.append(ctx->d()->callData->args[i].toQStringNoThrow());
}
QString stack = jsStack(v4);
@@ -1561,7 +1560,7 @@ QV4::ReturnedValue ConsoleObject::method_assert(CallContext *ctx)
QV4::ReturnedValue ConsoleObject::method_exception(CallContext *ctx)
{
- if (ctx->callData->argc == 0)
+ if (ctx->d()->callData->argc == 0)
V4THROW_ERROR("console.exception(): Missing argument");
writeToConsole(Error, ctx, true);
@@ -1588,10 +1587,10 @@ void QV4::GlobalExtensions::init(QQmlEngine *qmlEngine, Object *globalObject)
globalObject->defineDefaultProperty(QStringLiteral("print"), ConsoleObject::method_log);
globalObject->defineDefaultProperty(QStringLiteral("gc"), method_gc);
- ScopedValue console(scope, new (v4->memoryManager) QV4::ConsoleObject(v4));
+ ScopedObject console(scope, v4->memoryManager->alloc<QV4::ConsoleObject>(v4));
globalObject->defineDefaultProperty(QStringLiteral("console"), console);
- ScopedValue qt(scope, new (v4->memoryManager) QV4::QtObject(v4, qmlEngine));
+ ScopedObject qt(scope, v4->memoryManager->alloc<QV4::QtObject>(v4, qmlEngine));
globalObject->defineDefaultProperty(QStringLiteral("Qt"), qt);
// string prototype extension
@@ -1619,36 +1618,36 @@ void QV4::GlobalExtensions::init(QQmlEngine *qmlEngine, Object *globalObject)
*/
ReturnedValue GlobalExtensions::method_qsTranslate(CallContext *ctx)
{
- if (ctx->callData->argc < 2)
+ if (ctx->d()->callData->argc < 2)
V4THROW_ERROR("qsTranslate() requires at least two arguments");
- if (!ctx->callData->args[0].isString())
+ if (!ctx->d()->callData->args[0].isString())
V4THROW_ERROR("qsTranslate(): first argument (context) must be a string");
- if (!ctx->callData->args[1].isString())
+ if (!ctx->d()->callData->args[1].isString())
V4THROW_ERROR("qsTranslate(): second argument (sourceText) must be a string");
- if ((ctx->callData->argc > 2) && !ctx->callData->args[2].isString())
+ if ((ctx->d()->callData->argc > 2) && !ctx->d()->callData->args[2].isString())
V4THROW_ERROR("qsTranslate(): third argument (disambiguation) must be a string");
- QString context = ctx->callData->args[0].toQStringNoThrow();
- QString text = ctx->callData->args[1].toQStringNoThrow();
+ QString context = ctx->d()->callData->args[0].toQStringNoThrow();
+ QString text = ctx->d()->callData->args[1].toQStringNoThrow();
QString comment;
- if (ctx->callData->argc > 2) comment = ctx->callData->args[2].toQStringNoThrow();
+ if (ctx->d()->callData->argc > 2) comment = ctx->d()->callData->args[2].toQStringNoThrow();
int i = 3;
- if (ctx->callData->argc > i && ctx->callData->args[i].isString()) {
+ if (ctx->d()->callData->argc > i && ctx->d()->callData->args[i].isString()) {
qWarning("qsTranslate(): specifying the encoding as fourth argument is deprecated");
++i;
}
int n = -1;
- if (ctx->callData->argc > i)
- n = ctx->callData->args[i].toInt32();
+ if (ctx->d()->callData->argc > i)
+ n = ctx->d()->callData->args[i].toInt32();
QString result = QCoreApplication::translate(context.toUtf8().constData(),
text.toUtf8().constData(),
comment.toUtf8().constData(),
n);
- return ctx->engine->newString(result)->asReturnedValue();
+ return ctx->d()->engine->newString(result)->asReturnedValue();
}
/*!
@@ -1675,9 +1674,9 @@ ReturnedValue GlobalExtensions::method_qsTranslate(CallContext *ctx)
*/
ReturnedValue GlobalExtensions::method_qsTranslateNoOp(CallContext *ctx)
{
- if (ctx->callData->argc < 2)
+ if (ctx->d()->callData->argc < 2)
return QV4::Encode::undefined();
- return ctx->callData->args[1].asReturnedValue();
+ return ctx->d()->callData->args[1].asReturnedValue();
}
/*!
@@ -1699,36 +1698,54 @@ ReturnedValue GlobalExtensions::method_qsTranslateNoOp(CallContext *ctx)
*/
ReturnedValue GlobalExtensions::method_qsTr(CallContext *ctx)
{
- if (ctx->callData->argc < 1)
+ if (ctx->d()->callData->argc < 1)
V4THROW_ERROR("qsTr() requires at least one argument");
- if (!ctx->callData->args[0].isString())
+ if (!ctx->d()->callData->args[0].isString())
V4THROW_ERROR("qsTr(): first argument (sourceText) must be a string");
- if ((ctx->callData->argc > 1) && !ctx->callData->args[1].isString())
+ if ((ctx->d()->callData->argc > 1) && !ctx->d()->callData->args[1].isString())
V4THROW_ERROR("qsTr(): second argument (disambiguation) must be a string");
- if ((ctx->callData->argc > 2) && !ctx->callData->args[2].isNumber())
+ if ((ctx->d()->callData->argc > 2) && !ctx->d()->callData->args[2].isNumber())
V4THROW_ERROR("qsTr(): third argument (n) must be a number");
- QV8Engine *v8engine = ctx->engine->v8Engine;
- QQmlContextData *ctxt = v8engine->callingContext();
-
- QString path = ctxt->url.toString();
- int lastSlash = path.lastIndexOf(QLatin1Char('/'));
- int lastDot = path.lastIndexOf(QLatin1Char('.'));
- int length = lastDot - (lastSlash + 1);
- QString context = (lastSlash > -1) ? path.mid(lastSlash + 1, (length > -1) ? length : -1) : QString();
+ QV8Engine *v8engine = ctx->d()->engine->v8Engine;
+ QString context;
+ if (QQmlContextData *ctxt = v8engine->callingContext()) {
+ QString path = ctxt->url.toString();
+ int lastSlash = path.lastIndexOf(QLatin1Char('/'));
+ int lastDot = path.lastIndexOf(QLatin1Char('.'));
+ int length = lastDot - (lastSlash + 1);
+ context = (lastSlash > -1) ? path.mid(lastSlash + 1, (length > -1) ? length : -1) : QString();
+ } else if (QV4::ExecutionContext *parentCtx = ctx->d()->parent) {
+ // The first non-empty source URL in the call stack determines the translation context.
+ while (parentCtx && context.isEmpty()) {
+ if (QV4::CompiledData::CompilationUnit *unit = parentCtx->d()->compilationUnit) {
+ QString fileName = unit->fileName();
+ QUrl url(unit->fileName());
+ if (url.isValid() && url.isRelative()) {
+ context = url.fileName();
+ } else {
+ context = QQmlFile::urlToLocalFileOrQrc(fileName);
+ if (context.isEmpty() && fileName.startsWith(QLatin1String(":/")))
+ context = fileName;
+ }
+ context = QFileInfo(context).baseName();
+ }
+ parentCtx = parentCtx->d()->parent;
+ }
+ }
- QString text = ctx->callData->args[0].toQStringNoThrow();
+ QString text = ctx->d()->callData->args[0].toQStringNoThrow();
QString comment;
- if (ctx->callData->argc > 1)
- comment = ctx->callData->args[1].toQStringNoThrow();
+ if (ctx->d()->callData->argc > 1)
+ comment = ctx->d()->callData->args[1].toQStringNoThrow();
int n = -1;
- if (ctx->callData->argc > 2)
- n = ctx->callData->args[2].toInt32();
+ if (ctx->d()->callData->argc > 2)
+ n = ctx->d()->callData->args[2].toInt32();
QString result = QCoreApplication::translate(context.toUtf8().constData(), text.toUtf8().constData(),
comment.toUtf8().constData(), n);
- return ctx->engine->newString(result)->asReturnedValue();
+ return ctx->d()->engine->newString(result)->asReturnedValue();
}
/*!
@@ -1755,9 +1772,9 @@ ReturnedValue GlobalExtensions::method_qsTr(CallContext *ctx)
*/
ReturnedValue GlobalExtensions::method_qsTrNoOp(CallContext *ctx)
{
- if (ctx->callData->argc < 1)
+ if (ctx->d()->callData->argc < 1)
return QV4::Encode::undefined();
- return ctx->callData->args[0].asReturnedValue();
+ return ctx->d()->callData->args[0].asReturnedValue();
}
/*!
@@ -1792,18 +1809,18 @@ ReturnedValue GlobalExtensions::method_qsTrNoOp(CallContext *ctx)
*/
ReturnedValue GlobalExtensions::method_qsTrId(CallContext *ctx)
{
- if (ctx->callData->argc < 1)
+ if (ctx->d()->callData->argc < 1)
V4THROW_ERROR("qsTrId() requires at least one argument");
- if (!ctx->callData->args[0].isString())
+ if (!ctx->d()->callData->args[0].isString())
V4THROW_TYPE("qsTrId(): first argument (id) must be a string");
- if (ctx->callData->argc > 1 && !ctx->callData->args[1].isNumber())
+ if (ctx->d()->callData->argc > 1 && !ctx->d()->callData->args[1].isNumber())
V4THROW_TYPE("qsTrId(): second argument (n) must be a number");
int n = -1;
- if (ctx->callData->argc > 1)
- n = ctx->callData->args[1].toInt32();
+ if (ctx->d()->callData->argc > 1)
+ n = ctx->d()->callData->args[1].toInt32();
- return ctx->engine->newString(qtTrId(ctx->callData->args[0].toQStringNoThrow().toUtf8().constData(), n))->asReturnedValue();
+ return ctx->d()->engine->newString(qtTrId(ctx->d()->callData->args[0].toQStringNoThrow().toUtf8().constData(), n))->asReturnedValue();
}
/*!
@@ -1824,16 +1841,16 @@ ReturnedValue GlobalExtensions::method_qsTrId(CallContext *ctx)
*/
ReturnedValue GlobalExtensions::method_qsTrIdNoOp(CallContext *ctx)
{
- if (ctx->callData->argc < 1)
+ if (ctx->d()->callData->argc < 1)
return QV4::Encode::undefined();
- return ctx->callData->args[0].asReturnedValue();
+ return ctx->d()->callData->args[0].asReturnedValue();
}
#endif // QT_NO_TRANSLATION
QV4::ReturnedValue GlobalExtensions::method_gc(CallContext *ctx)
{
- ctx->engine->memoryManager->runGC();
+ ctx->d()->engine->memoryManager->runGC();
return QV4::Encode::undefined();
}
@@ -1842,21 +1859,21 @@ QV4::ReturnedValue GlobalExtensions::method_gc(CallContext *ctx)
ReturnedValue GlobalExtensions::method_string_arg(CallContext *ctx)
{
- if (ctx->callData->argc != 1)
+ if (ctx->d()->callData->argc != 1)
V4THROW_ERROR("String.arg(): Invalid arguments");
- QString value = ctx->callData->thisObject.toQString();
+ QString value = ctx->d()->callData->thisObject.toQString();
QV4::Scope scope(ctx);
- QV4::ScopedValue arg(scope, ctx->callData->args[0]);
+ QV4::ScopedValue arg(scope, ctx->d()->callData->args[0]);
if (arg->isInteger())
- return ctx->engine->newString(value.arg(arg->integerValue()))->asReturnedValue();
+ return ctx->d()->engine->newString(value.arg(arg->integerValue()))->asReturnedValue();
else if (arg->isDouble())
- return ctx->engine->newString(value.arg(arg->doubleValue()))->asReturnedValue();
+ return ctx->d()->engine->newString(value.arg(arg->doubleValue()))->asReturnedValue();
else if (arg->isBoolean())
- return ctx->engine->newString(value.arg(arg->booleanValue()))->asReturnedValue();
+ return ctx->d()->engine->newString(value.arg(arg->booleanValue()))->asReturnedValue();
- return ctx->engine->newString(value.arg(arg->toQString()))->asReturnedValue();
+ return ctx->d()->engine->newString(value.arg(arg->toQString()))->asReturnedValue();
}
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
index adc0c6ce4f..9732a468df 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
@@ -65,8 +65,13 @@ namespace QV4 {
struct QtObject : Object
{
- V4_OBJECT
- QtObject(ExecutionEngine *v4, QQmlEngine *qmlEngine);
+ struct Data : Object::Data {
+ Data(ExecutionEngine *v4, QQmlEngine *qmlEngine);
+ QObject *platform;
+ QObject *application;
+ };
+ V4_OBJECT(Object)
+
static ReturnedValue method_isQtObject(CallContext *ctx);
static ReturnedValue method_rgba(CallContext *ctx);
@@ -104,14 +109,13 @@ struct QtObject : Object
#ifndef QT_NO_IM
static ReturnedValue method_get_inputMethod(CallContext *ctx);
#endif
-
- QObject *m_platform;
- QObject *m_application;
};
struct ConsoleObject : Object
{
- ConsoleObject(ExecutionEngine *v4);
+ struct Data : Object::Data {
+ Data(ExecutionEngine *engine);
+ };
static ReturnedValue method_error(CallContext *ctx);
static ReturnedValue method_log(CallContext *ctx);
@@ -147,18 +151,23 @@ struct GlobalExtensions {
struct QQmlBindingFunction : public QV4::FunctionObject
{
- V4_OBJECT
- QQmlBindingFunction(FunctionObject *originalFunction);
+ struct Data : FunctionObject::Data {
+ Data(FunctionObject *originalFunction);
+ QV4::FunctionObject *originalFunction;
+ // Set when the binding is created later
+ QQmlSourceLocation bindingLocation;
+ };
+ V4_OBJECT(QV4::FunctionObject)
void initBindingLocation(); // from caller stack trace
static ReturnedValue call(Managed *that, CallData *callData);
static void markObjects(Managed *that, ExecutionEngine *e);
+ static void destroy(Managed *that) {
+ static_cast<QQmlBindingFunction *>(that)->d()->~Data();
+ }
- QV4::FunctionObject *originalFunction;
- // Set when the binding is created later
- QQmlSourceLocation bindingLocation;
};
}
diff --git a/src/qml/qml/v8/qv4domerrors_p.h b/src/qml/qml/v8/qv4domerrors_p.h
index faf52ce1ad..30cbd61467 100644
--- a/src/qml/qml/v8/qv4domerrors_p.h
+++ b/src/qml/qml/v8/qv4domerrors_p.h
@@ -77,9 +77,9 @@ QT_BEGIN_NAMESPACE
#define DOMEXCEPTION_TYPE_MISMATCH_ERR 17
#define V4THROW_DOM(error, string) { \
- QV4::ScopedValue v(scope, ctx->engine->newString(QStringLiteral(string))); \
- QV4::Scoped<Object> ex(scope, ctx->engine->newErrorObject(v)); \
- ex->put(QV4::ScopedString(scope, ctx->engine->newIdentifier(QStringLiteral("code"))), QV4::ScopedValue(scope, QV4::Primitive::fromInt32(error))); \
+ QV4::ScopedValue v(scope, scope.engine->newString(QStringLiteral(string))); \
+ QV4::Scoped<Object> ex(scope, scope.engine->newErrorObject(v)); \
+ ex->put(QV4::ScopedString(scope, scope.engine->newIdentifier(QStringLiteral("code"))).getPointer(), QV4::ScopedValue(scope, QV4::Primitive::fromInt32(error))); \
return ctx->throwError(ex); \
}
diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp
index 8305649177..68f312353a 100644
--- a/src/qml/qml/v8/qv8engine.cpp
+++ b/src/qml/qml/v8/qv8engine.cpp
@@ -130,7 +130,7 @@ QVariant QV8Engine::toVariant(const QV4::ValueRef value, int typeHint)
QV4::Scope scope(m_v4Engine);
if (QV4::VariantObject *v = value->as<QV4::VariantObject>())
- return v->data;
+ return v->d()->data;
if (typeHint == QVariant::Bool)
return QVariant(value->toBoolean());
@@ -229,9 +229,9 @@ static QV4::ReturnedValue objectFromVariantMap(QV8Engine *engine, const QVariant
for (QVariantMap::ConstIterator iter = map.begin(); iter != map.end(); ++iter) {
s = e->newString(iter.key());
uint idx = s->asArrayIndex();
- if (idx > 16 && (!o->arrayData || idx > o->arrayData->length() * 2))
+ if (idx > 16 && (!o->arrayData() || idx > o->arrayData()->length() * 2))
o->initSparseArray();
- o->put(s, (v = engine->fromVariant(iter.value())));
+ o->put(s.getPointer(), (v = engine->fromVariant(iter.value())));
}
return o.asReturnedValue();
}
@@ -261,7 +261,7 @@ QV4::ReturnedValue QV8Engine::fromVariant(const QVariant &variant)
case QMetaType::Double:
return QV4::Encode(*reinterpret_cast<const double*>(ptr));
case QMetaType::QString:
- return m_v4Engine->currentContext()->engine->newString(*reinterpret_cast<const QString*>(ptr))->asReturnedValue();
+ return m_v4Engine->currentContext()->d()->engine->newString(*reinterpret_cast<const QString*>(ptr))->asReturnedValue();
case QMetaType::Float:
return QV4::Encode(*reinterpret_cast<const float*>(ptr));
case QMetaType::Short:
@@ -398,7 +398,7 @@ QVariant QV8Engine::toBasicVariant(const QV4::ValueRef value)
if (value->isString())
return value->stringValue()->toQString();
if (QQmlLocaleData *ld = value->as<QQmlLocaleData>())
- return ld->locale;
+ return ld->d()->locale;
if (QV4::DateObject *d = value->asDateObject())
return d->toQDateTime();
// NOTE: since we convert QTime to JS Date, round trip will change the variant type (to QDateTime)!
@@ -444,9 +444,9 @@ void QV8Engine::initializeGlobal()
qt_add_sqlexceptions(m_v4Engine);
{
- for (uint i = 0; i < m_v4Engine->globalObject->internalClass->size; ++i) {
- if (m_v4Engine->globalObject->internalClass->nameMap.at(i))
- m_illegalNames.insert(m_v4Engine->globalObject->internalClass->nameMap.at(i)->toQString());
+ for (uint i = 0; i < m_v4Engine->globalObject->internalClass()->size; ++i) {
+ if (m_v4Engine->globalObject->internalClass()->nameMap.at(i))
+ m_illegalNames.insert(m_v4Engine->globalObject->internalClass()->nameMap.at(i)->toQString());
}
}
@@ -469,7 +469,7 @@ void QV8Engine::initializeGlobal()
" }"\
"})"
- QV4::Scoped<QV4::FunctionObject> result(scope, QV4::Script::evaluate(m_v4Engine, QString::fromUtf8(FREEZE_SOURCE), QV4::ObjectRef::null()));
+ QV4::Scoped<QV4::FunctionObject> result(scope, QV4::Script::evaluate(m_v4Engine, QString::fromUtf8(FREEZE_SOURCE), 0));
Q_ASSERT(!!result);
m_freezeObject = result;
#undef FREEZE_SOURCE
@@ -486,11 +486,6 @@ void QV8Engine::freezeObject(const QV4::ValueRef value)
f->call(callData);
}
-void QV8Engine::gc()
-{
- m_v4Engine->memoryManager->runGC();
-}
-
struct QV8EngineRegistrationData
{
QV8EngineRegistrationData() : extensionCount(0) {}
@@ -560,8 +555,7 @@ QV4::ReturnedValue QV8Engine::variantListToJS(const QVariantList &lst)
// The result is a QVariantList with length equal to the length
// of the JS Array, and elements being the JS Array's elements
// converted to QVariants, recursively.
-QVariantList QV8Engine::variantListFromJS(QV4::ArrayObjectRef a,
- V8ObjectSet &visitedObjects)
+QVariantList QV8Engine::variantListFromJS(QV4::ArrayObject *a, V8ObjectSet &visitedObjects)
{
QVariantList result;
if (!a)
@@ -605,7 +599,7 @@ QV4::ReturnedValue QV8Engine::variantMapToJS(const QVariantMap &vmap)
if (idx < UINT_MAX)
o->arraySet(idx, v);
else
- o->insertMember(s, v);
+ o->insertMember(s.getPointer(), v);
}
return o.asReturnedValue();
}
@@ -614,8 +608,7 @@ QV4::ReturnedValue QV8Engine::variantMapToJS(const QVariantMap &vmap)
// The result is a QVariantMap with keys being the property names
// of the object, and values being the values of the JS object's
// properties converted to QVariants, recursively.
-QVariantMap QV8Engine::variantMapFromJS(QV4::ObjectRef o,
- V8ObjectSet &visitedObjects)
+QVariantMap QV8Engine::variantMapFromJS(QV4::Object *o, V8ObjectSet &visitedObjects)
{
QVariantMap result;
@@ -679,7 +672,7 @@ QV4::ReturnedValue QV8Engine::metaTypeToJS(int type, const void *data)
case QMetaType::Double:
return QV4::Encode(*reinterpret_cast<const double*>(data));
case QMetaType::QString:
- return m_v4Engine->currentContext()->engine->newString(*reinterpret_cast<const QString*>(data))->asReturnedValue();
+ return m_v4Engine->currentContext()->d()->engine->newString(*reinterpret_cast<const QString*>(data))->asReturnedValue();
case QMetaType::Float:
return QV4::Encode(*reinterpret_cast<const float*>(data));
case QMetaType::Short:
@@ -882,7 +875,7 @@ bool QV8Engine::metaTypeFromJS(const QV4::ValueRef value, int type, void *data)
return true;
if (value->as<QV4::VariantObject>() && name.endsWith('*')) {
int valueType = QMetaType::type(name.left(name.size()-1));
- QVariant &var = value->as<QV4::VariantObject>()->data;
+ QVariant &var = value->as<QV4::VariantObject>()->d()->data;
if (valueType == var.userType()) {
// We have T t, T* is requested, so return &t.
*reinterpret_cast<void* *>(data) = var.data();
@@ -893,12 +886,12 @@ bool QV8Engine::metaTypeFromJS(const QV4::ValueRef value, int type, void *data)
while (proto) {
bool canCast = false;
if (QV4::VariantObject *vo = proto->as<QV4::VariantObject>()) {
- const QVariant &v = vo->data;
+ const QVariant &v = vo->d()->data;
canCast = (type == v.userType()) || (valueType && (valueType == v.userType()));
}
else if (proto->as<QV4::QObjectWrapper>()) {
QByteArray className = name.left(name.size()-1);
- QV4::ScopedObject p(scope, proto);
+ QV4::ScopedObject p(scope, proto.getPointer());
if (QObject *qobject = qtObjectFromJS(p))
canCast = qobject->qt_metacast(className) != 0;
}
@@ -969,7 +962,7 @@ QVariant QV8Engine::variantFromJS(const QV4::ValueRef value,
if (QV4::RegExpObject *re = value->as<QV4::RegExpObject>())
return re->toQRegExp();
if (QV4::VariantObject *v = value->as<QV4::VariantObject>())
- return v->data;
+ return v->d()->data;
if (value->as<QV4::QObjectWrapper>())
return qVariantFromValue(qtObjectFromJS(value));
if (QV4::QmlValueTypeWrapper *v = value->as<QV4::QmlValueTypeWrapper>())
@@ -1003,7 +996,7 @@ QObject *QV8Engine::qtObjectFromJS(const QV4::ValueRef value)
QV4::Scoped<QV4::VariantObject> v(scope, value);
if (v) {
- QVariant variant = v->data;
+ QVariant variant = v->d()->data;
int type = variant.userType();
if (type == QMetaType::QObjectStar)
return *reinterpret_cast<QObject* const *>(variant.constData());
diff --git a/src/qml/qml/v8/qv8engine_p.h b/src/qml/qml/v8/qv8engine_p.h
index 1295e671f0..a5b94e8bdf 100644
--- a/src/qml/qml/v8/qv8engine_p.h
+++ b/src/qml/qml/v8/qv8engine_p.h
@@ -219,8 +219,6 @@ public:
// Return the list of illegal id names (the names of the properties on the global object)
const QSet<QString> &illegalNames() const;
- void gc();
-
static QMutex *registrationMutex();
static int registerExtension();
@@ -228,11 +226,11 @@ public:
void setExtensionData(int, Deletable *);
QV4::ReturnedValue variantListToJS(const QVariantList &lst);
- inline QVariantList variantListFromJS(QV4::ArrayObjectRef array)
+ inline QVariantList variantListFromJS(QV4::ArrayObject *array)
{ V8ObjectSet visitedObjects; return variantListFromJS(array, visitedObjects); }
QV4::ReturnedValue variantMapToJS(const QVariantMap &vmap);
- inline QVariantMap variantMapFromJS(QV4::ObjectRef object)
+ inline QVariantMap variantMapFromJS(QV4::Object *object)
{ V8ObjectSet visitedObjects; return variantMapFromJS(object, visitedObjects); }
QV4::ReturnedValue variantToJS(const QVariant &value);
@@ -280,8 +278,8 @@ protected:
void initializeGlobal();
private:
- QVariantList variantListFromJS(QV4::ArrayObjectRef array, V8ObjectSet &visitedObjects);
- QVariantMap variantMapFromJS(QV4::ObjectRef object, V8ObjectSet &visitedObjects);
+ QVariantList variantListFromJS(QV4::ArrayObject *array, V8ObjectSet &visitedObjects);
+ QVariantMap variantMapFromJS(QV4::Object *object, V8ObjectSet &visitedObjects);
QVariant variantFromJS(const QV4::ValueRef value, V8ObjectSet &visitedObjects);
Q_DISABLE_COPY(QV8Engine)
diff --git a/src/qml/types/qqmlconnections.cpp b/src/qml/types/qqmlconnections.cpp
index 99ec0b55de..b0e814d285 100644
--- a/src/qml/types/qqmlconnections.cpp
+++ b/src/qml/types/qqmlconnections.cpp
@@ -68,8 +68,8 @@ public:
bool ignoreUnknownSignals;
bool componentcomplete;
- QByteArray data;
QQmlRefPointer<QQmlCompiledData> cdata;
+ QList<const QV4::CompiledData::Binding *> bindings;
};
/*!
@@ -205,18 +205,15 @@ void QQmlConnections::setIgnoreUnknownSignals(bool ignore)
d->ignoreUnknownSignals = ignore;
}
-QByteArray QQmlConnectionsParser::compile(const QV4::CompiledData::QmlUnit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &props)
+void QQmlConnectionsParser::verifyBindings(const QV4::CompiledData::QmlUnit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &props)
{
- QByteArray rv;
- QDataStream ds(&rv, QIODevice::WriteOnly);
-
for (int ii = 0; ii < props.count(); ++ii) {
const QV4::CompiledData::Binding *binding = props.at(ii);
QString propName = qmlUnit->header.stringAt(binding->propertyNameIndex);
if (!propName.startsWith(QLatin1String("on")) || !propName.at(2).isUpper()) {
error(props.at(ii), QQmlConnections::tr("Cannot assign to non-existent property \"%1\"").arg(propName));
- return QByteArray();
+ return;
}
@@ -226,56 +223,48 @@ QByteArray QQmlConnectionsParser::compile(const QV4::CompiledData::QmlUnit *qmlU
error(binding, QQmlConnections::tr("Connections: nested objects not allowed"));
else
error(binding, QQmlConnections::tr("Connections: syntax error"));
- return QByteArray();
+ return;
} if (binding->type != QV4::CompiledData::Binding::Type_Script) {
error(binding, QQmlConnections::tr("Connections: script expected"));
- return QByteArray();
- } else {
- ds << propName;
- ds << bindingIdentifier(binding);
+ return;
}
}
-
- return rv;
}
-void QQmlConnectionsParser::setCustomData(QObject *object, const QByteArray &data, QQmlCompiledData *cdata)
+void QQmlConnectionsParser::applyBindings(QObject *object, QQmlCompiledData *cdata, const QList<const QV4::CompiledData::Binding *> &bindings)
{
QQmlConnectionsPrivate *p =
static_cast<QQmlConnectionsPrivate *>(QObjectPrivate::get(object));
- p->data = data;
p->cdata = cdata;
+ p->bindings = bindings;
}
-
void QQmlConnections::connectSignals()
{
Q_D(QQmlConnections);
if (!d->componentcomplete || (d->targetSet && !target()))
return;
- QDataStream ds(d->data);
- while (!ds.atEnd()) {
- QString propName;
- ds >> propName;
- int bindingId;
- ds >> bindingId;
+ if (d->bindings.isEmpty())
+ return;
+ QObject *target = this->target();
+ QQmlData *ddata = QQmlData::get(this);
+ QQmlContextData *ctxtdata = ddata ? ddata->outerContext : 0;
+
+ const QV4::CompiledData::QmlUnit *qmlUnit = d->cdata->qmlUnit;
+ foreach (const QV4::CompiledData::Binding *binding, d->bindings) {
+ Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Script);
+ QString propName = qmlUnit->header.stringAt(binding->propertyNameIndex);
- QQmlProperty prop(target(), propName);
+ QQmlProperty prop(target, propName);
if (prop.isValid() && (prop.type() & QQmlProperty::SignalProperty)) {
int signalIndex = QQmlPropertyPrivate::get(prop)->signalIndex();
QQmlBoundSignal *signal =
- new QQmlBoundSignal(target(), signalIndex, this, qmlEngine(this));
-
- QQmlContextData *ctxtdata = 0;
- QQmlData *ddata = QQmlData::get(this);
- if (ddata) {
- ctxtdata = ddata->outerContext;
- }
+ new QQmlBoundSignal(target, signalIndex, this, qmlEngine(this));
QQmlBoundSignalExpression *expression = ctxtdata ?
- new QQmlBoundSignalExpression(target(), signalIndex,
- ctxtdata, this, d->cdata->functionForBindingId(bindingId)) : 0;
+ new QQmlBoundSignalExpression(target, signalIndex,
+ ctxtdata, this, d->cdata->compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex]) : 0;
signal->takeExpression(expression);
d->boundsignals += signal;
} else {
diff --git a/src/qml/types/qqmlconnections_p.h b/src/qml/types/qqmlconnections_p.h
index f169eeb53f..e829828bd8 100644
--- a/src/qml/types/qqmlconnections_p.h
+++ b/src/qml/types/qqmlconnections_p.h
@@ -84,8 +84,8 @@ private:
class QQmlConnectionsParser : public QQmlCustomParser
{
public:
- virtual QByteArray compile(const QV4::CompiledData::QmlUnit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &props);
- virtual void setCustomData(QObject *, const QByteArray &, QQmlCompiledData *cdata);
+ virtual void verifyBindings(const QV4::CompiledData::QmlUnit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &props);
+ virtual void applyBindings(QObject *object, QQmlCompiledData *cdata, const QList<const QV4::CompiledData::Binding *> &bindings);
};
diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp
index 4591d42710..e2f1cffb16 100644
--- a/src/qml/types/qqmldelegatemodel.cpp
+++ b/src/qml/types/qqmldelegatemodel.cpp
@@ -61,17 +61,23 @@ class QQmlDelegateModelItem;
struct DelegateModelGroupFunction: QV4::FunctionObject
{
- V4_OBJECT
+ struct Data : FunctionObject::Data {
+ Data(QV4::ExecutionContext *scope, uint flag, QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::ValueRef arg))
+ : FunctionObject::Data(scope, QStringLiteral("DelegateModelGroupFunction"))
+ , flag(flag)
+ , code(code)
+ {
+ setVTable(staticVTable());
+ }
- QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::ValueRef arg);
- uint flag;
+ uint flag;
+ QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::ValueRef arg);
+ };
+ V4_OBJECT(QV4::FunctionObject)
- DelegateModelGroupFunction(QV4::ExecutionContext *scope, uint flag, QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::ValueRef arg))
- : FunctionObject(scope, QStringLiteral("DelegateModelGroupFunction"))
- , code(code)
- , flag(flag)
+ static DelegateModelGroupFunction *create(QV4::ExecutionContext *scope, uint flag, QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::ValueRef arg))
{
- setVTable(staticVTable());
+ return scope->engine()->memoryManager->alloc<DelegateModelGroupFunction>(scope, flag, code);
}
static QV4::ReturnedValue construct(QV4::Managed *m, QV4::CallData *)
@@ -89,7 +95,7 @@ struct DelegateModelGroupFunction: QV4::FunctionObject
return v4->currentContext()->throwTypeError(QStringLiteral("Not a valid VisualData object"));
QV4::ScopedValue v(scope, callData->argument(0));
- return f->code(o->item, f->flag, v);
+ return f->d()->code(o->d()->item, f->d()->flag, v);
}
};
@@ -103,8 +109,7 @@ public:
QQmlDelegateModelEngineData(QV8Engine *engine);
~QQmlDelegateModelEngineData();
- QV4::ReturnedValue array(QV8Engine *engine, const QVector<QQmlChangeSet::Remove> &changes);
- QV4::ReturnedValue array(QV8Engine *engine, const QVector<QQmlChangeSet::Insert> &changes);
+ QV4::ReturnedValue array(QV8Engine *engine, const QVector<QQmlChangeSet::Change> &changes);
QV4::PersistentValue changeProto;
};
@@ -722,8 +727,8 @@ void QQmlDelegateModelPrivate::updateFilterGroup()
QQmlDelegateModelGroupPrivate::get(m_groups[m_compositorGroup])->emitters.insert(this);
if (m_compositorGroup != previousGroup) {
- QVector<QQmlChangeSet::Remove> removes;
- QVector<QQmlChangeSet::Insert> inserts;
+ QVector<QQmlChangeSet::Change> removes;
+ QVector<QQmlChangeSet::Change> inserts;
m_compositor.transition(previousGroup, m_compositorGroup, &removes, &inserts);
QQmlChangeSet changeSet;
@@ -903,7 +908,7 @@ QObject *QQmlDelegateModelPrivate::object(Compositor::Group group, int index, bo
if (!m_delegate || index < 0 || index >= m_compositor.count(group)) {
qWarning() << "DelegateModel::item: index out range" << index << m_compositor.count(group);
return 0;
- } else if (!m_context->isValid()) {
+ } else if (!m_context || !m_context->isValid()) {
return 0;
}
@@ -946,7 +951,7 @@ QObject *QQmlDelegateModelPrivate::object(Compositor::Group group, int index, bo
cacheItem->incubationTask->index[i] = it.index[i];
QQmlContextData *ctxt = new QQmlContextData;
- ctxt->setParent(QQmlContextData::get(creationContext ? creationContext : m_context));
+ ctxt->setParent(QQmlContextData::get(creationContext ? creationContext : m_context.data()));
ctxt->contextObject = cacheItem;
cacheItem->contextData = ctxt;
@@ -1143,7 +1148,7 @@ static void incrementIndexes(QQmlDelegateModelItem *cacheItem, int count, const
void QQmlDelegateModelPrivate::itemsInserted(
const QVector<Compositor::Insert> &inserts,
- QVarLengthArray<QVector<QQmlChangeSet::Insert>, Compositor::MaximumGroupCount> *translatedInserts,
+ QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> *translatedInserts,
QHash<int, QList<QQmlDelegateModelItem *> > *movedItems)
{
int cacheIndex = 0;
@@ -1159,7 +1164,7 @@ void QQmlDelegateModelPrivate::itemsInserted(
for (int i = 1; i < m_groupCount; ++i) {
if (insert.inGroup(i)) {
(*translatedInserts)[i].append(
- QQmlChangeSet::Insert(insert.index[i], insert.count, insert.moveId));
+ QQmlChangeSet::Change(insert.index[i], insert.count, insert.moveId));
inserted[i] += insert.count;
}
}
@@ -1200,7 +1205,7 @@ void QQmlDelegateModelPrivate::itemsInserted(
void QQmlDelegateModelPrivate::itemsInserted(const QVector<Compositor::Insert> &inserts)
{
- QVarLengthArray<QVector<QQmlChangeSet::Insert>, Compositor::MaximumGroupCount> translatedInserts(m_groupCount);
+ QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> translatedInserts(m_groupCount);
itemsInserted(inserts, &translatedInserts);
Q_ASSERT(m_cache.count() == m_compositor.count(Compositor::Cache));
if (!m_delegate)
@@ -1234,7 +1239,7 @@ void QQmlDelegateModel::_q_itemsInserted(int index, int count)
void QQmlDelegateModelPrivate::itemsRemoved(
const QVector<Compositor::Remove> &removes,
- QVarLengthArray<QVector<QQmlChangeSet::Remove>, Compositor::MaximumGroupCount> *translatedRemoves,
+ QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> *translatedRemoves,
QHash<int, QList<QQmlDelegateModelItem *> > *movedItems)
{
int cacheIndex = 0;
@@ -1251,7 +1256,7 @@ void QQmlDelegateModelPrivate::itemsRemoved(
for (int i = 1; i < m_groupCount; ++i) {
if (remove.inGroup(i)) {
(*translatedRemoves)[i].append(
- QQmlChangeSet::Remove(remove.index[i], remove.count, remove.moveId));
+ QQmlChangeSet::Change(remove.index[i], remove.count, remove.moveId));
removed[i] -= remove.count;
}
}
@@ -1318,7 +1323,7 @@ void QQmlDelegateModelPrivate::itemsRemoved(
void QQmlDelegateModelPrivate::itemsRemoved(const QVector<Compositor::Remove> &removes)
{
- QVarLengthArray<QVector<QQmlChangeSet::Remove>, Compositor::MaximumGroupCount> translatedRemoves(m_groupCount);
+ QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> translatedRemoves(m_groupCount);
itemsRemoved(removes, &translatedRemoves);
Q_ASSERT(m_cache.count() == m_compositor.count(Compositor::Cache));
if (!m_delegate)
@@ -1356,10 +1361,10 @@ void QQmlDelegateModelPrivate::itemsMoved(
{
QHash<int, QList<QQmlDelegateModelItem *> > movedItems;
- QVarLengthArray<QVector<QQmlChangeSet::Remove>, Compositor::MaximumGroupCount> translatedRemoves(m_groupCount);
+ QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> translatedRemoves(m_groupCount);
itemsRemoved(removes, &translatedRemoves, &movedItems);
- QVarLengthArray<QVector<QQmlChangeSet::Insert>, Compositor::MaximumGroupCount> translatedInserts(m_groupCount);
+ QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> translatedInserts(m_groupCount);
itemsInserted(inserts, &translatedInserts, &movedItems);
Q_ASSERT(m_cache.count() == m_compositor.count(Compositor::Cache));
Q_ASSERT(movedItems.isEmpty());
@@ -1409,7 +1414,7 @@ void QQmlDelegateModelPrivate::emitModelUpdated(const QQmlChangeSet &changeSet,
void QQmlDelegateModelPrivate::emitChanges()
{
- if (m_transaction || !m_complete || !m_context->isValid())
+ if (m_transaction || !m_complete || !m_context || !m_context->isValid())
return;
m_transaction = true;
@@ -1594,7 +1599,7 @@ QQmlDelegateModelAttached *QQmlDelegateModel::qmlAttachedProperties(QObject *obj
bool QQmlDelegateModelPrivate::insert(Compositor::insert_iterator &before, const QV4::ValueRef object, int groups)
{
- if (!m_context->isValid())
+ if (!m_context || !m_context->isValid())
return false;
QQmlDelegateModelItem *cacheItem = m_adaptorModel.createItem(m_cacheMetaType, m_context->engine(), -1);
@@ -1687,43 +1692,44 @@ void QQmlDelegateModelItemMetaType::initializePrototype()
QV4::ScopedProperty p(scope);
s = v4->newString(QStringLiteral("isUnresolved"));
- p->setGetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, 30, QQmlDelegateModelItem::get_member));
+ QV4::ScopedFunctionObject f(scope);
+ p->setGetter((f = DelegateModelGroupFunction::create(v4->rootContext, 30, QQmlDelegateModelItem::get_member)));
p->setSetter(0);
- proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
+ proto->insertMember(s.getPointer(), p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
s = v4->newString(QStringLiteral("inItems"));
- p->setGetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, QQmlListCompositor::Default, QQmlDelegateModelItem::get_member));
- p->setSetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, QQmlListCompositor::Default, QQmlDelegateModelItem::set_member));
- proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
+ p->setGetter((f = DelegateModelGroupFunction::create(v4->rootContext, QQmlListCompositor::Default, QQmlDelegateModelItem::get_member)));
+ p->setSetter((f = DelegateModelGroupFunction::create(v4->rootContext, QQmlListCompositor::Default, QQmlDelegateModelItem::set_member)));
+ proto->insertMember(s.getPointer(), p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
s = v4->newString(QStringLiteral("inPersistedItems"));
- p->setGetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, QQmlListCompositor::Persisted, QQmlDelegateModelItem::get_member));
- p->setSetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, QQmlListCompositor::Persisted, QQmlDelegateModelItem::set_member));
- proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
+ p->setGetter((f = DelegateModelGroupFunction::create(v4->rootContext, QQmlListCompositor::Persisted, QQmlDelegateModelItem::get_member)));
+ p->setSetter((f = DelegateModelGroupFunction::create(v4->rootContext, QQmlListCompositor::Persisted, QQmlDelegateModelItem::set_member)));
+ proto->insertMember(s.getPointer(), p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
s = v4->newString(QStringLiteral("itemsIndex"));
- p->setGetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, QQmlListCompositor::Default, QQmlDelegateModelItem::get_index));
- proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
+ p->setGetter((f = DelegateModelGroupFunction::create(v4->rootContext, QQmlListCompositor::Default, QQmlDelegateModelItem::get_index)));
+ proto->insertMember(s.getPointer(), p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
s = v4->newString(QStringLiteral("persistedItemsIndex"));
- p->setGetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, QQmlListCompositor::Persisted, QQmlDelegateModelItem::get_index));
+ p->setGetter((f = DelegateModelGroupFunction::create(v4->rootContext, QQmlListCompositor::Persisted, QQmlDelegateModelItem::get_index)));
p->setSetter(0);
- proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
+ proto->insertMember(s.getPointer(), p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
for (int i = 2; i < groupNames.count(); ++i) {
QString propertyName = QStringLiteral("in") + groupNames.at(i);
propertyName.replace(2, 1, propertyName.at(2).toUpper());
s = v4->newString(propertyName);
- p->setGetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, i + 1, QQmlDelegateModelItem::get_member));
- p->setSetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, i + 1, QQmlDelegateModelItem::set_member));
- proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
+ p->setGetter((f = DelegateModelGroupFunction::create(v4->rootContext, i + 1, QQmlDelegateModelItem::get_member)));
+ p->setSetter((f = DelegateModelGroupFunction::create(v4->rootContext, i + 1, QQmlDelegateModelItem::set_member)));
+ proto->insertMember(s.getPointer(), p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
}
for (int i = 2; i < groupNames.count(); ++i) {
const QString propertyName = groupNames.at(i) + QStringLiteral("Index");
s = v4->newString(propertyName);
- p->setGetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, i + 1, QQmlDelegateModelItem::get_index));
+ p->setGetter((f = DelegateModelGroupFunction::create(v4->rootContext, i + 1, QQmlDelegateModelItem::get_index)));
p->setSetter(0);
- proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
+ proto->insertMember(s.getPointer(), p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
}
modelItemProto = proto;
}
@@ -1771,46 +1777,46 @@ int QQmlDelegateModelItemMetaType::parseGroups(const QV4::ValueRef groups) const
QV4::ReturnedValue QQmlDelegateModelItem::get_model(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
- QV4::Scoped<QQmlDelegateModelItemObject> o(scope, ctx->callData->thisObject.as<QQmlDelegateModelItemObject>());
+ QV4::Scoped<QQmlDelegateModelItemObject> o(scope, ctx->d()->callData->thisObject.as<QQmlDelegateModelItemObject>());
if (!o)
return ctx->throwTypeError(QStringLiteral("Not a valid VisualData object"));
- if (!o->item->metaType->model)
+ if (!o->d()->item->metaType->model)
return QV4::Encode::undefined();
- return o->item->get();
+ return o->d()->item->get();
}
QV4::ReturnedValue QQmlDelegateModelItem::get_groups(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
- QV4::Scoped<QQmlDelegateModelItemObject> o(scope, ctx->callData->thisObject.as<QQmlDelegateModelItemObject>());
+ QV4::Scoped<QQmlDelegateModelItemObject> o(scope, ctx->d()->callData->thisObject.as<QQmlDelegateModelItemObject>());
if (!o)
return ctx->throwTypeError(QStringLiteral("Not a valid VisualData object"));
QStringList groups;
- for (int i = 1; i < o->item->metaType->groupCount; ++i) {
- if (o->item->groups & (1 << i))
- groups.append(o->item->metaType->groupNames.at(i - 1));
+ for (int i = 1; i < o->d()->item->metaType->groupCount; ++i) {
+ if (o->d()->item->groups & (1 << i))
+ groups.append(o->d()->item->metaType->groupNames.at(i - 1));
}
- return ctx->engine->v8Engine->fromVariant(groups);
+ return scope.engine->v8Engine->fromVariant(groups);
}
QV4::ReturnedValue QQmlDelegateModelItem::set_groups(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
- QV4::Scoped<QQmlDelegateModelItemObject> o(scope, ctx->callData->thisObject.as<QQmlDelegateModelItemObject>());
+ QV4::Scoped<QQmlDelegateModelItemObject> o(scope, ctx->d()->callData->thisObject.as<QQmlDelegateModelItemObject>());
if (!o)
return ctx->throwTypeError(QStringLiteral("Not a valid VisualData object"));
- if (!ctx->callData->argc)
+ if (!ctx->d()->callData->argc)
return ctx->throwTypeError();
- if (!o->item->metaType->model)
+ if (!o->d()->item->metaType->model)
return QV4::Encode::undefined();
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(o->item->metaType->model);
+ QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(o->d()->item->metaType->model);
- const int groupFlags = model->m_cacheMetaType->parseGroups(ctx->callData->args[0]);
- const int cacheIndex = model->m_cache.indexOf(o->item);
+ const int groupFlags = model->m_cacheMetaType->parseGroups(ctx->d()->callData->args[0]);
+ const int cacheIndex = model->m_cache.indexOf(o->d()->item);
Compositor::iterator it = model->m_compositor.find(Compositor::Cache, cacheIndex);
model->setGroups(it, 1, Compositor::Cache, groupFlags);
return QV4::Encode::undefined();
@@ -1852,14 +1858,14 @@ QV4::ReturnedValue QQmlDelegateModelItem::get_index(QQmlDelegateModelItem *thisI
DEFINE_OBJECT_VTABLE(QQmlDelegateModelItemObject);
-QQmlDelegateModelItemObject::~QQmlDelegateModelItemObject()
+QQmlDelegateModelItemObject::Data::~Data()
{
item->Dispose();
}
void QQmlDelegateModelItemObject::destroy(Managed *that)
{
- static_cast<QQmlDelegateModelItemObject *>(that)->~QQmlDelegateModelItemObject();
+ static_cast<QQmlDelegateModelItemObject *>(that)->d()->~Data();
}
@@ -2433,7 +2439,7 @@ QQmlV4Handle QQmlDelegateModelGroup::get(int index)
return QQmlV4Handle(QV4::Encode::undefined());
QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
- if (!model->m_context->isValid()) {
+ if (!model->m_context || !model->m_context->isValid()) {
return QQmlV4Handle(QV4::Encode::undefined());
} else if (index < 0 || index >= model->m_compositor.count(d->group)) {
qmlInfo(this) << tr("get: index out of range");
@@ -2461,7 +2467,7 @@ QQmlV4Handle QQmlDelegateModelGroup::get(int index)
QV8Engine *v8 = model->m_cacheMetaType->v8Engine;
QV4::ExecutionEngine *v4 = QV8Engine::getV4(v8);
QV4::Scope scope(v4);
- QV4::ScopedObject o(scope, new (v4->memoryManager) QQmlDelegateModelItemObject(v4, cacheItem));
+ QV4::ScopedObject o(scope, v4->memoryManager->alloc<QQmlDelegateModelItemObject>(v4, cacheItem));
QV4::ScopedObject p(scope, model->m_cacheMetaType->modelItemProto.value());
o->setPrototype(p.getPointer());
++cacheItem->scriptRef;
@@ -2484,7 +2490,7 @@ bool QQmlDelegateModelGroupPrivate::parseIndex(const QV4::ValueRef value, int *i
QV4::Scoped<QQmlDelegateModelItemObject> object(scope, value);
if (object) {
- QQmlDelegateModelItem * const cacheItem = object->item;
+ QQmlDelegateModelItem * const cacheItem = object->d()->item;
if (QQmlDelegateModelPrivate *model = cacheItem->metaType->model
? QQmlDelegateModelPrivate::get(cacheItem->metaType->model)
: 0) {
@@ -3061,8 +3067,8 @@ void QQmlPartsModel::updateFilterGroup()
QQmlDelegateModelGroupPrivate::get(model->m_groups[m_compositorGroup])->emitters.insert(this);
if (m_compositorGroup != previousGroup) {
- QVector<QQmlChangeSet::Remove> removes;
- QVector<QQmlChangeSet::Insert> inserts;
+ QVector<QQmlChangeSet::Change> removes;
+ QVector<QQmlChangeSet::Change> inserts;
model->m_compositor.transition(previousGroup, m_compositorGroup, &removes, &inserts);
QQmlChangeSet changeSet;
@@ -3203,59 +3209,70 @@ void QQmlPartsModel::emitModelUpdated(const QQmlChangeSet &changeSet, bool reset
struct QQmlDelegateModelGroupChange : QV4::Object
{
- V4_OBJECT
- QQmlDelegateModelGroupChange(QV4::ExecutionEngine *engine)
- : Object(engine)
- {
- setVTable(staticVTable());
+ struct Data : QV4::Object::Data {
+ Data(QV4::ExecutionEngine *engine)
+ : Object::Data(engine)
+ {
+ setVTable(staticVTable());
+ }
+ QQmlChangeSet::Change change;
+ };
+ V4_OBJECT(QV4::Object)
+
+ static QQmlDelegateModelGroupChange *create(QV4::ExecutionEngine *e) {
+ return e->memoryManager->alloc<QQmlDelegateModelGroupChange>(e);
}
static QV4::ReturnedValue method_get_index(QV4::CallContext *ctx) {
QV4::Scope scope(ctx);
- QV4::Scoped<QQmlDelegateModelGroupChange> that(scope, ctx->callData->thisObject.as<QQmlDelegateModelGroupChange>());
+ QV4::Scoped<QQmlDelegateModelGroupChange> that(scope, ctx->d()->callData->thisObject.as<QQmlDelegateModelGroupChange>());
if (!that)
return ctx->throwTypeError();
- return QV4::Encode(that->change.index);
+ return QV4::Encode(that->d()->change.index);
}
static QV4::ReturnedValue method_get_count(QV4::CallContext *ctx) {
QV4::Scope scope(ctx);
- QV4::Scoped<QQmlDelegateModelGroupChange> that(scope, ctx->callData->thisObject.as<QQmlDelegateModelGroupChange>());
+ QV4::Scoped<QQmlDelegateModelGroupChange> that(scope, ctx->d()->callData->thisObject.as<QQmlDelegateModelGroupChange>());
if (!that)
return ctx->throwTypeError();
- return QV4::Encode(that->change.count);
+ return QV4::Encode(that->d()->change.count);
}
static QV4::ReturnedValue method_get_moveId(QV4::CallContext *ctx) {
QV4::Scope scope(ctx);
- QV4::Scoped<QQmlDelegateModelGroupChange> that(scope, ctx->callData->thisObject.as<QQmlDelegateModelGroupChange>());
+ QV4::Scoped<QQmlDelegateModelGroupChange> that(scope, ctx->d()->callData->thisObject.as<QQmlDelegateModelGroupChange>());
if (!that)
return ctx->throwTypeError();
- if (that->change.moveId < 0)
+ if (that->d()->change.moveId < 0)
return QV4::Encode::undefined();
- return QV4::Encode(that->change.moveId);
+ return QV4::Encode(that->d()->change.moveId);
}
-
- QQmlChangeSet::Change change;
};
DEFINE_OBJECT_VTABLE(QQmlDelegateModelGroupChange);
-class QQmlDelegateModelGroupChangeArray : public QV4::Object
-{
- V4_OBJECT
+struct QQmlDelegateModelGroupChangeArray : public QV4::Object
+{
+ struct Data : QV4::Object::Data {
+ Data(QV4::ExecutionEngine *engine, const QVector<QQmlChangeSet::Change> &changes)
+ : Object::Data(engine)
+ , changes(changes)
+ {
+ setVTable(staticVTable());
+ QV4::Scope scope(engine);
+ QV4::ScopedObject o(scope, this);
+ o->setArrayType(QV4::ArrayData::Custom);
+ }
+ QVector<QQmlChangeSet::Change> changes;
+ };
+ V4_OBJECT(QV4::Object)
public:
- QQmlDelegateModelGroupChangeArray(QV4::ExecutionEngine *engine)
- : Object(engine)
+ static QQmlDelegateModelGroupChangeArray *create(QV4::ExecutionEngine *engine, const QVector<QQmlChangeSet::Change> &changes)
{
- setVTable(staticVTable());
- QV4::Scope scope(engine);
- QV4::ScopedObject protectThis(scope, this);
- Q_UNUSED(protectThis);
- setArrayType(QV4::ArrayData::Custom);
+ return engine->memoryManager->alloc<QQmlDelegateModelGroupChangeArray>(engine, changes);
}
- virtual ~QQmlDelegateModelGroupChangeArray() {}
- virtual quint32 count() const = 0;
- virtual const QQmlChangeSet::Change &at(int index) const = 0;
+ quint32 count() const { return d()->changes.count(); }
+ const QQmlChangeSet::Change &at(int index) const { return d()->changes.at(index); }
static QV4::ReturnedValue getIndexed(QV4::Managed *m, uint index, bool *hasProperty)
{
@@ -3274,16 +3291,16 @@ public:
const QQmlChangeSet::Change &change = array->at(index);
QV4::ScopedObject changeProto(scope, engineData(v4->v8Engine)->changeProto.value());
- QV4::Scoped<QQmlDelegateModelGroupChange> object(scope, new (v4->memoryManager) QQmlDelegateModelGroupChange(v4));
+ QV4::Scoped<QQmlDelegateModelGroupChange> object(scope, QQmlDelegateModelGroupChange::create(v4));
object->setPrototype(changeProto.getPointer());
- object->change = change;
+ object->d()->change = change;
if (hasProperty)
*hasProperty = true;
return object.asReturnedValue();
}
- static QV4::ReturnedValue get(QV4::Managed *m, const QV4::StringRef name, bool *hasProperty)
+ static QV4::ReturnedValue get(QV4::Managed *m, QV4::String *name, bool *hasProperty)
{
QQmlDelegateModelGroupChangeArray *array = m->as<QQmlDelegateModelGroupChangeArray>();
if (!array)
@@ -3299,46 +3316,13 @@ public:
}
static void destroy(Managed *that) {
QQmlDelegateModelGroupChangeArray *array = that->as<QQmlDelegateModelGroupChangeArray>();
- assert(array);
- array->~QQmlDelegateModelGroupChangeArray();
+ array->d()->~Data();
}
};
DEFINE_OBJECT_VTABLE(QQmlDelegateModelGroupChangeArray);
-class QQmlDelegateModelGroupRemoveArray : public QQmlDelegateModelGroupChangeArray
-{
-public:
- QQmlDelegateModelGroupRemoveArray(QV4::ExecutionEngine *engine, const QVector<QQmlChangeSet::Remove> &changes)
- : QQmlDelegateModelGroupChangeArray(engine)
- , changes(changes)
- {
- }
-
- quint32 count() const { return changes.count(); }
- const QQmlChangeSet::Change &at(int index) const { return changes.at(index); }
-
-private:
- QVector<QQmlChangeSet::Remove> changes;
-};
-
-class QQmlDelegateModelGroupInsertArray : public QQmlDelegateModelGroupChangeArray
-{
-public:
- QQmlDelegateModelGroupInsertArray(QV4::ExecutionEngine *engine, const QVector<QQmlChangeSet::Insert> &changes)
- : QQmlDelegateModelGroupChangeArray(engine)
- , changes(changes)
- {
- }
-
- quint32 count() const { return changes.count(); }
- const QQmlChangeSet::Change &at(int index) const { return changes.at(index); }
-
-private:
- QVector<QQmlChangeSet::Insert> changes;
-};
-
QQmlDelegateModelEngineData::QQmlDelegateModelEngineData(QV8Engine *e)
{
QV4::ExecutionEngine *v4 = QV8Engine::getV4(e);
@@ -3355,16 +3339,12 @@ QQmlDelegateModelEngineData::~QQmlDelegateModelEngineData()
{
}
-QV4::ReturnedValue QQmlDelegateModelEngineData::array(QV8Engine *engine, const QVector<QQmlChangeSet::Remove> &changes)
+QV4::ReturnedValue QQmlDelegateModelEngineData::array(QV8Engine *engine, const QVector<QQmlChangeSet::Change> &changes)
{
QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
- return (new (v4->memoryManager) QQmlDelegateModelGroupRemoveArray(v4, changes))->asReturnedValue();
-}
-
-QV4::ReturnedValue QQmlDelegateModelEngineData::array(QV8Engine *engine, const QVector<QQmlChangeSet::Insert> &changes)
-{
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
- return (new (v4->memoryManager) QQmlDelegateModelGroupInsertArray(v4, changes))->asReturnedValue();
+ QV4::Scope scope(v4);
+ QV4::ScopedObject o(scope, QQmlDelegateModelGroupChangeArray::create(v4, changes));
+ return o.asReturnedValue();
}
QT_END_NAMESPACE
diff --git a/src/qml/types/qqmldelegatemodel_p_p.h b/src/qml/types/qqmldelegatemodel_p_p.h
index d64f641a1b..7846992e5d 100644
--- a/src/qml/types/qqmldelegatemodel_p_p.h
+++ b/src/qml/types/qqmldelegatemodel_p_p.h
@@ -161,16 +161,19 @@ protected:
struct QQmlDelegateModelItemObject : QV4::Object
{
- V4_OBJECT;
- QQmlDelegateModelItemObject(QV4::ExecutionEngine *engine, QQmlDelegateModelItem *item)
- : Object(engine)
- , item(item)
- { setVTable(staticVTable()); }
- ~QQmlDelegateModelItemObject();
+ struct Data : QV4::Object::Data {
+ Data(QV4::ExecutionEngine *engine, QQmlDelegateModelItem *item)
+ : Object::Data(engine)
+ , item(item)
+ {
+ setVTable(staticVTable());
+ }
+ ~Data();
+ QQmlDelegateModelItem *item;
+ };
+ V4_OBJECT(QV4::Object)
static void destroy(Managed *that);
-
- QQmlDelegateModelItem *item;
};
@@ -275,12 +278,12 @@ public:
void itemsInserted(
const QVector<Compositor::Insert> &inserts,
- QVarLengthArray<QVector<QQmlChangeSet::Insert>, Compositor::MaximumGroupCount> *translatedInserts,
+ QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> *translatedInserts,
QHash<int, QList<QQmlDelegateModelItem *> > *movedItems = 0);
void itemsInserted(const QVector<Compositor::Insert> &inserts);
void itemsRemoved(
const QVector<Compositor::Remove> &removes,
- QVarLengthArray<QVector<QQmlChangeSet::Remove>, Compositor::MaximumGroupCount> *translatedRemoves,
+ QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> *translatedRemoves,
QHash<int, QList<QQmlDelegateModelItem *> > *movedItems = 0);
void itemsRemoved(const QVector<Compositor::Remove> &removes);
void itemsMoved(
@@ -303,7 +306,7 @@ public:
QQmlListCompositor m_compositor;
QQmlComponent *m_delegate;
QQmlDelegateModelItemMetaType *m_cacheMetaType;
- QQmlContext *m_context;
+ QPointer<QQmlContext> m_context;
QQmlDelegateModelParts *m_parts;
QQmlDelegateModelGroupEmitterList m_pendingParts;
diff --git a/src/qml/types/qqmlinstantiator.cpp b/src/qml/types/qqmlinstantiator.cpp
index 724a76825b..73e4ba851a 100644
--- a/src/qml/types/qqmlinstantiator.cpp
+++ b/src/qml/types/qqmlinstantiator.cpp
@@ -137,7 +137,7 @@ void QQmlInstantiatorPrivate::_q_modelUpdated(const QQmlChangeSet &changeSet, bo
int difference = 0;
QHash<int, QVector<QPointer<QObject> > > moved;
- foreach (const QQmlChangeSet::Remove &remove, changeSet.removes()) {
+ foreach (const QQmlChangeSet::Change &remove, changeSet.removes()) {
int index = qMin(remove.index, objects.count());
int count = qMin(remove.index + remove.count, objects.count()) - index;
if (remove.isMove()) {
@@ -156,7 +156,7 @@ void QQmlInstantiatorPrivate::_q_modelUpdated(const QQmlChangeSet &changeSet, bo
difference -= remove.count;
}
- foreach (const QQmlChangeSet::Insert &insert, changeSet.inserts()) {
+ foreach (const QQmlChangeSet::Change &insert, changeSet.inserts()) {
int index = qMin(insert.index, objects.count());
if (insert.isMove()) {
QVector<QPointer<QObject> > movedObjects = moved.value(insert.moveId);
diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp
index be49b6e5a0..46916656b6 100644
--- a/src/qml/types/qqmllistmodel.cpp
+++ b/src/qml/types/qqmllistmodel.cpp
@@ -44,7 +44,7 @@
#include <private/qqmlopenmetaobject_p.h>
#include <private/qqmljsast_p.h>
#include <private/qqmljsengine_p.h>
-
+#include <private/qqmlcompiler_p.h>
#include <private/qqmlcustomparser_p.h>
#include <private/qqmlengine_p.h>
@@ -103,9 +103,9 @@ const ListLayout::Role &ListLayout::getRoleOrCreate(const QString &key, Role::Da
return createRole(key, type);
}
-const ListLayout::Role &ListLayout::getRoleOrCreate(const QV4::StringRef key, Role::DataType type)
+const ListLayout::Role &ListLayout::getRoleOrCreate(QV4::String *key, Role::DataType type)
{
- QStringHash<Role *>::Node *node = roleHash.findNode(key.getPointer());
+ QStringHash<Role *>::Node *node = roleHash.findNode(key);
if (node) {
const Role &r = *node->value;
if (type != r.type)
@@ -239,10 +239,10 @@ const ListLayout::Role *ListLayout::getExistingRole(const QString &key)
return r;
}
-const ListLayout::Role *ListLayout::getExistingRole(const QV4::StringRef key)
+const ListLayout::Role *ListLayout::getExistingRole(QV4::String *key)
{
Role *r = 0;
- QStringHash<Role *>::Node *node = roleHash.findNode(key.getPointer());
+ QStringHash<Role *>::Node *node = roleHash.findNode(key);
if (node)
r = node->value;
return r;
@@ -409,7 +409,7 @@ ListModel *ListModel::getListProperty(int elementIndex, const ListLayout::Role &
return e->getListProperty(role);
}
-void ListModel::set(int elementIndex, QV4::ObjectRef object, QVector<int> *roles, QV8Engine *eng)
+void ListModel::set(int elementIndex, QV4::Object *object, QVector<int> *roles, QV8Engine *eng)
{
ListElement *e = elements[elementIndex];
@@ -432,13 +432,13 @@ void ListModel::set(int elementIndex, QV4::ObjectRef object, QVector<int> *roles
// Add the value now
if ((s = propertyValue)) {
- const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::String);
+ const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName.getPointer(), ListLayout::Role::String);
roleIndex = e->setStringProperty(r, s->toQString());
} else if (propertyValue->isNumber()) {
- const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::Number);
+ const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName.getPointer(), ListLayout::Role::Number);
roleIndex = e->setDoubleProperty(r, propertyValue->asDouble());
} else if ((a = propertyValue)) {
- const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::List);
+ const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName.getPointer(), ListLayout::Role::List);
ListModel *subModel = new ListModel(r.subLayout, 0, -1);
int arrayLength = a->getLength();
@@ -449,16 +449,16 @@ void ListModel::set(int elementIndex, QV4::ObjectRef object, QVector<int> *roles
roleIndex = e->setListProperty(r, subModel);
} else if (propertyValue->isBoolean()) {
- const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::Bool);
+ const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName.getPointer(), ListLayout::Role::Bool);
roleIndex = e->setBoolProperty(r, propertyValue->booleanValue());
} else if (QV4::DateObject *dd = propertyValue->asDateObject()) {
- const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::DateTime);
+ const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName.getPointer(), ListLayout::Role::DateTime);
QDateTime dt = dd->toQDateTime();
roleIndex = e->setDateTimeProperty(r, dt);
} else if (QV4::Object *o = propertyValue->asObject()) {
if (QV4::QObjectWrapper *wrapper = o->as<QV4::QObjectWrapper>()) {
QObject *o = wrapper->object();
- const ListLayout::Role &role = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::QObject);
+ const ListLayout::Role &role = m_layout->getRoleOrCreate(propertyName.getPointer(), ListLayout::Role::QObject);
if (role.type == ListLayout::Role::QObject)
roleIndex = e->setQObjectProperty(role, o);
} else {
@@ -483,7 +483,7 @@ void ListModel::set(int elementIndex, QV4::ObjectRef object, QVector<int> *roles
}
}
-void ListModel::set(int elementIndex, QV4::ObjectRef object, QV8Engine *eng)
+void ListModel::set(int elementIndex, QV4::Object *object, QV8Engine *eng)
{
if (!object)
return;
@@ -580,13 +580,13 @@ void ListModel::remove(int index, int count)
updateCacheIndices();
}
-void ListModel::insert(int elementIndex, QV4::ObjectRef object, QV8Engine *eng)
+void ListModel::insert(int elementIndex, QV4::Object *object, QV8Engine *eng)
{
insertElement(elementIndex);
set(elementIndex, object, eng);
}
-int ListModel::append(QV4::ObjectRef object, QV8Engine *eng)
+int ListModel::append(QV4::Object *object, QV8Engine *eng)
{
int elementIndex = appendElement();
set(elementIndex, object, eng);
@@ -883,7 +883,7 @@ int ListElement::setQObjectProperty(const ListLayout::Role &role, QObject *o)
return roleIndex;
}
-int ListElement::setVariantMapProperty(const ListLayout::Role &role, QV4::ObjectRef o, QV8Engine *eng)
+int ListElement::setVariantMapProperty(const ListLayout::Role &role, QV4::Object *o, QV8Engine *eng)
{
int roleIndex = -1;
@@ -970,7 +970,7 @@ void ListElement::setListPropertyFast(const ListLayout::Role &role, ListModel *m
*value = m;
}
-void ListElement::setVariantMapFast(const ListLayout::Role &role, QV4::ObjectRef o, QV8Engine *eng)
+void ListElement::setVariantMapFast(const ListLayout::Role &role, QV4::Object *o, QV8Engine *eng)
{
char *mem = getPropertyMemory(role);
QVariantMap *map = new (mem) QVariantMap;
@@ -1430,11 +1430,6 @@ void DynamicRoleModelNodeMetaObject::propertyWritten(int index)
}
}
-QQmlListModelParser::ListInstruction *QQmlListModelParser::ListModelData::instructions() const
-{
- return (QQmlListModelParser::ListInstruction *)((char *)this + sizeof(ListModelData));
-}
-
/*!
\qmltype ListModel
\instantiates QQmlListModel
@@ -2290,7 +2285,7 @@ void QQmlListModel::sync()
qmlInfo(this) << "List sync() can only be called from a WorkerScript";
}
-bool QQmlListModelParser::compileProperty(const QV4::CompiledData::QmlUnit *qmlUnit, const QV4::CompiledData::Binding *binding, QList<QQmlListModelParser::ListInstruction> &instr, QByteArray &data)
+bool QQmlListModelParser::verifyProperty(const QV4::CompiledData::QmlUnit *qmlUnit, const QV4::CompiledData::Binding *binding)
{
if (binding->type >= QV4::CompiledData::Binding::Type_Object) {
const quint32 targetObjectIndex = binding->value.objectIndex;
@@ -2305,13 +2300,6 @@ bool QQmlListModelParser::compileProperty(const QV4::CompiledData::QmlUnit *qmlU
listElementTypeName = objName; // cache right name for next time
}
- {
- ListInstruction li;
- li.type = ListInstruction::Push;
- li.dataIdx = -1;
- instr << li;
- }
-
if (!qmlUnit->header.stringAt(target->idIndex).isEmpty()) {
error(target->locationOfIdProperty, QQmlListModel::tr("ListElement: cannot use reserved \"id\" property"));
return false;
@@ -2324,208 +2312,116 @@ bool QQmlListModelParser::compileProperty(const QV4::CompiledData::QmlUnit *qmlU
error(binding, QQmlListModel::tr("ListElement: cannot contain nested elements"));
return false;
}
- ListInstruction li;
- int ref = data.count();
- data.append(propName.toUtf8());
- data.append('\0');
- li.type = ListInstruction::Set;
- li.dataIdx = ref;
- instr << li;
-
- if (!compileProperty(qmlUnit, binding, instr, data))
+ if (!verifyProperty(qmlUnit, binding))
+ return false;
+ }
+ } else if (binding->type == QV4::CompiledData::Binding::Type_Script) {
+ QString scriptStr = binding->valueAsScriptString(&qmlUnit->header);
+ if (!definesEmptyList(scriptStr)) {
+ QByteArray script = scriptStr.toUtf8();
+ bool ok;
+ evaluateEnum(script, &ok);
+ if (!ok) {
+ error(binding, QQmlListModel::tr("ListElement: cannot use script for property value"));
return false;
+ }
+ }
+ }
- li.type = ListInstruction::Pop;
- li.dataIdx = -1;
- instr << li;
+ return true;
+}
+
+bool QQmlListModelParser::applyProperty(const QV4::CompiledData::QmlUnit *qmlUnit, const QV4::CompiledData::Binding *binding, ListModel *model, int outterElementIndex)
+{
+ const QString elementName = qmlUnit->header.stringAt(binding->propertyNameIndex);
+
+ bool roleSet = false;
+ if (binding->type >= QV4::CompiledData::Binding::Type_Object) {
+ const quint32 targetObjectIndex = binding->value.objectIndex;
+ const QV4::CompiledData::Object *target = qmlUnit->objectAt(targetObjectIndex);
+
+ ListModel *subModel = 0;
+ if (outterElementIndex == -1) {
+ subModel = model;
+ } else {
+ const ListLayout::Role &role = model->getOrCreateListRole(elementName);
+ if (role.type == ListLayout::Role::List) {
+ subModel = model->getListProperty(outterElementIndex, role);
+ if (subModel == 0) {
+ subModel = new ListModel(role.subLayout, 0, -1);
+ QVariant vModel = QVariant::fromValue(subModel);
+ model->setOrCreateProperty(outterElementIndex, elementName, vModel);
+ }
+ }
}
- {
- ListInstruction li;
- li.type = ListInstruction::Pop;
- li.dataIdx = -1;
- instr << li;
+ int elementIndex = subModel ? subModel->appendElement() : -1;
+
+ const QV4::CompiledData::Binding *subBinding = target->bindingTable();
+ for (quint32 i = 0; i < target->nBindings; ++i, ++subBinding) {
+ roleSet |= applyProperty(qmlUnit, subBinding, subModel, elementIndex);
}
} else {
- int ref = data.count();
+ QVariant value;
- QByteArray d;
-
- if (binding->type == QV4::CompiledData::Binding::Type_String) {
- d += char(String);
- d += binding->valueAsString(&qmlUnit->header).toUtf8();
+ if (binding->evaluatesToString()) {
+ value = binding->valueAsString(&qmlUnit->header);
} else if (binding->type == QV4::CompiledData::Binding::Type_Number) {
- d += char(Number);
- d += QByteArray::number(binding->valueAsNumber(),'g',20);
+ value = binding->valueAsNumber();
} else if (binding->type == QV4::CompiledData::Binding::Type_Boolean) {
- d += char(Boolean);
- d += char(binding->valueAsBoolean());
- } else if (binding->type == QV4::CompiledData::Binding::Type_Translation
- || binding->type == QV4::CompiledData::Binding::Type_TranslationById) {
- error(binding, QQmlListModel::tr("ListElement: cannot use script for property value"));
- return false;
+ value = binding->valueAsBoolean();
} else if (binding->type == QV4::CompiledData::Binding::Type_Script) {
QString scriptStr = binding->valueAsScriptString(&qmlUnit->header);
if (definesEmptyList(scriptStr)) {
- d[0] = char(Invalid); // marks empty list
+ const ListLayout::Role &role = model->getOrCreateListRole(elementName);
+ ListModel *emptyModel = new ListModel(role.subLayout, 0, -1);
+ value = QVariant::fromValue(emptyModel);
} else {
QByteArray script = scriptStr.toUtf8();
bool ok;
- int v = evaluateEnum(script, &ok);
- if (!ok) {
- error(binding, QQmlListModel::tr("ListElement: cannot use script for property value"));
- return false;
- } else {
- d[0] = char(Number);
- d += QByteArray::number(v);
- }
+ value = evaluateEnum(script, &ok);
}
} else {
Q_UNREACHABLE();
}
- d.append('\0');
- data.append(d);
-
- ListInstruction li;
- li.type = ListInstruction::Value;
- li.dataIdx = ref;
- instr << li;
+ model->setOrCreateProperty(outterElementIndex, elementName, value);
+ roleSet = true;
}
-
- return true;
+ return roleSet;
}
-QByteArray QQmlListModelParser::compile(const QV4::CompiledData::QmlUnit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
+void QQmlListModelParser::verifyBindings(const QV4::CompiledData::QmlUnit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
{
- QList<ListInstruction> instr;
- QByteArray data;
listElementTypeName = QString(); // unknown
foreach (const QV4::CompiledData::Binding *binding, bindings) {
QString propName = qmlUnit->header.stringAt(binding->propertyNameIndex);
if (!propName.isEmpty()) { // isn't default property
error(binding, QQmlListModel::tr("ListModel: undefined property '%1'").arg(propName));
- return QByteArray();
+ return;
}
- if (!compileProperty(qmlUnit, binding, instr, data))
- return QByteArray();
+ if (!verifyProperty(qmlUnit, binding))
+ return;
}
-
- int size = sizeof(ListModelData) +
- instr.count() * sizeof(ListInstruction) +
- data.count();
-
- QByteArray rv;
- rv.resize(size);
-
- ListModelData *lmd = (ListModelData *)rv.data();
- lmd->dataOffset = sizeof(ListModelData) +
- instr.count() * sizeof(ListInstruction);
- lmd->instrCount = instr.count();
- for (int ii = 0; ii < instr.count(); ++ii)
- lmd->instructions()[ii] = instr.at(ii);
- ::memcpy(rv.data() + lmd->dataOffset, data.constData(), data.count());
-
- return rv;
}
-void QQmlListModelParser::setCustomData(QObject *obj, const QByteArray &d, QQmlCompiledData *)
+void QQmlListModelParser::applyBindings(QObject *obj, QQmlCompiledData *cdata, const QList<const QV4::CompiledData::Binding *> &bindings)
{
QQmlListModel *rv = static_cast<QQmlListModel *>(obj);
QV8Engine *engine = QQmlEnginePrivate::getV8Engine(qmlEngine(rv));
rv->m_engine = engine;
- const ListModelData *lmd = (const ListModelData *)d.constData();
- const char *data = ((const char *)lmd) + lmd->dataOffset;
+ const QV4::CompiledData::QmlUnit *qmlUnit = cdata->qmlUnit;
bool setRoles = false;
- QStack<DataStackElement> stack;
-
- for (int ii = 0; ii < lmd->instrCount; ++ii) {
- const ListInstruction &instr = lmd->instructions()[ii];
-
- switch(instr.type) {
- case ListInstruction::Push:
- {
- Q_ASSERT(!rv->m_dynamicRoles);
-
- ListModel *subModel = 0;
-
- if (stack.count() == 0) {
- subModel = rv->m_listModel;
- } else {
- const DataStackElement &e0 = stack.at(stack.size() - 1);
- DataStackElement &e1 = stack[stack.size() - 2];
-
- const ListLayout::Role &role = e1.model->getOrCreateListRole(e0.name);
- if (role.type == ListLayout::Role::List) {
- subModel = e1.model->getListProperty(e1.elementIndex, role);
-
- if (subModel == 0) {
- subModel = new ListModel(role.subLayout, 0, -1);
- QVariant vModel = QVariant::fromValue(subModel);
- e1.model->setOrCreateProperty(e1.elementIndex, e0.name, vModel);
- }
- }
- }
-
- DataStackElement e;
- e.model = subModel;
- e.elementIndex = subModel ? subModel->appendElement() : -1;
- stack.push(e);
- }
- break;
-
- case ListInstruction::Pop:
- stack.pop();
- break;
-
- case ListInstruction::Value:
- {
- const DataStackElement &e0 = stack.at(stack.size() - 1);
- DataStackElement &e1 = stack[stack.size() - 2];
-
- QString name = e0.name;
- QVariant value;
-
- switch (PropertyType(data[instr.dataIdx])) {
- case Invalid:
- {
- const ListLayout::Role &role = e1.model->getOrCreateListRole(e0.name);
- ListModel *emptyModel = new ListModel(role.subLayout, 0, -1);
- value = QVariant::fromValue(emptyModel);
- }
- break;
- case Boolean:
- value = bool(data[1 + instr.dataIdx]);
- break;
- case Number:
- value = QByteArray(data + 1 + instr.dataIdx).toDouble();
- break;
- case String:
- value = QString::fromUtf8(data + 1 + instr.dataIdx);
- break;
- default:
- Q_ASSERT("Format error in ListInstruction");
- }
-
- e1.model->setOrCreateProperty(e1.elementIndex, name, value);
- setRoles = true;
- }
- break;
-
- case ListInstruction::Set:
- {
- DataStackElement e;
- e.name = QString::fromUtf8(data + instr.dataIdx);
- stack.push(e);
- }
- break;
- }
+ foreach (const QV4::CompiledData::Binding *binding, bindings) {
+ if (binding->type != QV4::CompiledData::Binding::Type_Object)
+ continue;
+ setRoles |= applyProperty(qmlUnit, binding, rv->m_listModel, /*outter element index*/-1);
}
if (setRoles == false)
diff --git a/src/qml/types/qqmllistmodel_p.h b/src/qml/types/qqmllistmodel_p.h
index 3d84e14698..8c12173425 100644
--- a/src/qml/types/qqmllistmodel_p.h
+++ b/src/qml/types/qqmllistmodel_p.h
@@ -171,41 +171,20 @@ public:
QQmlListModelParser() : QQmlCustomParser(QQmlCustomParser::AcceptsSignalHandlers) {}
- QByteArray compile(const QV4::CompiledData::QmlUnit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &bindings);
- void setCustomData(QObject *, const QByteArray &, QQmlCompiledData *);
+
+ virtual void verifyBindings(const QV4::CompiledData::QmlUnit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &bindings);
+ virtual void applyBindings(QObject *obj, QQmlCompiledData *cdata, const QList<const QV4::CompiledData::Binding *> &bindings);
private:
- struct ListInstruction
- {
- enum { Push, Pop, Value, Set } type;
- int dataIdx;
- };
- struct ListModelData
- {
- int dataOffset;
- int instrCount;
- ListInstruction *instructions() const;
- };
- bool compileProperty(const QV4::CompiledData::QmlUnit *qmlUnit, const QV4::CompiledData::Binding *binding, QList<ListInstruction> &instr, QByteArray &data);
+ bool verifyProperty(const QV4::CompiledData::QmlUnit *qmlUnit, const QV4::CompiledData::Binding *binding);
+ // returns true if a role was set
+ bool applyProperty(const QV4::CompiledData::QmlUnit *qmlUnit, const QV4::CompiledData::Binding *binding, ListModel *model, int outterElementIndex);
bool definesEmptyList(const QString &);
QString listElementTypeName;
-
- struct DataStackElement
- {
- DataStackElement() : model(0), elementIndex(0) {}
-
- QString name;
- ListModel *model;
- int elementIndex;
- };
-
- friend class QTypeInfo<QQmlListModelParser::ListInstruction>;
};
-Q_DECLARE_TYPEINFO(QQmlListModelParser::ListInstruction, Q_PRIMITIVE_TYPE);
-
QT_END_NAMESPACE
QML_DECLARE_TYPE(QQmlListModel)
diff --git a/src/qml/types/qqmllistmodel_p_p.h b/src/qml/types/qqmllistmodel_p_p.h
index 924d89c52d..a27b8026d7 100644
--- a/src/qml/types/qqmllistmodel_p_p.h
+++ b/src/qml/types/qqmllistmodel_p_p.h
@@ -209,12 +209,12 @@ public:
};
const Role *getRoleOrCreate(const QString &key, const QVariant &data);
- const Role &getRoleOrCreate(const QV4::StringRef key, Role::DataType type);
+ const Role &getRoleOrCreate(QV4::String *key, Role::DataType type);
const Role &getRoleOrCreate(const QString &key, Role::DataType type);
const Role &getExistingRole(int index) { return *roles.at(index); }
const Role *getExistingRole(const QString &key);
- const Role *getExistingRole(const QV4::StringRef key);
+ const Role *getExistingRole(QV4::String *key);
int roleCount() const { return roles.count(); }
@@ -260,7 +260,7 @@ private:
int setBoolProperty(const ListLayout::Role &role, bool b);
int setListProperty(const ListLayout::Role &role, ListModel *m);
int setQObjectProperty(const ListLayout::Role &role, QObject *o);
- int setVariantMapProperty(const ListLayout::Role &role, QV4::ObjectRef o, QV8Engine *eng);
+ int setVariantMapProperty(const ListLayout::Role &role, QV4::Object *o, QV8Engine *eng);
int setVariantMapProperty(const ListLayout::Role &role, QVariantMap *m);
int setDateTimeProperty(const ListLayout::Role &role, const QDateTime &dt);
@@ -269,7 +269,7 @@ private:
void setBoolPropertyFast(const ListLayout::Role &role, bool b);
void setQObjectPropertyFast(const ListLayout::Role &role, QObject *o);
void setListPropertyFast(const ListLayout::Role &role, ListModel *m);
- void setVariantMapFast(const ListLayout::Role &role, QV4::ObjectRef o, QV8Engine *eng);
+ void setVariantMapFast(const ListLayout::Role &role, QV4::Object *o, QV8Engine *eng);
void setDateTimePropertyFast(const ListLayout::Role &role, const QDateTime &dt);
void clearProperty(const ListLayout::Role &role);
@@ -333,11 +333,11 @@ public:
return elements.count();
}
- void set(int elementIndex, QV4::ObjectRef object, QVector<int> *roles, QV8Engine *eng);
- void set(int elementIndex, QV4::ObjectRef object, QV8Engine *eng);
+ void set(int elementIndex, QV4::Object *object, QVector<int> *roles, QV8Engine *eng);
+ void set(int elementIndex, QV4::Object *object, QV8Engine *eng);
- int append(QV4::ObjectRef object, QV8Engine *eng);
- void insert(int elementIndex, QV4::ObjectRef object, QV8Engine *eng);
+ int append(QV4::Object *object, QV8Engine *eng);
+ void insert(int elementIndex, QV4::Object *object, QV8Engine *eng);
void clear();
void remove(int index, int count);
diff --git a/src/qml/types/qquickworkerscript.cpp b/src/qml/types/qquickworkerscript.cpp
index 4e842c5133..a9f748cde1 100644
--- a/src/qml/types/qquickworkerscript.cpp
+++ b/src/qml/types/qquickworkerscript.cpp
@@ -235,7 +235,7 @@ void QQuickWorkerScriptEnginePrivate::WorkerEngine::init()
QV4::Scoped<QV4::FunctionObject> createsendconstructor(scope, createsendscript.run());
Q_ASSERT(!scope.engine->hasException);
QV4::ScopedString name(scope, m_v4Engine->newString(QStringLiteral("sendMessage")));
- QV4::ScopedValue function(scope, m_v4Engine->newBuiltinFunction(m_v4Engine->rootContext, name,
+ QV4::ScopedValue function(scope, QV4::BuiltinFunction::create(m_v4Engine->rootContext, name.getPointer(),
QQuickWorkerScriptEnginePrivate::method_sendMessage));
QV4::ScopedCallData callData(scope, 1);
callData->args[0] = function;
@@ -283,12 +283,12 @@ QQuickWorkerScriptEnginePrivate::QQuickWorkerScriptEnginePrivate(QQmlEngine *eng
QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::method_sendMessage(QV4::CallContext *ctx)
{
- WorkerEngine *engine = (WorkerEngine*)ctx->engine->v8Engine;
+ WorkerEngine *engine = (WorkerEngine*)ctx->engine()->v8Engine;
- int id = ctx->callData->argc > 1 ? ctx->callData->args[1].toInt32() : 0;
+ int id = ctx->d()->callData->argc > 1 ? ctx->d()->callData->args[1].toInt32() : 0;
QV4::Scope scope(ctx);
- QV4::ScopedValue v(scope, ctx->callData->argument(2));
+ QV4::ScopedValue v(scope, ctx->d()->callData->argument(2));
QByteArray data = QV4::Serialize::serialize(v, engine);
QMutexLocker locker(&engine->p->m_lock);
@@ -315,9 +315,9 @@ QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::getWorker(WorkerScript *scri
w->setReadOnly(false);
QV4::Scoped<QV4::Object> api(scope, v4->newObject());
- api->put(QV4::ScopedString(scope, v4->newString(QStringLiteral("sendMessage"))), QV4::ScopedValue(scope, workerEngine->sendFunction(script->id)));
+ api->put(QV4::ScopedString(scope, v4->newString(QStringLiteral("sendMessage"))).getPointer(), QV4::ScopedValue(scope, workerEngine->sendFunction(script->id)));
- w->QV4::Object::put(QV4::ScopedString(scope, v4->newString(QStringLiteral("WorkerScript"))), api);
+ w->QV4::Object::put(QV4::ScopedString(scope, v4->newString(QStringLiteral("WorkerScript"))).getPointer(), api);
w->setReadOnly(true);
}
diff --git a/src/qml/util/qqmladaptormodel.cpp b/src/qml/util/qqmladaptormodel.cpp
index c1c8bfa81d..6349c6fa31 100644
--- a/src/qml/util/qqmladaptormodel.cpp
+++ b/src/qml/util/qqmladaptormodel.cpp
@@ -66,11 +66,11 @@ V8_DEFINE_EXTENSION(QQmlAdaptorModelEngineData, engineData)
static QV4::ReturnedValue get_index(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
- QV4::Scoped<QQmlDelegateModelItemObject> o(scope, ctx->callData->thisObject.as<QQmlDelegateModelItemObject>());
+ QV4::Scoped<QQmlDelegateModelItemObject> o(scope, ctx->d()->callData->thisObject.as<QQmlDelegateModelItemObject>());
if (!o)
return ctx->throwTypeError(QStringLiteral("Not a valid VisualData object"));
- return QV4::Encode(o->item->index);
+ return QV4::Encode(o->d()->item->index);
}
template <typename T, typename M> static void setModelDataType(QMetaObjectBuilder *builder, M *metaType)
@@ -198,14 +198,14 @@ public:
static QV4::ReturnedValue get_hasModelChildren(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
- QV4::Scoped<QQmlDelegateModelItemObject> o(scope, ctx->callData->thisObject.as<QQmlDelegateModelItemObject>());
+ QV4::Scoped<QQmlDelegateModelItemObject> o(scope, ctx->d()->callData->thisObject.as<QQmlDelegateModelItemObject>());
if (!o)
return ctx->throwTypeError(QStringLiteral("Not a valid VisualData object"));
- const QQmlAdaptorModel *const model = static_cast<QQmlDMCachedModelData *>(o->item)->type->model;
- if (o->item->index >= 0 && *model) {
+ const QQmlAdaptorModel *const model = static_cast<QQmlDMCachedModelData *>(o->d()->item)->type->model;
+ if (o->d()->item->index >= 0 && *model) {
const QAbstractItemModel * const aim = model->aim();
- return QV4::Encode(aim->hasChildren(aim->index(o->item->index, 0, model->rootIndex)));
+ return QV4::Encode(aim->hasChildren(aim->index(o->d()->item->index, 0, model->rootIndex)));
} else {
return QV4::Encode(false);
}
@@ -227,9 +227,11 @@ public:
const QByteArray &propertyName = it.key();
QV4::ScopedString name(scope, v4->newString(QString::fromUtf8(propertyName)));
- p->setGetter(new (v4->memoryManager) QV4::IndexedBuiltinFunction(v4->rootContext, propertyId, QQmlDMCachedModelData::get_property));
- p->setSetter(new (v4->memoryManager) QV4::IndexedBuiltinFunction(v4->rootContext, propertyId, QQmlDMCachedModelData::set_property));
- proto->insertMember(name, p, QV4::Attr_Accessor|QV4::Attr_NotEnumerable|QV4::Attr_NotConfigurable);
+ QV4::ScopedFunctionObject g(scope, v4->memoryManager->alloc<QV4::IndexedBuiltinFunction>(v4->rootContext, propertyId, QQmlDMCachedModelData::get_property));
+ QV4::ScopedFunctionObject s(scope, v4->memoryManager->alloc<QV4::IndexedBuiltinFunction>(v4->rootContext, propertyId, QQmlDMCachedModelData::set_property));
+ p->setGetter(g);
+ p->setSetter(s);
+ proto->insertMember(name.getPointer(), p, QV4::Attr_Accessor|QV4::Attr_NotEnumerable|QV4::Attr_NotConfigurable);
}
prototype = proto;
}
@@ -343,18 +345,18 @@ bool QQmlDMCachedModelData::resolveIndex(const QQmlAdaptorModel &, int idx)
QV4::ReturnedValue QQmlDMCachedModelData::get_property(QV4::CallContext *ctx, uint propertyId)
{
QV4::Scope scope(ctx);
- QV4::Scoped<QQmlDelegateModelItemObject> o(scope, ctx->callData->thisObject.as<QQmlDelegateModelItemObject>());
+ QV4::Scoped<QQmlDelegateModelItemObject> o(scope, ctx->d()->callData->thisObject.as<QQmlDelegateModelItemObject>());
if (!o)
return ctx->throwTypeError(QStringLiteral("Not a valid VisualData object"));
- QQmlDMCachedModelData *modelData = static_cast<QQmlDMCachedModelData *>(o->item);
- if (o->item->index == -1) {
+ QQmlDMCachedModelData *modelData = static_cast<QQmlDMCachedModelData *>(o->d()->item);
+ if (o->d()->item->index == -1) {
if (!modelData->cachedData.isEmpty()) {
- return ctx->engine->v8Engine->fromVariant(
+ return ctx->d()->engine->v8Engine->fromVariant(
modelData->cachedData.at(modelData->type->hasModelData ? 0 : propertyId));
}
} else if (*modelData->type->model) {
- return ctx->engine->v8Engine->fromVariant(
+ return ctx->d()->engine->v8Engine->fromVariant(
modelData->value(modelData->type->propertyRoles.at(propertyId)));
}
return QV4::Encode::undefined();
@@ -363,22 +365,22 @@ QV4::ReturnedValue QQmlDMCachedModelData::get_property(QV4::CallContext *ctx, ui
QV4::ReturnedValue QQmlDMCachedModelData::set_property(QV4::CallContext *ctx, uint propertyId)
{
QV4::Scope scope(ctx);
- QV4::Scoped<QQmlDelegateModelItemObject> o(scope, ctx->callData->thisObject.as<QQmlDelegateModelItemObject>());
+ QV4::Scoped<QQmlDelegateModelItemObject> o(scope, ctx->d()->callData->thisObject.as<QQmlDelegateModelItemObject>());
if (!o)
return ctx->throwTypeError(QStringLiteral("Not a valid VisualData object"));
- if (!ctx->callData->argc)
+ if (!ctx->d()->callData->argc)
return ctx->throwTypeError();
- if (o->item->index == -1) {
- QQmlDMCachedModelData *modelData = static_cast<QQmlDMCachedModelData *>(o->item);
+ if (o->d()->item->index == -1) {
+ QQmlDMCachedModelData *modelData = static_cast<QQmlDMCachedModelData *>(o->d()->item);
if (!modelData->cachedData.isEmpty()) {
if (modelData->cachedData.count() > 1) {
- modelData->cachedData[propertyId] = ctx->engine->v8Engine->toVariant(ctx->callData->args[0], QVariant::Invalid);
- QMetaObject::activate(o->item, o->item->metaObject(), propertyId, 0);
+ modelData->cachedData[propertyId] = scope.engine->v8Engine->toVariant(ctx->d()->callData->args[0], QVariant::Invalid);
+ QMetaObject::activate(o->d()->item, o->d()->item->metaObject(), propertyId, 0);
} else if (modelData->cachedData.count() == 1) {
- modelData->cachedData[0] = ctx->engine->v8Engine->toVariant(ctx->callData->args[0], QVariant::Invalid);
- QMetaObject::activate(o->item, o->item->metaObject(), 0, 0);
- QMetaObject::activate(o->item, o->item->metaObject(), 1, 0);
+ modelData->cachedData[0] = scope.engine->v8Engine->toVariant(ctx->d()->callData->args[0], QVariant::Invalid);
+ QMetaObject::activate(o->d()->item, o->d()->item->metaObject(), 0, 0);
+ QMetaObject::activate(o->d()->item, o->d()->item->metaObject(), 1, 0);
}
}
}
@@ -431,7 +433,7 @@ public:
}
QV4::Scope scope(v4);
QV4::ScopedObject proto(scope, type->prototype.value());
- QV4::ScopedObject o(scope, new (proto->engine()->memoryManager) QQmlDelegateModelItemObject(proto->engine(), this));
+ QV4::ScopedObject o(scope, proto->engine()->memoryManager->alloc<QQmlDelegateModelItemObject>(proto->engine(), this));
o->setPrototype(proto.getPointer());
++scriptRef;
return o.asReturnedValue();
@@ -585,23 +587,23 @@ public:
static QV4::ReturnedValue get_modelData(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
- QV4::Scoped<QQmlDelegateModelItemObject> o(scope, ctx->callData->thisObject.as<QQmlDelegateModelItemObject>());
+ QV4::Scoped<QQmlDelegateModelItemObject> o(scope, ctx->d()->callData->thisObject.as<QQmlDelegateModelItemObject>());
if (!o)
return ctx->throwTypeError(QStringLiteral("Not a valid VisualData object"));
- return ctx->engine->v8Engine->fromVariant(static_cast<QQmlDMListAccessorData *>(o->item)->cachedData);
+ return scope.engine->v8Engine->fromVariant(static_cast<QQmlDMListAccessorData *>(o->d()->item)->cachedData);
}
static QV4::ReturnedValue set_modelData(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
- QV4::Scoped<QQmlDelegateModelItemObject> o(scope, ctx->callData->thisObject.as<QQmlDelegateModelItemObject>());
+ QV4::Scoped<QQmlDelegateModelItemObject> o(scope, ctx->d()->callData->thisObject.as<QQmlDelegateModelItemObject>());
if (!o)
return ctx->throwTypeError(QStringLiteral("Not a valid VisualData object"));
- if (!ctx->callData->argc)
+ if (!ctx->d()->callData->argc)
return ctx->throwTypeError();
- static_cast<QQmlDMListAccessorData *>(o->item)->setModelData(ctx->engine->v8Engine->toVariant(ctx->callData->args[0], QVariant::Invalid));
+ static_cast<QQmlDMListAccessorData *>(o->d()->item)->setModelData(scope.engine->v8Engine->toVariant(ctx->d()->callData->args[0], QVariant::Invalid));
return QV4::Encode::undefined();
}
@@ -609,7 +611,7 @@ public:
{
QQmlAdaptorModelEngineData *data = engineData(v4->v8Engine);
QV4::Scope scope(v4);
- QV4::ScopedObject o(scope, new (v4->memoryManager) QQmlDelegateModelItemObject(v4, this));
+ QV4::ScopedObject o(scope, v4->memoryManager->alloc<QQmlDelegateModelItemObject>(v4, this));
QV4::ScopedObject p(scope, data->listItemProto.value());
o->setPrototype(p.getPointer());
++scriptRef;
diff --git a/src/qml/util/qqmlchangeset.cpp b/src/qml/util/qqmlchangeset.cpp
index 831cb063a5..4e5e619d39 100644
--- a/src/qml/util/qqmlchangeset.cpp
+++ b/src/qml/util/qqmlchangeset.cpp
@@ -111,7 +111,7 @@ QQmlChangeSet &QQmlChangeSet::operator =(const QQmlChangeSet &changeSet)
void QQmlChangeSet::insert(int index, int count)
{
- insert(QVector<Insert>() << Insert(index, count));
+ insert(QVector<Change>() << Change(index, count));
}
/*!
@@ -120,8 +120,8 @@ void QQmlChangeSet::insert(int index, int count)
void QQmlChangeSet::remove(int index, int count)
{
- QVector<Remove> removes;
- removes.append(Remove(index, count));
+ QVector<Change> removes;
+ removes.append(Change(index, count));
remove(&removes, 0);
}
@@ -134,10 +134,10 @@ void QQmlChangeSet::remove(int index, int count)
void QQmlChangeSet::move(int from, int to, int count, int moveId)
{
- QVector<Remove> removes;
- removes.append(Remove(from, count, moveId));
- QVector<Insert> inserts;
- inserts.append(Insert(to, count, moveId));
+ QVector<Change> removes;
+ removes.append(Change(from, count, moveId));
+ QVector<Change> inserts;
+ inserts.append(Change(to, count, moveId));
remove(&removes, &inserts);
insert(inserts);
}
@@ -159,8 +159,8 @@ void QQmlChangeSet::change(int index, int count)
void QQmlChangeSet::apply(const QQmlChangeSet &changeSet)
{
- QVector<Remove> r = changeSet.m_removes;
- QVector<Insert> i = changeSet.m_inserts;
+ QVector<Change> r = changeSet.m_removes;
+ QVector<Change> i = changeSet.m_inserts;
QVector<Change> c = changeSet.m_changes;
remove(&r, &i);
insert(i);
@@ -174,19 +174,19 @@ void QQmlChangeSet::apply(const QQmlChangeSet &changeSet)
corresponding intersection in the optional \a inserts list.
*/
-void QQmlChangeSet::remove(const QVector<Remove> &removes, QVector<Insert> *inserts)
+void QQmlChangeSet::remove(const QVector<Change> &removes, QVector<Change> *inserts)
{
- QVector<Remove> r = removes;
+ QVector<Change> r = removes;
remove(&r, inserts);
}
-void QQmlChangeSet::remove(QVector<Remove> *removes, QVector<Insert> *inserts)
+void QQmlChangeSet::remove(QVector<Change> *removes, QVector<Change> *inserts)
{
int removeCount = 0;
int insertCount = 0;
- QVector<Insert>::iterator insert = m_inserts.begin();
+ QVector<Change>::iterator insert = m_inserts.begin();
QVector<Change>::iterator change = m_changes.begin();
- QVector<Remove>::iterator rit = removes->begin();
+ QVector<Change>::iterator rit = removes->begin();
for (; rit != removes->end(); ++rit) {
int index = rit->index + removeCount;
int count = rit->count;
@@ -223,7 +223,7 @@ void QQmlChangeSet::remove(QVector<Remove> *removes, QVector<Insert> *inserts)
// a new delta for that portion and subtract the size of that delta from the current
// one.
if (offset < 0 && rit->moveId != -1) {
- rit = removes->insert(rit, Remove(
+ rit = removes->insert(rit, Change(
rit->index, -offset, rit->moveId, rit->offset));
++rit;
rit->count -= -offset;
@@ -233,7 +233,7 @@ void QQmlChangeSet::remove(QVector<Remove> *removes, QVector<Insert> *inserts)
removeCount += -offset;
offset = 0;
} else if (offset > 0 && insert->moveId != -1) {
- insert = m_inserts.insert(insert, Insert(
+ insert = m_inserts.insert(insert, Change(
insert->index - removeCount, offset, insert->moveId, insert->offset));
++insert;
insert->index += offset;
@@ -246,7 +246,7 @@ void QQmlChangeSet::remove(QVector<Remove> *removes, QVector<Insert> *inserts)
// If the current remove has a move id, find any inserts with the same move id and
// replace the corresponding sections with the insert removed from the change set.
if (rit->moveId != -1 && difference > 0 && inserts) {
- for (QVector<Insert>::iterator iit = inserts->begin(); iit != inserts->end(); ++iit) {
+ for (QVector<Change>::iterator iit = inserts->begin(); iit != inserts->end(); ++iit) {
if (iit->moveId != rit->moveId
|| rit->offset > iit->offset + iit->count
|| iit->offset > rit->offset + difference) {
@@ -256,7 +256,7 @@ void QQmlChangeSet::remove(QVector<Remove> *removes, QVector<Insert> *inserts)
// a new insert for the portion prior to the replacement insert.
const int overlapOffset = rit->offset - iit->offset;
if (overlapOffset > 0) {
- iit = inserts->insert(iit, Insert(
+ iit = inserts->insert(iit, Change(
iit->index, overlapOffset, iit->moveId, iit->offset));
++iit;
iit->index += overlapOffset;
@@ -275,7 +275,7 @@ void QQmlChangeSet::remove(QVector<Remove> *removes, QVector<Insert> *inserts)
const int count
= qMin(iit->offset + iit->count, rit->offset + difference)
- qMax(iit->offset, rit->offset);
- iit = inserts->insert(iit, Insert(
+ iit = inserts->insert(iit, Change(
iit->index,
count,
insert->moveId,
@@ -316,12 +316,12 @@ void QQmlChangeSet::remove(QVector<Remove> *removes, QVector<Insert> *inserts)
insert->index -= removeCount;
removeCount = 0;
- QVector<Remove>::iterator remove = m_removes.begin();
+ QVector<Change>::iterator remove = m_removes.begin();
for (rit = removes->begin(); rit != removes->end(); ++rit) {
if (rit->count == 0)
continue;
// Accumulate consecutive removes into a single delta before attempting to apply.
- for (QVector<Remove>::iterator next = rit + 1; next != removes->end()
+ for (QVector<Change>::iterator next = rit + 1; next != removes->end()
&& next->index == rit->index
&& next->moveId == -1
&& rit->moveId == -1; ++next) {
@@ -336,7 +336,7 @@ void QQmlChangeSet::remove(QVector<Remove> *removes, QVector<Insert> *inserts)
while (remove != m_removes.end() && index + rit->count >= remove->index) {
int count = 0;
const int offset = remove->index - index;
- QVector<Remove>::iterator rend = remove;
+ QVector<Change>::iterator rend = remove;
for (; rend != m_removes.end()
&& rit->moveId == -1
&& rend->moveId == -1
@@ -366,7 +366,7 @@ void QQmlChangeSet::remove(QVector<Remove> *removes, QVector<Insert> *inserts)
// Insert a remove for the portion of the unmergable current remove prior to the
// point of intersection.
if (offset > 0) {
- remove = m_removes.insert(remove, Remove(
+ remove = m_removes.insert(remove, Change(
rit->index, offset, rit->moveId, rit->offset));
++remove;
rit->count -= offset;
@@ -395,19 +395,19 @@ void QQmlChangeSet::remove(QVector<Remove> *removes, QVector<Insert> *inserts)
Applies a list of \a inserts to a change set.
*/
-void QQmlChangeSet::insert(const QVector<Insert> &inserts)
+void QQmlChangeSet::insert(const QVector<Change> &inserts)
{
int insertCount = 0;
- QVector<Insert>::iterator insert = m_inserts.begin();
+ QVector<Change>::iterator insert = m_inserts.begin();
QVector<Change>::iterator change = m_changes.begin();
- for (QVector<Insert>::const_iterator iit = inserts.begin(); iit != inserts.end(); ++iit) {
+ for (QVector<Change>::const_iterator iit = inserts.begin(); iit != inserts.end(); ++iit) {
if (iit->count == 0)
continue;
int index = iit->index - insertCount;
- Insert current = *iit;
+ Change current = *iit;
// Accumulate consecutive inserts into a single delta before attempting to insert.
- for (QVector<Insert>::const_iterator next = iit + 1; next != inserts.end()
+ for (QVector<Change>::const_iterator next = iit + 1; next != inserts.end()
&& next->index == iit->index + iit->count
&& next->moveId == -1
&& iit->moveId == -1; ++next) {
@@ -459,7 +459,7 @@ void QQmlChangeSet::insert(const QVector<Insert> &inserts)
// If either insert has a moveId then split the existing insert and insert the
// current one in the middle.
if (offset > 0) {
- insert = m_inserts.insert(insert, Insert(
+ insert = m_inserts.insert(insert, Change(
insert->index + insertCount, offset, insert->moveId, insert->offset));
++insert;
insert->index += offset;
@@ -487,10 +487,10 @@ void QQmlChangeSet::insert(const QVector<Insert> &inserts)
calling \l remove() followed by \l insert() with the same lists.
*/
-void QQmlChangeSet::move(const QVector<Remove> &removes, const QVector<Insert> &inserts)
+void QQmlChangeSet::move(const QVector<Change> &removes, const QVector<Change> &inserts)
{
- QVector<Remove> r = removes;
- QVector<Insert> i = inserts;
+ QVector<Change> r = removes;
+ QVector<Change> i = inserts;
remove(&r, &i);
insert(i);
}
@@ -507,7 +507,7 @@ void QQmlChangeSet::change(const QVector<Change> &changes)
void QQmlChangeSet::change(QVector<Change> *changes)
{
- QVector<Insert>::iterator insert = m_inserts.begin();
+ QVector<Change>::iterator insert = m_inserts.begin();
QVector<Change>::iterator change = m_changes.begin();
for (QVector<Change>::iterator cit = changes->begin(); cit != changes->end(); ++cit) {
for (; insert != m_inserts.end() && insert->end() < cit->index; ++insert) {}
@@ -560,55 +560,13 @@ void QQmlChangeSet::change(QVector<Change> *changes)
QDebug operator <<(QDebug debug, const QQmlChangeSet &set)
{
debug.nospace() << "QQmlChangeSet(";
- foreach (const QQmlChangeSet::Remove &remove, set.removes()) debug << remove;
- foreach (const QQmlChangeSet::Insert &insert, set.inserts()) debug << insert;
+ foreach (const QQmlChangeSet::Change &remove, set.removes()) debug << remove;
+ foreach (const QQmlChangeSet::Change &insert, set.inserts()) debug << insert;
foreach (const QQmlChangeSet::Change &change, set.changes()) debug << change;
return debug.nospace() << ')';
}
/*!
- Prints a \a remove to the \a debug stream.
-*/
-
-QDebug operator <<(QDebug debug, const QQmlChangeSet::Remove &remove)
-{
- if (remove.moveId == -1) {
- return (debug.nospace()
- << "Remove(" << remove.index
- << ',' << remove.count
- << ')').space();
- } else {
- return (debug.nospace()
- << "Remove(" << remove.index
- << ',' << remove.count
- << ',' << remove.moveId
- << ',' << remove.offset
- << ')').space();
- }
-}
-
-/*!
- Prints an \a insert to the \a debug stream.
-*/
-
-QDebug operator <<(QDebug debug, const QQmlChangeSet::Insert &insert)
-{
- if (insert.moveId == -1) {
- return (debug.nospace()
- << "Insert(" << insert.index
- << ',' << insert.count
- << ')').space();
- } else {
- return (debug.nospace()
- << "Insert(" << insert.index
- << ',' << insert.count
- << ',' << insert.moveId
- << ',' << insert.offset
- << ')').space();
- }
-}
-
-/*!
Prints a \a change to the \a debug stream.
*/
diff --git a/src/qml/util/qqmlchangeset_p.h b/src/qml/util/qqmlchangeset_p.h
index acafbd4eec..e79bc4a832 100644
--- a/src/qml/util/qqmlchangeset_p.h
+++ b/src/qml/util/qqmlchangeset_p.h
@@ -90,29 +90,14 @@ public:
int end() const { return index + count; }
};
-
- struct Insert : public Change
- {
- Insert() {}
- Insert(int index, int count, int moveId = -1, int offset = 0)
- : Change(index, count, moveId, offset) {}
- };
-
- struct Remove : public Change
- {
- Remove() {}
- Remove(int index, int count, int moveId = -1, int offset = 0)
- : Change(index, count, moveId, offset) {}
- };
-
QQmlChangeSet();
QQmlChangeSet(const QQmlChangeSet &changeSet);
~QQmlChangeSet();
QQmlChangeSet &operator =(const QQmlChangeSet &changeSet);
- const QVector<Remove> &removes() const { return m_removes; }
- const QVector<Insert> &inserts() const { return m_inserts; }
+ const QVector<Change> &removes() const { return m_removes; }
+ const QVector<Change> &inserts() const { return m_inserts; }
const QVector<Change> &changes() const { return m_changes; }
void insert(int index, int count);
@@ -120,9 +105,9 @@ public:
void move(int from, int to, int count, int moveId);
void change(int index, int count);
- void insert(const QVector<Insert> &inserts);
- void remove(const QVector<Remove> &removes, QVector<Insert> *inserts = 0);
- void move(const QVector<Remove> &removes, const QVector<Insert> &inserts);
+ void insert(const QVector<Change> &inserts);
+ void remove(const QVector<Change> &removes, QVector<Change> *inserts = 0);
+ void move(const QVector<Change> &removes, const QVector<Change> &inserts);
void change(const QVector<Change> &changes);
void apply(const QQmlChangeSet &changeSet);
@@ -139,26 +124,22 @@ public:
int difference() const { return m_difference; }
private:
- void remove(QVector<Remove> *removes, QVector<Insert> *inserts);
+ void remove(QVector<Change> *removes, QVector<Change> *inserts);
void change(QVector<Change> *changes);
- QVector<Remove> m_removes;
- QVector<Insert> m_inserts;
+ QVector<Change> m_removes;
+ QVector<Change> m_inserts;
QVector<Change> m_changes;
int m_difference;
};
Q_DECLARE_TYPEINFO(QQmlChangeSet::Change, Q_PRIMITIVE_TYPE);
-Q_DECLARE_TYPEINFO(QQmlChangeSet::Remove, Q_PRIMITIVE_TYPE);
-Q_DECLARE_TYPEINFO(QQmlChangeSet::Insert, Q_PRIMITIVE_TYPE);
Q_DECLARE_TYPEINFO(QQmlChangeSet::MoveKey, Q_PRIMITIVE_TYPE);
inline uint qHash(const QQmlChangeSet::MoveKey &key) { return qHash(qMakePair(key.moveId, key.offset)); }
inline bool operator ==(const QQmlChangeSet::MoveKey &l, const QQmlChangeSet::MoveKey &r) {
return l.moveId == r.moveId && l.offset == r.offset; }
-Q_QML_PRIVATE_EXPORT QDebug operator <<(QDebug debug, const QQmlChangeSet::Remove &remove);
-Q_QML_PRIVATE_EXPORT QDebug operator <<(QDebug debug, const QQmlChangeSet::Insert &insert);
Q_QML_PRIVATE_EXPORT QDebug operator <<(QDebug debug, const QQmlChangeSet::Change &change);
Q_QML_PRIVATE_EXPORT QDebug operator <<(QDebug debug, const QQmlChangeSet &change);
diff --git a/src/qml/util/qqmllistcompositor.cpp b/src/qml/util/qqmllistcompositor.cpp
index 830a24e752..64528dafd2 100644
--- a/src/qml/util/qqmllistcompositor.cpp
+++ b/src/qml/util/qqmllistcompositor.cpp
@@ -951,7 +951,7 @@ void QQmlListCompositor::clear()
void QQmlListCompositor::listItemsInserted(
QVector<Insert> *translatedInsertions,
void *list,
- const QVector<QQmlChangeSet::Insert> &insertions,
+ const QVector<QQmlChangeSet::Change> &insertions,
const QVector<MovedFlags> *movedFlags)
{
QT_QML_TRACE_LISTCOMPOSITOR(<< list << insertions)
@@ -966,7 +966,7 @@ void QQmlListCompositor::listItemsInserted(
it.incrementIndexes(it->count);
continue;
}
- foreach (const QQmlChangeSet::Insert &insertion, insertions) {
+ foreach (const QQmlChangeSet::Change &insertion, insertions) {
int offset = insertion.index - it->index;
if ((offset > 0 && offset < it->count)
|| (offset == 0 && it->prepend())
@@ -1064,8 +1064,8 @@ void QQmlListCompositor::listItemsInserted(
QT_QML_TRACE_LISTCOMPOSITOR(<< list << index << count)
Q_ASSERT(count > 0);
- QVector<QQmlChangeSet::Insert> insertions;
- insertions.append(QQmlChangeSet::Insert(index, count));
+ QVector<QQmlChangeSet::Change> insertions;
+ insertions.append(QQmlChangeSet::Change(index, count));
listItemsInserted(translatedInsertions, list, insertions);
}
@@ -1073,8 +1073,8 @@ void QQmlListCompositor::listItemsInserted(
void QQmlListCompositor::listItemsRemoved(
QVector<Remove> *translatedRemovals,
void *list,
- QVector<QQmlChangeSet::Remove> *removals,
- QVector<QQmlChangeSet::Insert> *insertions,
+ QVector<QQmlChangeSet::Change> *removals,
+ QVector<QQmlChangeSet::Change> *insertions,
QVector<MovedFlags> *movedFlags)
{
QT_QML_TRACE_LISTCOMPOSITOR(<< list << *removals)
@@ -1086,7 +1086,7 @@ void QQmlListCompositor::listItemsRemoved(
continue;
}
bool removed = false;
- for (QVector<QQmlChangeSet::Remove>::iterator removal = removals->begin();
+ for (QVector<QQmlChangeSet::Change>::iterator removal = removals->begin();
!removed && removal != removals->end();
++removal) {
int relativeIndex = removal->index - it->index;
@@ -1104,7 +1104,7 @@ void QQmlListCompositor::listItemsRemoved(
}
if (removal->isMove()) {
// If the removal was part of a move find the corresponding insert.
- QVector<QQmlChangeSet::Insert>::iterator insertion = insertions->begin();
+ QVector<QQmlChangeSet::Change>::iterator insertion = insertions->begin();
for (; insertion != insertions->end() && insertion->moveId != removal->moveId;
++insertion) {}
Q_ASSERT(insertion != insertions->end());
@@ -1114,11 +1114,11 @@ void QQmlListCompositor::listItemsRemoved(
// If the remove started before the current range, split it and the
// corresponding insert so we're only working with intersecting part.
int splitMoveId = ++m_moveId;
- removal = removals->insert(removal, QQmlChangeSet::Remove(
+ removal = removals->insert(removal, QQmlChangeSet::Change(
removal->index, -relativeIndex, splitMoveId));
++removal;
removal->count -= -relativeIndex;
- insertion = insertions->insert(insertion, QQmlChangeSet::Insert(
+ insertion = insertions->insert(insertion, QQmlChangeSet::Change(
insertion->index, -relativeIndex, splitMoveId));
++insertion;
insertion->index += -relativeIndex;
@@ -1135,10 +1135,10 @@ void QQmlListCompositor::listItemsRemoved(
if (removeCount < removal->count) {
// If the remove doesn't encompass all of the current range,
// split it and the corresponding insert.
- removal = removals->insert(removal, QQmlChangeSet::Remove(
+ removal = removals->insert(removal, QQmlChangeSet::Change(
removal->index, removeCount, translatedRemoval.moveId));
++removal;
- insertion = insertions->insert(insertion, QQmlChangeSet::Insert(
+ insertion = insertions->insert(insertion, QQmlChangeSet::Change(
insertion->index, removeCount, translatedRemoval.moveId));
++insertion;
@@ -1253,8 +1253,8 @@ void QQmlListCompositor::listItemsRemoved(
QT_QML_TRACE_LISTCOMPOSITOR(<< list << index << count)
Q_ASSERT(count >= 0);
- QVector<QQmlChangeSet::Remove> removals;
- removals.append(QQmlChangeSet::Remove(index, count));
+ QVector<QQmlChangeSet::Change> removals;
+ removals.append(QQmlChangeSet::Change(index, count));
listItemsRemoved(translatedRemovals, list, &removals, 0, 0);
}
@@ -1280,11 +1280,11 @@ void QQmlListCompositor::listItemsMoved(
QT_QML_TRACE_LISTCOMPOSITOR(<< list << from << to << count)
Q_ASSERT(count >= 0);
- QVector<QQmlChangeSet::Remove> removals;
- QVector<QQmlChangeSet::Insert> insertions;
+ QVector<QQmlChangeSet::Change> removals;
+ QVector<QQmlChangeSet::Change> insertions;
QVector<MovedFlags> movedFlags;
- removals.append(QQmlChangeSet::Remove(from, count, 0));
- insertions.append(QQmlChangeSet::Insert(to, count, 0));
+ removals.append(QQmlChangeSet::Change(from, count, 0));
+ insertions.append(QQmlChangeSet::Change(to, count, 0));
listItemsRemoved(translatedRemovals, list, &removals, &insertions, &movedFlags);
listItemsInserted(translatedInsertions, list, insertions, &movedFlags);
@@ -1342,16 +1342,16 @@ void QQmlListCompositor::listItemsChanged(
void QQmlListCompositor::transition(
Group from,
Group to,
- QVector<QQmlChangeSet::Remove> *removes,
- QVector<QQmlChangeSet::Insert> *inserts)
+ QVector<QQmlChangeSet::Change> *removes,
+ QVector<QQmlChangeSet::Change> *inserts)
{
int removeCount = 0;
for (iterator it(m_ranges.next, 0, Default, m_groupCount); *it != &m_ranges; *it = it->next) {
if (it == from && it != to) {
- removes->append(QQmlChangeSet::Remove(it.index[from]- removeCount, it->count));
+ removes->append(QQmlChangeSet::Change(it.index[from]- removeCount, it->count));
removeCount += it->count;
} else if (it != from && it == to) {
- inserts->append(QQmlChangeSet::Insert(it.index[to], it->count));
+ inserts->append(QQmlChangeSet::Change(it.index[to], it->count));
}
it.incrementIndexes(it->count);
}
diff --git a/src/qml/util/qqmllistcompositor_p.h b/src/qml/util/qqmllistcompositor_p.h
index 5d87051582..c26b62a38c 100644
--- a/src/qml/util/qqmllistcompositor_p.h
+++ b/src/qml/util/qqmllistcompositor_p.h
@@ -263,8 +263,8 @@ public:
void transition(
Group from,
Group to,
- QVector<QQmlChangeSet::Remove> *removes,
- QVector<QQmlChangeSet::Insert> *inserts);
+ QVector<QQmlChangeSet::Change> *removes,
+ QVector<QQmlChangeSet::Change> *inserts);
private:
Range m_ranges;
@@ -290,13 +290,13 @@ private:
void listItemsRemoved(
QVector<Remove> *translatedRemovals,
void *list,
- QVector<QQmlChangeSet::Remove> *removals,
- QVector<QQmlChangeSet::Insert> *insertions = 0,
+ QVector<QQmlChangeSet::Change> *removals,
+ QVector<QQmlChangeSet::Change> *insertions = 0,
QVector<MovedFlags> *movedFlags = 0);
void listItemsInserted(
QVector<Insert> *translatedInsertions,
void *list,
- const QVector<QQmlChangeSet::Insert> &insertions,
+ const QVector<QQmlChangeSet::Change> &insertions,
const QVector<MovedFlags> *movedFlags = 0);
void listItemsChanged(
QVector<Change> *translatedChanges,