Merge remote-tracking branch 'origin/5.9' into dev
Conflicts: src/qml/jit/qv4assembler.cpp src/qml/jit/qv4assembler_p.h src/qml/jit/qv4isel_masm.cpp src/qml/jsruntime/qv4vme_moth.cpp Change-Id: I865d794e550a263387a39ca8d051ebf48b70cbc0
This commit is contained in:
commit
017350a8a9
|
@ -233,7 +233,7 @@ WTF_EXPORT_PRIVATE void WTFInstallReportBacktraceOnCrashHook();
|
|||
#define ASSERT_NOT_REACHED() ((void)0)
|
||||
#define NO_RETURN_DUE_TO_ASSERT
|
||||
|
||||
#if COMPILER(INTEL) && !OS(WINDOWS) || COMPILER(RVCT)
|
||||
#if COMPILER(RVCT)
|
||||
template<typename T>
|
||||
inline void assertUnused(T& x) { (void)x; }
|
||||
#define ASSERT_UNUSED(variable, assertion) (assertUnused(variable))
|
||||
|
|
|
@ -6,9 +6,9 @@ SUBDIRS += \
|
|||
builtins \
|
||||
qtqml \
|
||||
folderlistmodel \
|
||||
localstorage \
|
||||
models
|
||||
|
||||
qtHaveModule(sql): SUBDIRS += localstorage
|
||||
qtConfig(settings): SUBDIRS += settings
|
||||
qtConfig(statemachine): SUBDIRS += statemachine
|
||||
|
||||
|
@ -17,9 +17,9 @@ qtHaveModule(quick) {
|
|||
layouts \
|
||||
qtquick2 \
|
||||
window \
|
||||
sharedimage \
|
||||
testlib
|
||||
|
||||
qtConfig(systemsemaphore): SUBDIRS += sharedimage
|
||||
qtConfig(quick-particles): \
|
||||
SUBDIRS += particles
|
||||
}
|
||||
|
|
|
@ -770,6 +770,8 @@ void QQuickLocalStorage::openDatabaseSync(QQmlV4Function *args)
|
|||
}
|
||||
|
||||
args->setReturnValue(db.asReturnedValue());
|
||||
#else
|
||||
Q_UNUSED(args)
|
||||
#endif // settings
|
||||
}
|
||||
|
||||
|
|
|
@ -668,8 +668,11 @@ void QQuickParticleSystem::setPaused(bool arg) {
|
|||
if (m_animation && m_animation->state() != QAbstractAnimation::Stopped)
|
||||
m_paused ? m_animation->pause() : m_animation->resume();
|
||||
if (!m_paused) {
|
||||
foreach (QQuickParticlePainter *p, m_painters)
|
||||
p->update();
|
||||
foreach (QQuickParticlePainter *p, m_painters) {
|
||||
if (p) {
|
||||
p->update();
|
||||
}
|
||||
}
|
||||
}
|
||||
emit pausedChanged(arg);
|
||||
}
|
||||
|
@ -873,8 +876,11 @@ void QQuickParticleSystem::emittersChanged()
|
|||
if (particleCount > bySysIdx.size())//New datum requests haven't updated it
|
||||
bySysIdx.resize(particleCount);
|
||||
|
||||
foreach (QQuickParticleAffector *a, m_affectors)//Groups may have changed
|
||||
a->m_updateIntSet = true;
|
||||
foreach (QQuickParticleAffector *a, m_affectors) {//Groups may have changed
|
||||
if (a) {
|
||||
a->m_updateIntSet = true;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (QQuickParticlePainter *p, m_painters)
|
||||
loadPainter(p);
|
||||
|
|
|
@ -409,18 +409,7 @@ QQmlEngineDebugServiceImpl::objectData(QObject *object)
|
|||
rv.objectId = QQmlDebugService::idForObject(object);
|
||||
rv.contextId = QQmlDebugService::idForObject(qmlContext(object));
|
||||
rv.parentId = QQmlDebugService::idForObject(object->parent());
|
||||
QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
|
||||
if (type) {
|
||||
QString typeName = type->qmlTypeName();
|
||||
int lastSlash = typeName.lastIndexOf(QLatin1Char('/'));
|
||||
rv.objectType = lastSlash < 0 ? typeName : typeName.mid(lastSlash+1);
|
||||
} else {
|
||||
rv.objectType = QString::fromUtf8(object->metaObject()->className());
|
||||
int marker = rv.objectType.indexOf(QLatin1String("_QMLTYPE_"));
|
||||
if (marker != -1)
|
||||
rv.objectType = rv.objectType.left(marker);
|
||||
}
|
||||
|
||||
rv.objectType = QQmlMetaType::prettyTypeName(object);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,8 @@ HEADERS += \
|
|||
$$PWD/qv4isel_util_p.h \
|
||||
$$PWD/qv4ssa_p.h \
|
||||
$$PWD/qqmlirbuilder_p.h \
|
||||
$$PWD/qqmltypecompiler_p.h
|
||||
$$PWD/qqmltypecompiler_p.h \
|
||||
$$PWD/qv4jssimplifier_p.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/qv4compileddata.cpp \
|
||||
|
@ -19,7 +20,8 @@ SOURCES += \
|
|||
$$PWD/qv4isel_p.cpp \
|
||||
$$PWD/qv4jsir.cpp \
|
||||
$$PWD/qv4ssa.cpp \
|
||||
$$PWD/qqmlirbuilder.cpp
|
||||
$$PWD/qqmlirbuilder.cpp \
|
||||
$$PWD/qv4jssimplifier.cpp
|
||||
|
||||
!qmldevtools_build {
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include <private/qv4ssa_p.h>
|
||||
|
||||
#include "qqmlpropertycachecreator_p.h"
|
||||
#include "qv4jssimplifier_p.h"
|
||||
|
||||
#define COMPILE_EXCEPTION(token, desc) \
|
||||
{ \
|
||||
|
@ -144,7 +145,7 @@ QV4::CompiledData::CompilationUnit *QQmlTypeCompiler::compile()
|
|||
if (!jsCodeGen.generateCodeForComponents())
|
||||
return nullptr;
|
||||
|
||||
QQmlJavaScriptBindingExpressionSimplificationPass pass(this);
|
||||
QQmlJavaScriptBindingExpressionSimplificationPass pass(document->objects, &document->jsModule, &document->jsGenerator);
|
||||
pass.reduceTranslationBindings();
|
||||
|
||||
QV4::ExecutionEngine *v4 = engine->v4engine();
|
||||
|
@ -1429,344 +1430,4 @@ void QQmlDefaultPropertyMerger::mergeDefaultProperties(int objectIndex)
|
|||
}
|
||||
}
|
||||
|
||||
QQmlJavaScriptBindingExpressionSimplificationPass::QQmlJavaScriptBindingExpressionSimplificationPass(QQmlTypeCompiler *typeCompiler)
|
||||
: QQmlCompilePass(typeCompiler)
|
||||
, qmlObjects(*typeCompiler->qmlObjects())
|
||||
, jsModule(typeCompiler->jsIRModule())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void QQmlJavaScriptBindingExpressionSimplificationPass::reduceTranslationBindings()
|
||||
{
|
||||
for (int i = 0; i < qmlObjects.count(); ++i)
|
||||
reduceTranslationBindings(i);
|
||||
if (!irFunctionsToRemove.isEmpty()) {
|
||||
QQmlIRFunctionCleanser cleanser(compiler, irFunctionsToRemove);
|
||||
cleanser.clean();
|
||||
}
|
||||
}
|
||||
|
||||
void QQmlJavaScriptBindingExpressionSimplificationPass::reduceTranslationBindings(int objectIndex)
|
||||
{
|
||||
const QmlIR::Object *obj = qmlObjects.at(objectIndex);
|
||||
|
||||
for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
|
||||
if (binding->type != QV4::CompiledData::Binding::Type_Script)
|
||||
continue;
|
||||
|
||||
const int irFunctionIndex = obj->runtimeFunctionIndices.at(binding->value.compiledScriptIndex);
|
||||
QV4::IR::Function *irFunction = jsModule->functions.at(irFunctionIndex);
|
||||
if (simplifyBinding(irFunction, binding)) {
|
||||
irFunctionsToRemove.append(irFunctionIndex);
|
||||
jsModule->functions[irFunctionIndex] = 0;
|
||||
delete irFunction;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QQmlJavaScriptBindingExpressionSimplificationPass::visitMove(QV4::IR::Move *move)
|
||||
{
|
||||
QV4::IR::Temp *target = move->target->asTemp();
|
||||
if (!target || target->kind != QV4::IR::Temp::VirtualRegister) {
|
||||
discard();
|
||||
return;
|
||||
}
|
||||
|
||||
if (QV4::IR::Call *call = move->source->asCall()) {
|
||||
if (QV4::IR::Name *n = call->base->asName()) {
|
||||
if (n->builtin == QV4::IR::Name::builtin_invalid) {
|
||||
visitFunctionCall(n->id, call->args, target);
|
||||
return;
|
||||
}
|
||||
}
|
||||
discard();
|
||||
return;
|
||||
}
|
||||
|
||||
if (QV4::IR::Name *n = move->source->asName()) {
|
||||
if (n->builtin == QV4::IR::Name::builtin_qml_context
|
||||
|| n->builtin == QV4::IR::Name::builtin_qml_imported_scripts_object) {
|
||||
// these are free of side-effects
|
||||
return;
|
||||
}
|
||||
discard();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!move->source->asTemp() && !move->source->asString() && !move->source->asConst()) {
|
||||
discard();
|
||||
return;
|
||||
}
|
||||
|
||||
_temps[target->index] = move->source;
|
||||
}
|
||||
|
||||
void QQmlJavaScriptBindingExpressionSimplificationPass::visitFunctionCall(const QString *name, QV4::IR::ExprList *args, QV4::IR::Temp *target)
|
||||
{
|
||||
// more than one function call?
|
||||
if (_nameOfFunctionCalled) {
|
||||
discard();
|
||||
return;
|
||||
}
|
||||
|
||||
_nameOfFunctionCalled = name;
|
||||
|
||||
_functionParameters.clear();
|
||||
while (args) {
|
||||
int slot;
|
||||
if (QV4::IR::Temp *param = args->expr->asTemp()) {
|
||||
if (param->kind != QV4::IR::Temp::VirtualRegister) {
|
||||
discard();
|
||||
return;
|
||||
}
|
||||
slot = param->index;
|
||||
_functionParameters.append(slot);
|
||||
} else if (QV4::IR::Const *param = args->expr->asConst()) {
|
||||
slot = --_synthesizedConsts;
|
||||
Q_ASSERT(!_temps.contains(slot));
|
||||
_temps[slot] = param;
|
||||
_functionParameters.append(slot);
|
||||
}
|
||||
args = args->next;
|
||||
}
|
||||
|
||||
_functionCallReturnValue = target->index;
|
||||
}
|
||||
|
||||
void QQmlJavaScriptBindingExpressionSimplificationPass::visitRet(QV4::IR::Ret *ret)
|
||||
{
|
||||
// nothing initialized earlier?
|
||||
if (_returnValueOfBindingExpression != -1) {
|
||||
discard();
|
||||
return;
|
||||
}
|
||||
QV4::IR::Temp *target = ret->expr->asTemp();
|
||||
if (!target || target->kind != QV4::IR::Temp::VirtualRegister) {
|
||||
discard();
|
||||
return;
|
||||
}
|
||||
_returnValueOfBindingExpression = target->index;
|
||||
}
|
||||
|
||||
bool QQmlJavaScriptBindingExpressionSimplificationPass::simplifyBinding(QV4::IR::Function *function, QmlIR::Binding *binding)
|
||||
{
|
||||
_canSimplify = true;
|
||||
_nameOfFunctionCalled = 0;
|
||||
_functionParameters.clear();
|
||||
_functionCallReturnValue = -1;
|
||||
_temps.clear();
|
||||
_returnValueOfBindingExpression = -1;
|
||||
_synthesizedConsts = 0;
|
||||
|
||||
// It would seem unlikely that function with some many basic blocks (after optimization)
|
||||
// consists merely of a qsTr call or a constant value return ;-)
|
||||
if (function->basicBlockCount() > 10)
|
||||
return false;
|
||||
|
||||
for (QV4::IR::BasicBlock *bb : function->basicBlocks()) {
|
||||
for (QV4::IR::Stmt *s : bb->statements()) {
|
||||
visit(s);
|
||||
if (!_canSimplify)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (_returnValueOfBindingExpression == -1)
|
||||
return false;
|
||||
|
||||
if (_nameOfFunctionCalled) {
|
||||
if (_functionCallReturnValue != _returnValueOfBindingExpression)
|
||||
return false;
|
||||
return detectTranslationCallAndConvertBinding(binding);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QQmlJavaScriptBindingExpressionSimplificationPass::detectTranslationCallAndConvertBinding(QmlIR::Binding *binding)
|
||||
{
|
||||
if (*_nameOfFunctionCalled == QLatin1String("qsTr")) {
|
||||
QString translation;
|
||||
QV4::CompiledData::TranslationData translationData;
|
||||
translationData.number = -1;
|
||||
translationData.commentIndex = 0; // empty string
|
||||
|
||||
QVector<int>::ConstIterator param = _functionParameters.constBegin();
|
||||
QVector<int>::ConstIterator end = _functionParameters.constEnd();
|
||||
if (param == end)
|
||||
return false;
|
||||
|
||||
QV4::IR::String *stringParam = _temps[*param]->asString();
|
||||
if (!stringParam)
|
||||
return false;
|
||||
|
||||
translation = *stringParam->value;
|
||||
|
||||
++param;
|
||||
if (param != end) {
|
||||
stringParam = _temps[*param]->asString();
|
||||
if (!stringParam)
|
||||
return false;
|
||||
translationData.commentIndex = compiler->registerString(*stringParam->value);
|
||||
++param;
|
||||
|
||||
if (param != end) {
|
||||
QV4::IR::Const *constParam = _temps[*param]->asConst();
|
||||
if (!constParam || constParam->type != QV4::IR::SInt32Type)
|
||||
return false;
|
||||
|
||||
translationData.number = int(constParam->value);
|
||||
++param;
|
||||
}
|
||||
}
|
||||
|
||||
if (param != end)
|
||||
return false;
|
||||
|
||||
binding->type = QV4::CompiledData::Binding::Type_Translation;
|
||||
binding->stringIndex = compiler->registerString(translation);
|
||||
binding->value.translationData = translationData;
|
||||
return true;
|
||||
} else if (*_nameOfFunctionCalled == QLatin1String("qsTrId")) {
|
||||
QString id;
|
||||
QV4::CompiledData::TranslationData translationData;
|
||||
translationData.number = -1;
|
||||
translationData.commentIndex = 0; // empty string, but unused
|
||||
|
||||
QVector<int>::ConstIterator param = _functionParameters.constBegin();
|
||||
QVector<int>::ConstIterator end = _functionParameters.constEnd();
|
||||
if (param == end)
|
||||
return false;
|
||||
|
||||
QV4::IR::String *stringParam = _temps[*param]->asString();
|
||||
if (!stringParam)
|
||||
return false;
|
||||
|
||||
id = *stringParam->value;
|
||||
|
||||
++param;
|
||||
if (param != end) {
|
||||
QV4::IR::Const *constParam = _temps[*param]->asConst();
|
||||
if (!constParam || constParam->type != QV4::IR::SInt32Type)
|
||||
return false;
|
||||
|
||||
translationData.number = int(constParam->value);
|
||||
++param;
|
||||
}
|
||||
|
||||
if (param != end)
|
||||
return false;
|
||||
|
||||
binding->type = QV4::CompiledData::Binding::Type_TranslationById;
|
||||
binding->stringIndex = compiler->registerString(id);
|
||||
binding->value.translationData = translationData;
|
||||
return true;
|
||||
} else if (*_nameOfFunctionCalled == QLatin1String("QT_TR_NOOP") || *_nameOfFunctionCalled == QLatin1String("QT_TRID_NOOP")) {
|
||||
QVector<int>::ConstIterator param = _functionParameters.constBegin();
|
||||
QVector<int>::ConstIterator end = _functionParameters.constEnd();
|
||||
if (param == end)
|
||||
return false;
|
||||
|
||||
QV4::IR::String *stringParam = _temps[*param]->asString();
|
||||
if (!stringParam)
|
||||
return false;
|
||||
|
||||
++param;
|
||||
if (param != end)
|
||||
return false;
|
||||
|
||||
binding->type = QV4::CompiledData::Binding::Type_String;
|
||||
binding->stringIndex = compiler->registerString(*stringParam->value);
|
||||
return true;
|
||||
} else if (*_nameOfFunctionCalled == QLatin1String("QT_TRANSLATE_NOOP")) {
|
||||
QVector<int>::ConstIterator param = _functionParameters.constBegin();
|
||||
QVector<int>::ConstIterator end = _functionParameters.constEnd();
|
||||
if (param == end)
|
||||
return false;
|
||||
|
||||
++param;
|
||||
if (param == end)
|
||||
return false;
|
||||
|
||||
QV4::IR::String *stringParam = _temps[*param]->asString();
|
||||
if (!stringParam)
|
||||
return false;
|
||||
|
||||
++param;
|
||||
if (param != end)
|
||||
return false;
|
||||
|
||||
binding->type = QV4::CompiledData::Binding::Type_String;
|
||||
binding->stringIndex = compiler->registerString(*stringParam->value);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QQmlIRFunctionCleanser::QQmlIRFunctionCleanser(QQmlTypeCompiler *typeCompiler, const QVector<int> &functionsToRemove)
|
||||
: QQmlCompilePass(typeCompiler)
|
||||
, module(typeCompiler->jsIRModule())
|
||||
, functionsToRemove(functionsToRemove)
|
||||
{
|
||||
}
|
||||
|
||||
void QQmlIRFunctionCleanser::clean()
|
||||
{
|
||||
QVector<QV4::IR::Function*> newFunctions;
|
||||
newFunctions.reserve(module->functions.count() - functionsToRemove.count());
|
||||
|
||||
newFunctionIndices.resize(module->functions.count());
|
||||
|
||||
for (int i = 0; i < module->functions.count(); ++i) {
|
||||
QV4::IR::Function *f = module->functions.at(i);
|
||||
Q_ASSERT(f || functionsToRemove.contains(i));
|
||||
if (f) {
|
||||
newFunctionIndices[i] = newFunctions.count();
|
||||
newFunctions << f;
|
||||
}
|
||||
}
|
||||
|
||||
module->functions = newFunctions;
|
||||
|
||||
for (QV4::IR::Function *function : qAsConst(module->functions)) {
|
||||
for (QV4::IR::BasicBlock *block : function->basicBlocks()) {
|
||||
for (QV4::IR::Stmt *s : block->statements()) {
|
||||
visit(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (QmlIR::Object *obj : qAsConst(*compiler->qmlObjects())) {
|
||||
for (int i = 0; i < obj->runtimeFunctionIndices.count; ++i)
|
||||
obj->runtimeFunctionIndices[i] = newFunctionIndices[obj->runtimeFunctionIndices.at(i)];
|
||||
}
|
||||
}
|
||||
|
||||
void QQmlIRFunctionCleanser::visit(QV4::IR::Stmt *s)
|
||||
{
|
||||
|
||||
switch (s->stmtKind) {
|
||||
case QV4::IR::Stmt::PhiStmt:
|
||||
// nothing to do
|
||||
break;
|
||||
default:
|
||||
STMT_VISIT_ALL_KINDS(s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void QQmlIRFunctionCleanser::visit(QV4::IR::Expr *e)
|
||||
{
|
||||
switch (e->exprKind) {
|
||||
case QV4::IR::Expr::ClosureExpr: {
|
||||
auto closure = e->asClosure();
|
||||
closure->value = newFunctionIndices.at(closure->value);
|
||||
} break;
|
||||
default:
|
||||
EXPR_VISIT_ALL_KINDS(e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
@ -345,86 +345,6 @@ private:
|
|||
const QQmlPropertyCacheVector * const propertyCaches;
|
||||
};
|
||||
|
||||
class QQmlJavaScriptBindingExpressionSimplificationPass : public QQmlCompilePass
|
||||
{
|
||||
public:
|
||||
QQmlJavaScriptBindingExpressionSimplificationPass(QQmlTypeCompiler *typeCompiler);
|
||||
|
||||
void reduceTranslationBindings();
|
||||
|
||||
private:
|
||||
void reduceTranslationBindings(int objectIndex);
|
||||
|
||||
void visit(QV4::IR::Stmt *s)
|
||||
{
|
||||
switch (s->stmtKind) {
|
||||
case QV4::IR::Stmt::MoveStmt:
|
||||
visitMove(s->asMove());
|
||||
break;
|
||||
case QV4::IR::Stmt::RetStmt:
|
||||
visitRet(s->asRet());
|
||||
break;
|
||||
case QV4::IR::Stmt::CJumpStmt:
|
||||
discard();
|
||||
break;
|
||||
case QV4::IR::Stmt::ExpStmt:
|
||||
discard();
|
||||
break;
|
||||
case QV4::IR::Stmt::JumpStmt:
|
||||
break;
|
||||
case QV4::IR::Stmt::PhiStmt:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void visitMove(QV4::IR::Move *move);
|
||||
void visitRet(QV4::IR::Ret *ret);
|
||||
|
||||
void visitFunctionCall(const QString *name, QV4::IR::ExprList *args, QV4::IR::Temp *target);
|
||||
|
||||
void discard() { _canSimplify = false; }
|
||||
|
||||
bool simplifyBinding(QV4::IR::Function *function, QmlIR::Binding *binding);
|
||||
bool detectTranslationCallAndConvertBinding(QmlIR::Binding *binding);
|
||||
|
||||
const QVector<QmlIR::Object*> &qmlObjects;
|
||||
QV4::IR::Module *jsModule;
|
||||
|
||||
bool _canSimplify;
|
||||
const QString *_nameOfFunctionCalled;
|
||||
QVector<int> _functionParameters;
|
||||
int _functionCallReturnValue;
|
||||
|
||||
QHash<int, QV4::IR::Expr*> _temps;
|
||||
int _returnValueOfBindingExpression;
|
||||
int _synthesizedConsts;
|
||||
|
||||
QVector<int> irFunctionsToRemove;
|
||||
};
|
||||
|
||||
class QQmlIRFunctionCleanser : public QQmlCompilePass
|
||||
{
|
||||
public:
|
||||
QQmlIRFunctionCleanser(QQmlTypeCompiler *typeCompiler, const QVector<int> &functionsToRemove);
|
||||
|
||||
void clean();
|
||||
|
||||
private:
|
||||
virtual void visitMove(QV4::IR::Move *s) {
|
||||
visit(s->source);
|
||||
visit(s->target);
|
||||
}
|
||||
|
||||
void visit(QV4::IR::Stmt *s);
|
||||
void visit(QV4::IR::Expr *e);
|
||||
|
||||
private:
|
||||
QV4::IR::Module *module;
|
||||
const QVector<int> &functionsToRemove;
|
||||
|
||||
QVector<int> newFunctionIndices;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QQMLTYPECOMPILER_P_H
|
||||
|
|
|
@ -92,6 +92,27 @@ static bool cjumpCanHandle(IR::AluOp op)
|
|||
}
|
||||
}
|
||||
|
||||
static inline void setJumpOutLocation(IR::Stmt *s, const Statement *body,
|
||||
const SourceLocation &fallback)
|
||||
{
|
||||
switch (body->kind) {
|
||||
// Statements where we might never execute the last line.
|
||||
// Use the fallback.
|
||||
case Statement::Kind_ConditionalExpression:
|
||||
case Statement::Kind_ForEachStatement:
|
||||
case Statement::Kind_ForStatement:
|
||||
case Statement::Kind_IfStatement:
|
||||
case Statement::Kind_LocalForEachStatement:
|
||||
case Statement::Kind_LocalForStatement:
|
||||
case Statement::Kind_WhileStatement:
|
||||
setLocation(s, fallback);
|
||||
break;
|
||||
default:
|
||||
setLocation(s, body->lastSourceLocation());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Codegen::ScanFunctions::ScanFunctions(Codegen *cg, const QString &sourceCode, CompilationMode defaultProgramMode)
|
||||
: _cg(cg)
|
||||
, _sourceCode(sourceCode)
|
||||
|
@ -2269,7 +2290,7 @@ bool Codegen::visit(DoWhileStatement *ast)
|
|||
|
||||
_block = loopbody;
|
||||
statement(ast->statement);
|
||||
setLocation(_block->JUMP(loopcond), ast->statement->lastSourceLocation());
|
||||
setJumpOutLocation(_block->JUMP(loopcond), ast->statement, ast->semicolonToken);
|
||||
|
||||
_block = loopcond;
|
||||
condition(ast->expression, loopbody, loopend);
|
||||
|
@ -2334,7 +2355,7 @@ bool Codegen::visit(ForEachStatement *ast)
|
|||
return false;
|
||||
move(*init, _block->TEMP(temp));
|
||||
statement(ast->statement);
|
||||
setLocation(_block->JUMP(foreachin), ast->lastSourceLocation());
|
||||
setJumpOutLocation(_block->JUMP(foreachin), ast->statement, ast->forToken);
|
||||
|
||||
_block = foreachin;
|
||||
|
||||
|
@ -2373,7 +2394,7 @@ bool Codegen::visit(ForStatement *ast)
|
|||
|
||||
_block = forbody;
|
||||
statement(ast->statement);
|
||||
setLocation(_block->JUMP(forstep), ast->lastSourceLocation());
|
||||
setJumpOutLocation(_block->JUMP(forstep), ast->statement, ast->forToken);
|
||||
|
||||
_block = forstep;
|
||||
statement(ast->expression);
|
||||
|
@ -2399,12 +2420,12 @@ bool Codegen::visit(IfStatement *ast)
|
|||
|
||||
_block = iftrue;
|
||||
statement(ast->ok);
|
||||
_block->JUMP(endif);
|
||||
setJumpOutLocation(_block->JUMP(endif), ast->ok, ast->ifToken);
|
||||
|
||||
if (ast->ko) {
|
||||
_block = iffalse;
|
||||
statement(ast->ko);
|
||||
_block->JUMP(endif);
|
||||
setJumpOutLocation(_block->JUMP(endif), ast->ko, ast->elseToken);
|
||||
}
|
||||
|
||||
_block = endif;
|
||||
|
@ -2473,7 +2494,7 @@ bool Codegen::visit(LocalForEachStatement *ast)
|
|||
int temp = _block->newTemp();
|
||||
move(identifier(ast->declaration->name.toString()), _block->TEMP(temp));
|
||||
statement(ast->statement);
|
||||
setLocation(_block->JUMP(foreachin), ast->lastSourceLocation());
|
||||
setJumpOutLocation(_block->JUMP(foreachin), ast->statement, ast->forToken);
|
||||
|
||||
_block = foreachin;
|
||||
|
||||
|
@ -2512,7 +2533,7 @@ bool Codegen::visit(LocalForStatement *ast)
|
|||
|
||||
_block = forbody;
|
||||
statement(ast->statement);
|
||||
setLocation(_block->JUMP(forstep), ast->lastSourceLocation());
|
||||
setJumpOutLocation(_block->JUMP(forstep), ast->statement, ast->forToken);
|
||||
|
||||
_block = forstep;
|
||||
statement(ast->expression);
|
||||
|
@ -2813,7 +2834,7 @@ bool Codegen::visit(WhileStatement *ast)
|
|||
|
||||
_block = whilebody;
|
||||
statement(ast->statement);
|
||||
setLocation(_block->JUMP(whilecond), ast->lastSourceLocation());
|
||||
setJumpOutLocation(_block->JUMP(whilecond), ast->statement, ast->whileToken);
|
||||
|
||||
_block = whileend;
|
||||
leaveLoop();
|
||||
|
|
|
@ -461,6 +461,7 @@ bool CompilationUnit::saveToDisk(const QUrl &unitUrl, QString *errorString)
|
|||
|
||||
return true;
|
||||
#else
|
||||
Q_UNUSED(outputFileName)
|
||||
*errorString = QStringLiteral("features.temporaryfile is disabled.");
|
||||
return false;
|
||||
#endif // QT_CONFIG(temporaryfile)
|
||||
|
@ -745,7 +746,7 @@ static QByteArray ownLibraryChecksum()
|
|||
if (dladdr(reinterpret_cast<const void *>(&ownLibraryChecksum), &libInfo) != 0) {
|
||||
QFile library(QFile::decodeName(libInfo.dli_fname));
|
||||
if (library.open(QIODevice::ReadOnly)) {
|
||||
QCryptographicHash hash(QCryptographicHash::Sha1);
|
||||
QCryptographicHash hash(QCryptographicHash::Md5);
|
||||
hash.addData(&library);
|
||||
libraryChecksum = hash.result();
|
||||
}
|
||||
|
|
|
@ -376,7 +376,7 @@ QV4::CompiledData::Unit QV4::Compiler::JSUnitGenerator::generateHeader(QV4::Comp
|
|||
unit.version = QV4_DATA_STRUCTURE_VERSION;
|
||||
unit.qtVersion = QT_VERSION;
|
||||
memset(unit.md5Checksum, 0, sizeof(unit.md5Checksum));
|
||||
unit.architectureIndex = registerString(QSysInfo::buildAbi());
|
||||
unit.architectureIndex = registerString(irModule->targetABI.isEmpty() ? QSysInfo::buildAbi() : irModule->targetABI);
|
||||
unit.codeGeneratorIndex = registerString(codeGeneratorName);
|
||||
memset(unit.dependencyMD5Checksum, 0, sizeof(unit.dependencyMD5Checksum));
|
||||
|
||||
|
|
|
@ -58,6 +58,59 @@ QT_BEGIN_NAMESPACE
|
|||
|
||||
namespace QV4 {
|
||||
|
||||
struct TargetPrimitive32 {
|
||||
static TargetPrimitive32 emptyValue() { TargetPrimitive32 p; p._val = quint64(Value::ValueTypeInternal_32::Empty) << 32; return p; }
|
||||
static TargetPrimitive32 nullValue() { TargetPrimitive32 p; p._val = quint64(Value::ValueTypeInternal_32::Null) << 32; return p; }
|
||||
static TargetPrimitive32 undefinedValue() { TargetPrimitive32 p; p._val = quint64(Value::Managed_Type_Internal_32) << 32; return p; }
|
||||
static TargetPrimitive32 fromBoolean(bool b) { TargetPrimitive32 p; p._val = quint64(Value::ValueTypeInternal_32::Boolean) << 32 | quint64(b); return p; }
|
||||
static TargetPrimitive32 fromInt32(int v) { TargetPrimitive32 p; p._val = quint64(Value::ValueTypeInternal_32::Integer) << 32 | quint32(v); return p; }
|
||||
static TargetPrimitive32 fromDouble(double v) {
|
||||
TargetPrimitive32 p;
|
||||
memcpy(&p._val, &v, 8);
|
||||
return p;
|
||||
}
|
||||
static TargetPrimitive32 fromUInt32(uint v) {
|
||||
if (v < INT_MAX)
|
||||
return fromInt32(qint32(v));
|
||||
return fromDouble(double(v));
|
||||
}
|
||||
|
||||
quint32 value() const { return _val & quint64(~quint32(0)); }
|
||||
quint32 tag() const { return _val >> 32; }
|
||||
|
||||
quint64 rawValue() const { return _val; }
|
||||
|
||||
private:
|
||||
quint64 _val;
|
||||
};
|
||||
|
||||
struct TargetPrimitive64 {
|
||||
static TargetPrimitive64 emptyValue() { TargetPrimitive64 p; p._val = quint64(Value::ValueTypeInternal_64::Empty) << 32; return p; }
|
||||
static TargetPrimitive64 nullValue() { TargetPrimitive64 p; p._val = quint64(Value::ValueTypeInternal_64::Null) << 32; return p; }
|
||||
static TargetPrimitive64 undefinedValue() { TargetPrimitive64 p; p._val = 0; return p; }
|
||||
static TargetPrimitive64 fromBoolean(bool b) { TargetPrimitive64 p; p._val = quint64(Value::ValueTypeInternal_64::Boolean) << 32 | quint64(b); return p; }
|
||||
static TargetPrimitive64 fromInt32(int v) { TargetPrimitive64 p; p._val = quint64(Value::ValueTypeInternal_64::Integer) << 32 | quint32(v); return p; }
|
||||
static TargetPrimitive64 fromDouble(double v) {
|
||||
TargetPrimitive64 p;
|
||||
memcpy(&p._val, &v, 8);
|
||||
p._val ^= Value::NaNEncodeMask;
|
||||
return p;
|
||||
}
|
||||
static TargetPrimitive64 fromUInt32(uint v) {
|
||||
if (v < INT_MAX)
|
||||
return fromInt32(qint32(v));
|
||||
return fromDouble(double(v));
|
||||
}
|
||||
|
||||
quint32 value() const { return _val & quint64(~quint32(0)); }
|
||||
quint32 tag() const { return _val >> 32; }
|
||||
|
||||
quint64 rawValue() const { return _val; }
|
||||
|
||||
private:
|
||||
quint64 _val;
|
||||
};
|
||||
|
||||
inline bool canConvertToSignedInteger(double value)
|
||||
{
|
||||
int ival = (int) value;
|
||||
|
@ -72,36 +125,37 @@ inline bool canConvertToUnsignedInteger(double value)
|
|||
return uval == value && !(value == 0 && isNegative(value));
|
||||
}
|
||||
|
||||
inline Primitive convertToValue(IR::Const *c)
|
||||
template <typename PrimitiveType = Primitive>
|
||||
inline PrimitiveType convertToValue(IR::Const *c)
|
||||
{
|
||||
switch (c->type) {
|
||||
case IR::MissingType:
|
||||
return Primitive::emptyValue();
|
||||
return PrimitiveType::emptyValue();
|
||||
case IR::NullType:
|
||||
return Primitive::nullValue();
|
||||
return PrimitiveType::nullValue();
|
||||
case IR::UndefinedType:
|
||||
return Primitive::undefinedValue();
|
||||
return PrimitiveType::undefinedValue();
|
||||
case IR::BoolType:
|
||||
return Primitive::fromBoolean(c->value != 0);
|
||||
return PrimitiveType::fromBoolean(c->value != 0);
|
||||
case IR::SInt32Type:
|
||||
return Primitive::fromInt32(int(c->value));
|
||||
return PrimitiveType::fromInt32(int(c->value));
|
||||
case IR::UInt32Type:
|
||||
return Primitive::fromUInt32(unsigned(c->value));
|
||||
return PrimitiveType::fromUInt32(unsigned(c->value));
|
||||
case IR::DoubleType:
|
||||
return Primitive::fromDouble(c->value);
|
||||
return PrimitiveType::fromDouble(c->value);
|
||||
case IR::NumberType: {
|
||||
int ival = (int)c->value;
|
||||
if (canConvertToSignedInteger(c->value)) {
|
||||
return Primitive::fromInt32(ival);
|
||||
return PrimitiveType::fromInt32(ival);
|
||||
} else {
|
||||
return Primitive::fromDouble(c->value);
|
||||
return PrimitiveType::fromDouble(c->value);
|
||||
}
|
||||
}
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
// unreachable, but the function must return something
|
||||
return Primitive::undefinedValue();
|
||||
return PrimitiveType::undefinedValue();
|
||||
}
|
||||
|
||||
class ConvertTemps
|
||||
|
|
|
@ -946,6 +946,7 @@ struct Q_QML_PRIVATE_EXPORT Module {
|
|||
QDateTime sourceTimeStamp;
|
||||
bool isQmlModule; // implies rootFunction is always 0
|
||||
uint unitFlags; // flags merged into CompiledData::Unit::flags
|
||||
QString targetABI; // fallback to QSysInfo::buildAbi() if empty
|
||||
#ifdef QT_NO_QML_DEBUGGER
|
||||
static const bool debugMode = false;
|
||||
#else
|
||||
|
|
|
@ -0,0 +1,384 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2017 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the tools applications 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 The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qv4jssimplifier_p.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
QQmlJavaScriptBindingExpressionSimplificationPass::QQmlJavaScriptBindingExpressionSimplificationPass(const QVector<QmlIR::Object*> &qmlObjects, QV4::IR::Module *jsModule, QV4::Compiler::JSUnitGenerator *unitGenerator)
|
||||
: qmlObjects(qmlObjects)
|
||||
, jsModule(jsModule)
|
||||
, unitGenerator(unitGenerator)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void QQmlJavaScriptBindingExpressionSimplificationPass::reduceTranslationBindings()
|
||||
{
|
||||
for (int i = 0; i < qmlObjects.count(); ++i)
|
||||
reduceTranslationBindings(i);
|
||||
if (!irFunctionsToRemove.isEmpty()) {
|
||||
QQmlIRFunctionCleanser cleanser(jsModule, qmlObjects, irFunctionsToRemove);
|
||||
cleanser.clean();
|
||||
}
|
||||
}
|
||||
|
||||
void QQmlJavaScriptBindingExpressionSimplificationPass::reduceTranslationBindings(int objectIndex)
|
||||
{
|
||||
const QmlIR::Object *obj = qmlObjects.at(objectIndex);
|
||||
|
||||
for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
|
||||
if (binding->type != QV4::CompiledData::Binding::Type_Script)
|
||||
continue;
|
||||
|
||||
const int irFunctionIndex = obj->runtimeFunctionIndices.at(binding->value.compiledScriptIndex);
|
||||
QV4::IR::Function *irFunction = jsModule->functions.at(irFunctionIndex);
|
||||
if (simplifyBinding(irFunction, binding)) {
|
||||
irFunctionsToRemove.append(irFunctionIndex);
|
||||
jsModule->functions[irFunctionIndex] = 0;
|
||||
delete irFunction;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QQmlJavaScriptBindingExpressionSimplificationPass::visitMove(QV4::IR::Move *move)
|
||||
{
|
||||
QV4::IR::Temp *target = move->target->asTemp();
|
||||
if (!target || target->kind != QV4::IR::Temp::VirtualRegister) {
|
||||
discard();
|
||||
return;
|
||||
}
|
||||
|
||||
if (QV4::IR::Call *call = move->source->asCall()) {
|
||||
if (QV4::IR::Name *n = call->base->asName()) {
|
||||
if (n->builtin == QV4::IR::Name::builtin_invalid) {
|
||||
visitFunctionCall(n->id, call->args, target);
|
||||
return;
|
||||
}
|
||||
}
|
||||
discard();
|
||||
return;
|
||||
}
|
||||
|
||||
if (QV4::IR::Name *n = move->source->asName()) {
|
||||
if (n->builtin == QV4::IR::Name::builtin_qml_context
|
||||
|| n->builtin == QV4::IR::Name::builtin_qml_imported_scripts_object) {
|
||||
// these are free of side-effects
|
||||
return;
|
||||
}
|
||||
discard();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!move->source->asTemp() && !move->source->asString() && !move->source->asConst()) {
|
||||
discard();
|
||||
return;
|
||||
}
|
||||
|
||||
_temps[target->index] = move->source;
|
||||
}
|
||||
|
||||
void QQmlJavaScriptBindingExpressionSimplificationPass::visitFunctionCall(const QString *name, QV4::IR::ExprList *args, QV4::IR::Temp *target)
|
||||
{
|
||||
// more than one function call?
|
||||
if (_nameOfFunctionCalled) {
|
||||
discard();
|
||||
return;
|
||||
}
|
||||
|
||||
_nameOfFunctionCalled = name;
|
||||
|
||||
_functionParameters.clear();
|
||||
while (args) {
|
||||
int slot;
|
||||
if (QV4::IR::Temp *param = args->expr->asTemp()) {
|
||||
if (param->kind != QV4::IR::Temp::VirtualRegister) {
|
||||
discard();
|
||||
return;
|
||||
}
|
||||
slot = param->index;
|
||||
_functionParameters.append(slot);
|
||||
} else if (QV4::IR::Const *param = args->expr->asConst()) {
|
||||
slot = --_synthesizedConsts;
|
||||
Q_ASSERT(!_temps.contains(slot));
|
||||
_temps[slot] = param;
|
||||
_functionParameters.append(slot);
|
||||
}
|
||||
args = args->next;
|
||||
}
|
||||
|
||||
_functionCallReturnValue = target->index;
|
||||
}
|
||||
|
||||
void QQmlJavaScriptBindingExpressionSimplificationPass::visitRet(QV4::IR::Ret *ret)
|
||||
{
|
||||
// nothing initialized earlier?
|
||||
if (_returnValueOfBindingExpression != -1) {
|
||||
discard();
|
||||
return;
|
||||
}
|
||||
QV4::IR::Temp *target = ret->expr->asTemp();
|
||||
if (!target || target->kind != QV4::IR::Temp::VirtualRegister) {
|
||||
discard();
|
||||
return;
|
||||
}
|
||||
_returnValueOfBindingExpression = target->index;
|
||||
}
|
||||
|
||||
bool QQmlJavaScriptBindingExpressionSimplificationPass::simplifyBinding(QV4::IR::Function *function, QmlIR::Binding *binding)
|
||||
{
|
||||
_canSimplify = true;
|
||||
_nameOfFunctionCalled = 0;
|
||||
_functionParameters.clear();
|
||||
_functionCallReturnValue = -1;
|
||||
_temps.clear();
|
||||
_returnValueOfBindingExpression = -1;
|
||||
_synthesizedConsts = 0;
|
||||
|
||||
// It would seem unlikely that function with some many basic blocks (after optimization)
|
||||
// consists merely of a qsTr call or a constant value return ;-)
|
||||
if (function->basicBlockCount() > 10)
|
||||
return false;
|
||||
|
||||
for (QV4::IR::BasicBlock *bb : function->basicBlocks()) {
|
||||
for (QV4::IR::Stmt *s : bb->statements()) {
|
||||
visit(s);
|
||||
if (!_canSimplify)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (_returnValueOfBindingExpression == -1)
|
||||
return false;
|
||||
|
||||
if (_nameOfFunctionCalled) {
|
||||
if (_functionCallReturnValue != _returnValueOfBindingExpression)
|
||||
return false;
|
||||
return detectTranslationCallAndConvertBinding(binding);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QQmlJavaScriptBindingExpressionSimplificationPass::detectTranslationCallAndConvertBinding(QmlIR::Binding *binding)
|
||||
{
|
||||
if (*_nameOfFunctionCalled == QLatin1String("qsTr")) {
|
||||
QString translation;
|
||||
QV4::CompiledData::TranslationData translationData;
|
||||
translationData.number = -1;
|
||||
translationData.commentIndex = 0; // empty string
|
||||
|
||||
QVector<int>::ConstIterator param = _functionParameters.constBegin();
|
||||
QVector<int>::ConstIterator end = _functionParameters.constEnd();
|
||||
if (param == end)
|
||||
return false;
|
||||
|
||||
QV4::IR::String *stringParam = _temps[*param]->asString();
|
||||
if (!stringParam)
|
||||
return false;
|
||||
|
||||
translation = *stringParam->value;
|
||||
|
||||
++param;
|
||||
if (param != end) {
|
||||
stringParam = _temps[*param]->asString();
|
||||
if (!stringParam)
|
||||
return false;
|
||||
translationData.commentIndex = unitGenerator->registerString(*stringParam->value);
|
||||
++param;
|
||||
|
||||
if (param != end) {
|
||||
QV4::IR::Const *constParam = _temps[*param]->asConst();
|
||||
if (!constParam || constParam->type != QV4::IR::SInt32Type)
|
||||
return false;
|
||||
|
||||
translationData.number = int(constParam->value);
|
||||
++param;
|
||||
}
|
||||
}
|
||||
|
||||
if (param != end)
|
||||
return false;
|
||||
|
||||
binding->type = QV4::CompiledData::Binding::Type_Translation;
|
||||
binding->stringIndex = unitGenerator->registerString(translation);
|
||||
binding->value.translationData = translationData;
|
||||
return true;
|
||||
} else if (*_nameOfFunctionCalled == QLatin1String("qsTrId")) {
|
||||
QString id;
|
||||
QV4::CompiledData::TranslationData translationData;
|
||||
translationData.number = -1;
|
||||
translationData.commentIndex = 0; // empty string, but unused
|
||||
|
||||
QVector<int>::ConstIterator param = _functionParameters.constBegin();
|
||||
QVector<int>::ConstIterator end = _functionParameters.constEnd();
|
||||
if (param == end)
|
||||
return false;
|
||||
|
||||
QV4::IR::String *stringParam = _temps[*param]->asString();
|
||||
if (!stringParam)
|
||||
return false;
|
||||
|
||||
id = *stringParam->value;
|
||||
|
||||
++param;
|
||||
if (param != end) {
|
||||
QV4::IR::Const *constParam = _temps[*param]->asConst();
|
||||
if (!constParam || constParam->type != QV4::IR::SInt32Type)
|
||||
return false;
|
||||
|
||||
translationData.number = int(constParam->value);
|
||||
++param;
|
||||
}
|
||||
|
||||
if (param != end)
|
||||
return false;
|
||||
|
||||
binding->type = QV4::CompiledData::Binding::Type_TranslationById;
|
||||
binding->stringIndex = unitGenerator->registerString(id);
|
||||
binding->value.translationData = translationData;
|
||||
return true;
|
||||
} else if (*_nameOfFunctionCalled == QLatin1String("QT_TR_NOOP") || *_nameOfFunctionCalled == QLatin1String("QT_TRID_NOOP")) {
|
||||
QVector<int>::ConstIterator param = _functionParameters.constBegin();
|
||||
QVector<int>::ConstIterator end = _functionParameters.constEnd();
|
||||
if (param == end)
|
||||
return false;
|
||||
|
||||
QV4::IR::String *stringParam = _temps[*param]->asString();
|
||||
if (!stringParam)
|
||||
return false;
|
||||
|
||||
++param;
|
||||
if (param != end)
|
||||
return false;
|
||||
|
||||
binding->type = QV4::CompiledData::Binding::Type_String;
|
||||
binding->stringIndex = unitGenerator->registerString(*stringParam->value);
|
||||
return true;
|
||||
} else if (*_nameOfFunctionCalled == QLatin1String("QT_TRANSLATE_NOOP")) {
|
||||
QVector<int>::ConstIterator param = _functionParameters.constBegin();
|
||||
QVector<int>::ConstIterator end = _functionParameters.constEnd();
|
||||
if (param == end)
|
||||
return false;
|
||||
|
||||
++param;
|
||||
if (param == end)
|
||||
return false;
|
||||
|
||||
QV4::IR::String *stringParam = _temps[*param]->asString();
|
||||
if (!stringParam)
|
||||
return false;
|
||||
|
||||
++param;
|
||||
if (param != end)
|
||||
return false;
|
||||
|
||||
binding->type = QV4::CompiledData::Binding::Type_String;
|
||||
binding->stringIndex = unitGenerator->registerString(*stringParam->value);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QQmlIRFunctionCleanser::QQmlIRFunctionCleanser(QV4::IR::Module *module, const QVector<QmlIR::Object *> &qmlObjects, const QVector<int> &functionsToRemove)
|
||||
: module(module)
|
||||
, qmlObjects(qmlObjects)
|
||||
, functionsToRemove(functionsToRemove)
|
||||
{
|
||||
}
|
||||
|
||||
void QQmlIRFunctionCleanser::clean()
|
||||
{
|
||||
QVector<QV4::IR::Function*> newFunctions;
|
||||
newFunctions.reserve(module->functions.count() - functionsToRemove.count());
|
||||
|
||||
newFunctionIndices.resize(module->functions.count());
|
||||
|
||||
for (int i = 0; i < module->functions.count(); ++i) {
|
||||
QV4::IR::Function *f = module->functions.at(i);
|
||||
Q_ASSERT(f || functionsToRemove.contains(i));
|
||||
if (f) {
|
||||
newFunctionIndices[i] = newFunctions.count();
|
||||
newFunctions << f;
|
||||
}
|
||||
}
|
||||
|
||||
module->functions = newFunctions;
|
||||
|
||||
for (QV4::IR::Function *function : qAsConst(module->functions)) {
|
||||
for (QV4::IR::BasicBlock *block : function->basicBlocks()) {
|
||||
for (QV4::IR::Stmt *s : block->statements()) {
|
||||
visit(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (QmlIR::Object *obj : qmlObjects) {
|
||||
for (int i = 0; i < obj->runtimeFunctionIndices.count; ++i)
|
||||
obj->runtimeFunctionIndices[i] = newFunctionIndices[obj->runtimeFunctionIndices.at(i)];
|
||||
}
|
||||
}
|
||||
|
||||
void QQmlIRFunctionCleanser::visit(QV4::IR::Stmt *s)
|
||||
{
|
||||
|
||||
switch (s->stmtKind) {
|
||||
case QV4::IR::Stmt::PhiStmt:
|
||||
// nothing to do
|
||||
break;
|
||||
default:
|
||||
STMT_VISIT_ALL_KINDS(s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void QQmlIRFunctionCleanser::visit(QV4::IR::Expr *e)
|
||||
{
|
||||
switch (e->exprKind) {
|
||||
case QV4::IR::Expr::ClosureExpr: {
|
||||
auto closure = e->asClosure();
|
||||
closure->value = newFunctionIndices.at(closure->value);
|
||||
} break;
|
||||
default:
|
||||
EXPR_VISIT_ALL_KINDS(e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
|
@ -0,0 +1,154 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2017 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the tools applications 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 The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
#ifndef QV4JSSIMPLIFIER
|
||||
#define QV4JSSIMPLIFIER
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include <private/qv4global_p.h>
|
||||
|
||||
#include "qqmlirbuilder_p.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
namespace QmlIR {
|
||||
struct Document;
|
||||
}
|
||||
|
||||
namespace QV4 {
|
||||
namespace CompiledData {
|
||||
struct QmlUnit;
|
||||
struct Location;
|
||||
}
|
||||
}
|
||||
|
||||
class QQmlJavaScriptBindingExpressionSimplificationPass
|
||||
{
|
||||
public:
|
||||
QQmlJavaScriptBindingExpressionSimplificationPass(const QVector<QmlIR::Object*> &qmlObjects, QV4::IR::Module *jsModule, QV4::Compiler::JSUnitGenerator *unitGenerator);
|
||||
|
||||
void reduceTranslationBindings();
|
||||
|
||||
private:
|
||||
void reduceTranslationBindings(int objectIndex);
|
||||
|
||||
void visit(QV4::IR::Stmt *s)
|
||||
{
|
||||
switch (s->stmtKind) {
|
||||
case QV4::IR::Stmt::MoveStmt:
|
||||
visitMove(s->asMove());
|
||||
break;
|
||||
case QV4::IR::Stmt::RetStmt:
|
||||
visitRet(s->asRet());
|
||||
break;
|
||||
case QV4::IR::Stmt::CJumpStmt:
|
||||
discard();
|
||||
break;
|
||||
case QV4::IR::Stmt::ExpStmt:
|
||||
discard();
|
||||
break;
|
||||
case QV4::IR::Stmt::JumpStmt:
|
||||
break;
|
||||
case QV4::IR::Stmt::PhiStmt:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void visitMove(QV4::IR::Move *move);
|
||||
void visitRet(QV4::IR::Ret *ret);
|
||||
|
||||
void visitFunctionCall(const QString *name, QV4::IR::ExprList *args, QV4::IR::Temp *target);
|
||||
|
||||
void discard() { _canSimplify = false; }
|
||||
|
||||
bool simplifyBinding(QV4::IR::Function *function, QmlIR::Binding *binding);
|
||||
bool detectTranslationCallAndConvertBinding(QmlIR::Binding *binding);
|
||||
|
||||
const QVector<QmlIR::Object*> &qmlObjects;
|
||||
QV4::IR::Module *jsModule;
|
||||
QV4::Compiler::JSUnitGenerator *unitGenerator;
|
||||
|
||||
bool _canSimplify;
|
||||
const QString *_nameOfFunctionCalled;
|
||||
QVector<int> _functionParameters;
|
||||
int _functionCallReturnValue;
|
||||
|
||||
QHash<int, QV4::IR::Expr*> _temps;
|
||||
int _returnValueOfBindingExpression;
|
||||
int _synthesizedConsts;
|
||||
|
||||
QVector<int> irFunctionsToRemove;
|
||||
};
|
||||
|
||||
class QQmlIRFunctionCleanser
|
||||
{
|
||||
public:
|
||||
QQmlIRFunctionCleanser(QV4::IR::Module *module, const QVector<QmlIR::Object*> &qmlObjects, const QVector<int> &functionsToRemove);
|
||||
|
||||
void clean();
|
||||
|
||||
private:
|
||||
virtual void visitMove(QV4::IR::Move *s) {
|
||||
visit(s->source);
|
||||
visit(s->target);
|
||||
}
|
||||
|
||||
void visit(QV4::IR::Stmt *s);
|
||||
void visit(QV4::IR::Expr *e);
|
||||
|
||||
private:
|
||||
QV4::IR::Module *module;
|
||||
const QVector<QmlIR::Object*> &qmlObjects;
|
||||
const QVector<int> &functionsToRemove;
|
||||
|
||||
QVector<int> newFunctionIndices;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QV4JSSIMPLIFIER
|
|
@ -687,7 +687,7 @@ class MessageBoard : public QObject
|
|||
Q_PROPERTY(QQmlListProperty<Message> messages READ messages)
|
||||
Q_CLASSINFO("DefaultProperty", "messages")
|
||||
public:
|
||||
QQmlListProperty<Message> messages() const;
|
||||
QQmlListProperty<Message> messages();
|
||||
|
||||
private:
|
||||
QList<Message *> messages;
|
||||
|
|
|
@ -267,7 +267,7 @@ class MessageBoard : public QObject
|
|||
Q_OBJECT
|
||||
Q_PROPERTY(QQmlListProperty<Message> messages READ messages)
|
||||
public:
|
||||
QQmlListProperty<Message> messages() const;
|
||||
QQmlListProperty<Message> messages();
|
||||
|
||||
private:
|
||||
static void append_message(QQmlListProperty<Message> *list, Message *msg);
|
||||
|
|
|
@ -155,9 +155,6 @@ bool CompilationUnit::saveCodeToDisk(QIODevice *device, const CompiledData::Unit
|
|||
return true;
|
||||
}
|
||||
|
||||
template <typename TargetConfiguration>
|
||||
const typename Assembler<TargetConfiguration>::VoidType Assembler<TargetConfiguration>::Void;
|
||||
|
||||
template <typename TargetConfiguration>
|
||||
Assembler<TargetConfiguration>::Assembler(QV4::Compiler::JSUnitGenerator *jsGenerator, IR::Function* function, QV4::ExecutableAllocator *executableAllocator)
|
||||
: _function(function)
|
||||
|
@ -324,21 +321,21 @@ typename Assembler<TargetConfiguration>::Pointer Assembler<TargetConfiguration>:
|
|||
loadPtr(Address(Assembler::ScratchRegister, targetStructureOffset(Heap::ExecutionContextData::baseOffset + offsetof(Heap::ExecutionContextData, compilationUnit))), Assembler::ScratchRegister);
|
||||
loadPtr(Address(Assembler::ScratchRegister, offsetof(CompiledData::CompilationUnitBase, runtimeStrings)), reg);
|
||||
const int id = _jsGenerator->registerString(string);
|
||||
return Pointer(reg, id * sizeof(QV4::String*));
|
||||
return Pointer(reg, id * RegisterSize);
|
||||
}
|
||||
|
||||
template <typename TargetConfiguration>
|
||||
typename Assembler<TargetConfiguration>::Address Assembler<TargetConfiguration>::loadConstant(IR::Const *c, RegisterID baseReg)
|
||||
{
|
||||
return loadConstant(convertToValue(c), baseReg);
|
||||
return loadConstant(convertToValue<TargetPrimitive>(c), baseReg);
|
||||
}
|
||||
|
||||
template <typename TargetConfiguration>
|
||||
typename Assembler<TargetConfiguration>::Address Assembler<TargetConfiguration>::loadConstant(const Primitive &v, RegisterID baseReg)
|
||||
typename Assembler<TargetConfiguration>::Address Assembler<TargetConfiguration>::loadConstant(const TargetPrimitive &v, RegisterID baseReg)
|
||||
{
|
||||
loadPtr(Address(Assembler::EngineRegister, targetStructureOffset(offsetof(QV4::EngineBase, current))), baseReg);
|
||||
loadPtr(Address(baseReg, targetStructureOffset(Heap::ExecutionContextData::baseOffset + offsetof(Heap::ExecutionContextData, constantTable))), baseReg);
|
||||
const int index = _jsGenerator->registerConstant(v.asReturnedValue());
|
||||
const int index = _jsGenerator->registerConstant(v.rawValue());
|
||||
return Address(baseReg, index * sizeof(QV4::Value));
|
||||
}
|
||||
|
||||
|
@ -350,7 +347,7 @@ void Assembler<TargetConfiguration>::loadStringRef(RegisterID reg, const QString
|
|||
}
|
||||
|
||||
template <typename TargetConfiguration>
|
||||
void Assembler<TargetConfiguration>::storeValue(QV4::Primitive value, IR::Expr *destination)
|
||||
void Assembler<TargetConfiguration>::storeValue(TargetPrimitive value, IR::Expr *destination)
|
||||
{
|
||||
WriteBarrier::Type barrier;
|
||||
Address addr = loadAddressForWriting(ScratchRegister, destination, &barrier);
|
||||
|
@ -449,19 +446,13 @@ typename Assembler<TargetConfiguration>::Jump Assembler<TargetConfiguration>::ge
|
|||
|
||||
// check if it's an int32:
|
||||
Assembler::Jump isNoInt = branch32(Assembler::NotEqual, Assembler::ScratchRegister,
|
||||
Assembler::TrustedImm32(Value::Integer_Type_Internal));
|
||||
Assembler::TrustedImm32(quint32(ValueTypeInternal::Integer)));
|
||||
convertInt32ToDouble(toInt32Register(src, Assembler::ScratchRegister), dest);
|
||||
Assembler::Jump intDone = jump();
|
||||
|
||||
// not an int, check if it's a double:
|
||||
isNoInt.link(this);
|
||||
#ifdef QV4_USE_64_BIT_VALUE_ENCODING
|
||||
rshift32(TrustedImm32(Value::IsDoubleTag_Shift), ScratchRegister);
|
||||
Assembler::Jump isNoDbl = branch32(RelationalCondition::Equal, JITTargetPlatform::ScratchRegister, TrustedImm32(0));
|
||||
#else
|
||||
and32(Assembler::TrustedImm32(Value::NotDouble_Mask), Assembler::ScratchRegister);
|
||||
Assembler::Jump isNoDbl = branch32(RelationalCondition::Equal, JITTargetPlatform::ScratchRegister, TrustedImm32(Value::NotDouble_Mask));
|
||||
#endif
|
||||
Assembler::Jump isNoDbl = RegisterSizeDependentOps::checkIfTagRegisterIsDouble(this, ScratchRegister);
|
||||
toDoubleRegister(src, dest);
|
||||
intDone.link(this);
|
||||
|
||||
|
@ -530,7 +521,7 @@ void Assembler<TargetConfiguration>::returnFromFunction(IR::Ret *s, RegisterInfo
|
|||
} else if (IR::Temp *t = s->expr->asTemp()) {
|
||||
RegisterSizeDependentOps::setFunctionReturnValueFromTemp(this, t);
|
||||
} else if (IR::Const *c = s->expr->asConst()) {
|
||||
QV4::Primitive retVal = convertToValue(c);
|
||||
auto retVal = convertToValue<TargetPrimitive>(c);
|
||||
RegisterSizeDependentOps::setFunctionReturnValueFromConst(this, retVal);
|
||||
} else {
|
||||
Q_UNREACHABLE();
|
||||
|
@ -547,7 +538,7 @@ void Assembler<TargetConfiguration>::returnFromFunction(IR::Ret *s, RegisterInfo
|
|||
ret();
|
||||
|
||||
exceptionReturnLabel = label();
|
||||
QV4::Primitive retVal = Primitive::undefinedValue();
|
||||
auto retVal = TargetPrimitive::undefinedValue();
|
||||
RegisterSizeDependentOps::setFunctionReturnValueFromConst(this, retVal);
|
||||
jump(leaveStackFrame);
|
||||
}
|
||||
|
|
|
@ -153,6 +153,8 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo
|
|||
using TrustedImm64 = typename JITAssembler::TrustedImm64;
|
||||
using Jump = typename JITAssembler::Jump;
|
||||
using Label = typename JITAssembler::Label;
|
||||
using ValueTypeInternal = Value::ValueTypeInternal_32;
|
||||
using TargetPrimitive = TargetPrimitive32;
|
||||
|
||||
static void emitSetGrayBit(JITAssembler *as, RegisterID base)
|
||||
{
|
||||
|
@ -223,9 +225,9 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo
|
|||
as->storeDouble(source, ptr, barrier);
|
||||
}
|
||||
|
||||
static void storeValue(JITAssembler *as, QV4::Primitive value, Address destination, WriteBarrier::Type barrier)
|
||||
static void storeValue(JITAssembler *as, TargetPrimitive value, Address destination, WriteBarrier::Type barrier)
|
||||
{
|
||||
as->store32(TrustedImm32(value.int_32()), destination);
|
||||
as->store32(TrustedImm32(value.value()), destination);
|
||||
destination.offset += 4;
|
||||
as->store32(TrustedImm32(value.tag()), destination);
|
||||
if (WriteBarrier::isRequired<WriteBarrier::Primitive>() && barrier == WriteBarrier::Barrier)
|
||||
|
@ -282,16 +284,16 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo
|
|||
Jump done = as->jump();
|
||||
intRange.link(as);
|
||||
as->move(srcReg, lowReg);
|
||||
as->move(TrustedImm32(QV4::Value::Integer_Type_Internal), highReg);
|
||||
as->move(TrustedImm32(quint32(QV4::Value::ValueTypeInternal_32::Integer)), highReg);
|
||||
done.link(as);
|
||||
} break;
|
||||
case IR::SInt32Type:
|
||||
as->move((RegisterID) t->index, lowReg);
|
||||
as->move(TrustedImm32(QV4::Value::Integer_Type_Internal), highReg);
|
||||
as->move(TrustedImm32(quint32(QV4::Value::ValueTypeInternal_32::Integer)), highReg);
|
||||
break;
|
||||
case IR::BoolType:
|
||||
as->move((RegisterID) t->index, lowReg);
|
||||
as->move(TrustedImm32(QV4::Value::Boolean_Type_Internal), highReg);
|
||||
as->move(TrustedImm32(quint32(QV4::Value::ValueTypeInternal_32::Boolean)), highReg);
|
||||
break;
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
|
@ -304,9 +306,9 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo
|
|||
}
|
||||
}
|
||||
|
||||
static void setFunctionReturnValueFromConst(JITAssembler *as, QV4::Primitive retVal)
|
||||
static void setFunctionReturnValueFromConst(JITAssembler *as, TargetPrimitive retVal)
|
||||
{
|
||||
as->move(TrustedImm32(retVal.int_32()), TargetPlatform::LowReturnValueRegister);
|
||||
as->move(TrustedImm32(retVal.value()), TargetPlatform::LowReturnValueRegister);
|
||||
as->move(TrustedImm32(retVal.tag()), TargetPlatform::HighReturnValueRegister);
|
||||
}
|
||||
|
||||
|
@ -382,7 +384,7 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo
|
|||
|
||||
// check if it's an int32:
|
||||
Jump fallback = as->branch32(RelationalCondition::NotEqual, TargetPlatform::ReturnValueRegister,
|
||||
TrustedImm32(Value::Integer_Type_Internal));
|
||||
TrustedImm32(quint32(Value::ValueTypeInternal_32::Integer)));
|
||||
IR::Temp *targetTemp = target->asTemp();
|
||||
if (!targetTemp || targetTemp->kind == IR::Temp::StackSlot) {
|
||||
as->load32(addr, TargetPlatform::ReturnValueRegister);
|
||||
|
@ -390,7 +392,7 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo
|
|||
Pointer targetAddr = as->loadAddressForWriting(TargetPlatform::ScratchRegister, target, &barrier);
|
||||
as->store32(TargetPlatform::ReturnValueRegister, targetAddr);
|
||||
targetAddr.offset += 4;
|
||||
as->store32(TrustedImm32(Value::Integer_Type_Internal), targetAddr);
|
||||
as->store32(TrustedImm32(quint32(Value::ValueTypeInternal_32::Integer)), targetAddr);
|
||||
if (WriteBarrier::isRequired<WriteBarrier::Primitive>() && barrier == WriteBarrier::Barrier)
|
||||
emitWriteBarrier(as, targetAddr);
|
||||
} else {
|
||||
|
@ -435,6 +437,13 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo
|
|||
Jump jump = as->branchSub32(ResultCondition::NonZero, TrustedImm32(1), TargetPlatform::ScratchRegister);
|
||||
jump.linkTo(loop, as);
|
||||
}
|
||||
|
||||
static Jump checkIfTagRegisterIsDouble(JITAssembler *as, RegisterID tagRegister)
|
||||
{
|
||||
as->and32(TrustedImm32(Value::NotDouble_Mask), tagRegister);
|
||||
Jump isNoDbl = as->branch32(RelationalCondition::Equal, tagRegister, TrustedImm32(Value::NotDouble_Mask));
|
||||
return isNoDbl;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename JITAssembler, typename MacroAssembler, typename TargetPlatform>
|
||||
|
@ -451,6 +460,8 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo
|
|||
using BranchTruncateType = typename JITAssembler::BranchTruncateType;
|
||||
using Jump = typename JITAssembler::Jump;
|
||||
using Label = typename JITAssembler::Label;
|
||||
using ValueTypeInternal = Value::ValueTypeInternal_64;
|
||||
using TargetPrimitive = TargetPrimitive64;
|
||||
|
||||
static void emitSetGrayBit(JITAssembler *as, RegisterID base)
|
||||
{
|
||||
|
@ -558,7 +569,7 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo
|
|||
Jump done = as->jump();
|
||||
intRange.link(as);
|
||||
as->zeroExtend32ToPtr(srcReg, TargetPlatform::ReturnValueRegister);
|
||||
quint64 tag = QV4::Value::Integer_Type_Internal;
|
||||
quint64 tag = quint64(QV4::Value::ValueTypeInternal_64::Integer);
|
||||
as->or64(TrustedImm64(tag << 32),
|
||||
TargetPlatform::ReturnValueRegister);
|
||||
done.link(as);
|
||||
|
@ -567,10 +578,10 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo
|
|||
quint64 tag;
|
||||
switch (t->type) {
|
||||
case IR::SInt32Type:
|
||||
tag = QV4::Value::Integer_Type_Internal;
|
||||
tag = quint64(QV4::Value::ValueTypeInternal_64::Integer);
|
||||
break;
|
||||
case IR::BoolType:
|
||||
tag = QV4::Value::Boolean_Type_Internal;
|
||||
tag = quint64(QV4::Value::ValueTypeInternal_64::Boolean);
|
||||
break;
|
||||
default:
|
||||
tag = 31337; // bogus value
|
||||
|
@ -584,12 +595,12 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo
|
|||
}
|
||||
}
|
||||
|
||||
static void setFunctionReturnValueFromConst(JITAssembler *as, QV4::Primitive retVal)
|
||||
static void setFunctionReturnValueFromConst(JITAssembler *as, TargetPrimitive retVal)
|
||||
{
|
||||
as->move(TrustedImm64(retVal.rawValue()), TargetPlatform::ReturnValueRegister);
|
||||
}
|
||||
|
||||
static void storeValue(JITAssembler *as, QV4::Primitive value, Address destination, WriteBarrier::Type barrier)
|
||||
static void storeValue(JITAssembler *as, TargetPrimitive value, Address destination, WriteBarrier::Type barrier)
|
||||
{
|
||||
as->store64(TrustedImm64(value.rawValue()), destination);
|
||||
if (WriteBarrier::isRequired<WriteBarrier::Unknown>() && barrier == WriteBarrier::Barrier)
|
||||
|
@ -628,7 +639,7 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo
|
|||
Pointer addr = as->loadTempAddress(temp);
|
||||
as->load64(addr, dest);
|
||||
} else {
|
||||
QV4::Value undefined = QV4::Primitive::undefinedValue();
|
||||
auto undefined = TargetPrimitive::undefinedValue();
|
||||
as->move(TrustedImm64(undefined.rawValue()), dest);
|
||||
}
|
||||
}
|
||||
|
@ -641,7 +652,7 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo
|
|||
Pointer addr = as->loadArgLocalAddressForReading(dest, al);
|
||||
as->load64(addr, dest);
|
||||
} else {
|
||||
QV4::Value undefined = QV4::Primitive::undefinedValue();
|
||||
auto undefined = TargetPrimitive::undefinedValue();
|
||||
as->move(TrustedImm64(undefined.rawValue()), dest);
|
||||
}
|
||||
}
|
||||
|
@ -650,7 +661,7 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo
|
|||
{
|
||||
Q_UNUSED(argumentNumber);
|
||||
|
||||
QV4::Value v = convertToValue(c);
|
||||
auto v = convertToValue<TargetPrimitive64>(c);
|
||||
as->move(TrustedImm64(v.rawValue()), dest);
|
||||
}
|
||||
|
||||
|
@ -659,7 +670,7 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo
|
|||
Q_UNUSED(argumentNumber);
|
||||
|
||||
if (!expr) {
|
||||
QV4::Value undefined = QV4::Primitive::undefinedValue();
|
||||
auto undefined = TargetPrimitive::undefinedValue();
|
||||
as->move(TrustedImm64(undefined.rawValue()), dest);
|
||||
} else if (IR::Temp *t = expr->asTemp()){
|
||||
loadArgumentInRegister(as, t, dest, argumentNumber);
|
||||
|
@ -751,7 +762,7 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo
|
|||
Pointer targetAddr = as->loadAddressForWriting(TargetPlatform::ScratchRegister, target, &barrier);
|
||||
as->store32(TargetPlatform::ReturnValueRegister, targetAddr);
|
||||
targetAddr.offset += 4;
|
||||
as->store32(TrustedImm32(Value::Integer_Type_Internal), targetAddr);
|
||||
as->store32(TrustedImm32(quint32(Value::ValueTypeInternal_64::Integer)), targetAddr);
|
||||
if (WriteBarrier::isRequired<WriteBarrier::Primitive>() && barrier == WriteBarrier::Barrier)
|
||||
emitWriteBarrier(as, targetAddr);
|
||||
} else {
|
||||
|
@ -783,6 +794,13 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo
|
|||
Jump jump = as->branchSub32(ResultCondition::NonZero, TrustedImm32(1), TargetPlatform::ScratchRegister);
|
||||
jump.linkTo(loop, as);
|
||||
}
|
||||
|
||||
static Jump checkIfTagRegisterIsDouble(JITAssembler *as, RegisterID tagRegister)
|
||||
{
|
||||
as->rshift32(TrustedImm32(Value::IsDoubleTag_Shift), tagRegister);
|
||||
Jump isNoDbl = as->branch32(RelationalCondition::Equal, tagRegister, TrustedImm32(0));
|
||||
return isNoDbl;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TargetConfiguration>
|
||||
|
@ -851,8 +869,6 @@ public:
|
|||
return (hostOffset * RegisterSize) / QT_POINTER_SIZE;
|
||||
}
|
||||
|
||||
using RegisterSizeDependentOps = RegisterSizeDependentAssembler<Assembler<TargetConfiguration>, MacroAssembler, JITTargetPlatform, RegisterSize>;
|
||||
|
||||
struct LookupCall {
|
||||
Address addr;
|
||||
uint getterSetterOffset;
|
||||
|
@ -883,6 +899,10 @@ public:
|
|||
{}
|
||||
};
|
||||
|
||||
using RegisterSizeDependentOps = RegisterSizeDependentAssembler<Assembler<TargetConfiguration>, MacroAssembler, JITTargetPlatform, RegisterSize>;
|
||||
using ValueTypeInternal = typename RegisterSizeDependentOps::ValueTypeInternal;
|
||||
using TargetPrimitive = typename RegisterSizeDependentOps::TargetPrimitive;
|
||||
|
||||
// V4 uses two stacks: one stack with QV4::Value items, which is checked by the garbage
|
||||
// collector, and one stack used by the native C/C++/ABI code. This C++ stack is not scanned
|
||||
// by the garbage collector, so if any JS object needs to be retained, it should be put on the
|
||||
|
@ -1112,7 +1132,7 @@ public:
|
|||
}
|
||||
Pointer loadStringAddress(RegisterID reg, const QString &string);
|
||||
Address loadConstant(IR::Const *c, RegisterID baseReg);
|
||||
Address loadConstant(const Primitive &v, RegisterID baseReg);
|
||||
Address loadConstant(const TargetPrimitive &v, RegisterID baseReg);
|
||||
void loadStringRef(RegisterID reg, const QString &string);
|
||||
Pointer stackSlotPointer(IR::Temp *t) const
|
||||
{
|
||||
|
@ -1387,12 +1407,12 @@ public:
|
|||
RegisterSizeDependentOps::emitWriteBarrier(this, dest);
|
||||
}
|
||||
|
||||
void storeValue(QV4::Primitive value, Address destination, WriteBarrier::Type barrier)
|
||||
void storeValue(TargetPrimitive value, Address destination, WriteBarrier::Type barrier)
|
||||
{
|
||||
RegisterSizeDependentOps::storeValue(this, value, destination, barrier);
|
||||
}
|
||||
|
||||
void storeValue(QV4::Primitive value, IR::Expr* temp);
|
||||
void storeValue(TargetPrimitive value, IR::Expr* temp);
|
||||
|
||||
void emitWriteBarrier(Address addr, WriteBarrier::Type barrier) {
|
||||
if (WriteBarrier::isRequired<WriteBarrier::Primitive>() && barrier == WriteBarrier::Barrier)
|
||||
|
@ -1426,13 +1446,7 @@ public:
|
|||
if (argumentNumber < RegisterArgumentCount)
|
||||
loadArgumentInRegister(value, registerForArgument(argumentNumber), argumentNumber);
|
||||
else
|
||||
#if OS(WINDOWS) && CPU(X86_64)
|
||||
loadArgumentOnStack<argumentNumber>(value, argumentNumber);
|
||||
#elif CPU(MIPS) // Stack space for 4 arguments needs to be allocated for MIPS platforms.
|
||||
loadArgumentOnStack<argumentNumber>(value, argumentNumber + 4);
|
||||
#else // Sanity:
|
||||
loadArgumentOnStack<argumentNumber - RegisterArgumentCount>(value, argumentNumber);
|
||||
#endif
|
||||
loadArgumentOnStack<argumentNumber - RegisterArgumentCount + (StackShadowSpace / RegisterSize)>(value, argumentNumber);
|
||||
}
|
||||
|
||||
template <int argumentNumber>
|
||||
|
@ -1576,8 +1590,8 @@ public:
|
|||
Address tagAddr = addr;
|
||||
tagAddr.offset += 4;
|
||||
|
||||
QV4::Primitive v = convertToValue(c);
|
||||
store32(TrustedImm32(v.int_32()), addr);
|
||||
auto v = convertToValue<TargetPrimitive>(c);
|
||||
store32(TrustedImm32(v.value()), addr);
|
||||
store32(TrustedImm32(v.tag()), tagAddr);
|
||||
return Pointer(addr);
|
||||
}
|
||||
|
@ -1593,7 +1607,7 @@ public:
|
|||
{
|
||||
store32(reg, addr);
|
||||
addr.offset += 4;
|
||||
store32(TrustedImm32(QV4::Primitive::fromBoolean(0).tag()), addr);
|
||||
store32(TrustedImm32(TargetPrimitive::fromBoolean(0).tag()), addr);
|
||||
if (WriteBarrier::isRequired<WriteBarrier::Primitive>() && barrier == WriteBarrier::Barrier)
|
||||
RegisterSizeDependentOps::emitWriteBarrier(this, addr);
|
||||
}
|
||||
|
@ -1640,7 +1654,7 @@ public:
|
|||
{
|
||||
store32(reg, addr);
|
||||
addr.offset += 4;
|
||||
store32(TrustedImm32(QV4::Primitive::fromInt32(0).tag()), addr);
|
||||
store32(TrustedImm32(TargetPrimitive::fromInt32(0).tag()), addr);
|
||||
if (WriteBarrier::isRequired<WriteBarrier::Primitive>() && barrier == WriteBarrier::Barrier)
|
||||
RegisterSizeDependentOps::emitWriteBarrier(this, addr);
|
||||
}
|
||||
|
@ -1709,7 +1723,7 @@ public:
|
|||
RegisterID toInt32Register(IR::Expr *e, RegisterID scratchReg)
|
||||
{
|
||||
if (IR::Const *c = e->asConst()) {
|
||||
move(TrustedImm32(convertToValue(c).int_32()), scratchReg);
|
||||
move(TrustedImm32(convertToValue<Primitive>(c).int_32()), scratchReg);
|
||||
return scratchReg;
|
||||
}
|
||||
|
||||
|
@ -1748,11 +1762,11 @@ public:
|
|||
Pointer tagAddr = addr;
|
||||
tagAddr.offset += 4;
|
||||
load32(tagAddr, scratchReg);
|
||||
Jump inIntRange = branch32(RelationalCondition::Equal, scratchReg, TrustedImm32(QV4::Value::Integer_Type_Internal));
|
||||
Jump inIntRange = branch32(RelationalCondition::Equal, scratchReg, TrustedImm32(quint32(ValueTypeInternal::Integer)));
|
||||
|
||||
// it's not in signed int range, so load it as a double, and truncate it down
|
||||
loadDouble(addr, FPGpr0);
|
||||
Address inversionAddress = loadConstant(QV4::Primitive::fromDouble(double(INT_MAX) + 1), scratchReg);
|
||||
Address inversionAddress = loadConstant(TargetPrimitive::fromDouble(double(INT_MAX) + 1), scratchReg);
|
||||
subDouble(inversionAddress, FPGpr0);
|
||||
Jump canNeverHappen = branchTruncateDoubleToUint32(FPGpr0, scratchReg);
|
||||
canNeverHappen.link(this);
|
||||
|
@ -1807,6 +1821,9 @@ private:
|
|||
QV4::Compiler::JSUnitGenerator *_jsGenerator;
|
||||
};
|
||||
|
||||
template <typename TargetConfiguration>
|
||||
const typename Assembler<TargetConfiguration>::VoidType Assembler<TargetConfiguration>::Void;
|
||||
|
||||
template <typename TargetConfiguration>
|
||||
template <typename Result, typename Source>
|
||||
void Assembler<TargetConfiguration>::copyValue(Result result, Source source, WriteBarrier::Type barrier)
|
||||
|
@ -1832,7 +1849,7 @@ void Assembler<TargetConfiguration>::copyValue(Result result, IR::Expr* source,
|
|||
} else if (source->asTemp() || source->asArgLocal()) {
|
||||
RegisterSizeDependentOps::copyValueViaRegisters(this, source, result, barrier);
|
||||
} else if (IR::Const *c = source->asConst()) {
|
||||
QV4::Primitive v = convertToValue(c);
|
||||
auto v = convertToValue<TargetPrimitive>(c);
|
||||
storeValue(v, result, barrier);
|
||||
} else {
|
||||
Q_UNREACHABLE();
|
||||
|
|
|
@ -256,7 +256,7 @@ void InstructionSelection<JITAssembler>::callBuiltinDeleteName(const QString &na
|
|||
template <typename JITAssembler>
|
||||
void InstructionSelection<JITAssembler>::callBuiltinDeleteValue(IR::Expr *result)
|
||||
{
|
||||
_as->storeValue(Primitive::fromBoolean(false), result);
|
||||
_as->storeValue(JITAssembler::TargetPrimitive::fromBoolean(false), result);
|
||||
}
|
||||
|
||||
template <typename JITAssembler>
|
||||
|
@ -376,7 +376,7 @@ void InstructionSelection<JITAssembler>::callBuiltinDefineObjectLiteral(IR::Expr
|
|||
++arrayValueCount;
|
||||
|
||||
// Index
|
||||
_as->storeValue(QV4::Primitive::fromUInt32(index), _as->stackLayout().argumentAddressForCall(argc++), WriteBarrier::NoBarrier);
|
||||
_as->storeValue(JITAssembler::TargetPrimitive::fromUInt32(index), _as->stackLayout().argumentAddressForCall(argc++), WriteBarrier::NoBarrier);
|
||||
|
||||
// Value
|
||||
_as->copyValue(_as->stackLayout().argumentAddressForCall(argc++), it->expr, WriteBarrier::NoBarrier);
|
||||
|
@ -400,7 +400,7 @@ void InstructionSelection<JITAssembler>::callBuiltinDefineObjectLiteral(IR::Expr
|
|||
++arrayGetterSetterCount;
|
||||
|
||||
// Index
|
||||
_as->storeValue(QV4::Primitive::fromUInt32(index), _as->stackLayout().argumentAddressForCall(argc++), WriteBarrier::NoBarrier);
|
||||
_as->storeValue(JITAssembler::TargetPrimitive::fromUInt32(index), _as->stackLayout().argumentAddressForCall(argc++), WriteBarrier::NoBarrier);
|
||||
|
||||
// Getter
|
||||
_as->copyValue(_as->stackLayout().argumentAddressForCall(argc++), it->expr, WriteBarrier::NoBarrier);
|
||||
|
@ -488,7 +488,7 @@ void InstructionSelection<JITAssembler>::loadConst(IR::Const *sourceConst, IR::E
|
|||
_as->toUInt32Register(sourceConst, (RegisterID) targetTemp->index);
|
||||
} else if (targetTemp->type == IR::BoolType) {
|
||||
Q_ASSERT(sourceConst->type == IR::BoolType);
|
||||
_as->move(TrustedImm32(convertToValue(sourceConst).int_32()),
|
||||
_as->move(TrustedImm32(convertToValue<Primitive>(sourceConst).int_32()),
|
||||
(RegisterID) targetTemp->index);
|
||||
} else {
|
||||
Q_UNREACHABLE();
|
||||
|
@ -497,7 +497,7 @@ void InstructionSelection<JITAssembler>::loadConst(IR::Const *sourceConst, IR::E
|
|||
}
|
||||
}
|
||||
|
||||
_as->storeValue(convertToValue(sourceConst), target);
|
||||
_as->storeValue(convertToValue<typename JITAssembler::TargetPrimitive>(sourceConst), target);
|
||||
}
|
||||
|
||||
template <typename JITAssembler>
|
||||
|
@ -781,10 +781,10 @@ void InstructionSelection<JITAssembler>::swapValues(IR::Expr *source, IR::Expr *
|
|||
quint32 tag;
|
||||
switch (regTemp->type) {
|
||||
case IR::BoolType:
|
||||
tag = QV4::Value::Boolean_Type_Internal;
|
||||
tag = quint32(JITAssembler::ValueTypeInternal::Boolean);
|
||||
break;
|
||||
case IR::SInt32Type:
|
||||
tag = QV4::Value::Integer_Type_Internal;
|
||||
tag = quint32(JITAssembler::ValueTypeInternal::Integer);
|
||||
break;
|
||||
default:
|
||||
tag = 31337; // bogus value
|
||||
|
@ -933,7 +933,7 @@ void InstructionSelection<JITAssembler>::convertTypeToDouble(IR::Expr *source, I
|
|||
|
||||
// check if it's an int32:
|
||||
Jump isNoInt = _as->branch32(RelationalCondition::NotEqual, JITTargetPlatform::ScratchRegister,
|
||||
TrustedImm32(Value::Integer_Type_Internal));
|
||||
TrustedImm32(quint32(JITAssembler::ValueTypeInternal::Integer)));
|
||||
convertIntToDouble(source, target);
|
||||
Jump intDone = _as->jump();
|
||||
|
||||
|
@ -1011,13 +1011,13 @@ void InstructionSelection<JITAssembler>::convertTypeToBool(IR::Expr *source, IR:
|
|||
|
||||
// checkif it's a bool:
|
||||
Jump notBool = _as->branch32(RelationalCondition::NotEqual, JITTargetPlatform::ReturnValueRegister,
|
||||
TrustedImm32(Value::Boolean_Type_Internal));
|
||||
TrustedImm32(quint32(JITAssembler::ValueTypeInternal::Boolean)));
|
||||
_as->load32(addr, JITTargetPlatform::ReturnValueRegister);
|
||||
Jump boolDone = _as->jump();
|
||||
// check if it's an int32:
|
||||
notBool.link(_as);
|
||||
Jump fallback = _as->branch32(RelationalCondition::NotEqual, JITTargetPlatform::ReturnValueRegister,
|
||||
TrustedImm32(Value::Integer_Type_Internal));
|
||||
TrustedImm32(quint32(JITAssembler::ValueTypeInternal::Integer)));
|
||||
_as->load32(addr, JITTargetPlatform::ReturnValueRegister);
|
||||
Jump isZero = _as->branch32(RelationalCondition::Equal, JITTargetPlatform::ReturnValueRegister,
|
||||
TrustedImm32(0));
|
||||
|
@ -1087,7 +1087,7 @@ void InstructionSelection<JITAssembler>::convertTypeToUInt32(IR::Expr *source, I
|
|||
|
||||
// check if it's an int32:
|
||||
Jump isNoInt = _as->branch32(RelationalCondition::NotEqual, JITTargetPlatform::ScratchRegister,
|
||||
TrustedImm32(Value::Integer_Type_Internal));
|
||||
TrustedImm32(quint32(JITAssembler::ValueTypeInternal::Integer)));
|
||||
Pointer addr = _as->loadAddressForReading(JITTargetPlatform::ScratchRegister, source);
|
||||
_as->storeUInt32(_as->toInt32Register(addr, JITTargetPlatform::ScratchRegister), target);
|
||||
Jump intDone = _as->jump();
|
||||
|
@ -1203,7 +1203,8 @@ void InstructionSelection<JITAssembler>::visitCJump(IR::CJump *s)
|
|||
Address temp = _as->loadAddressForReading(JITTargetPlatform::ScratchRegister, s->cond);
|
||||
Address tag = temp;
|
||||
tag.offset += QV4::Value::tagOffset();
|
||||
Jump booleanConversion = _as->branch32(RelationalCondition::NotEqual, tag, TrustedImm32(QV4::Value::Boolean_Type_Internal));
|
||||
Jump booleanConversion = _as->branch32(RelationalCondition::NotEqual, tag,
|
||||
TrustedImm32(quint32(JITAssembler::ValueTypeInternal::Boolean)));
|
||||
|
||||
Address data = temp;
|
||||
data.offset += QV4::Value::valueOffset();
|
||||
|
@ -1322,12 +1323,12 @@ int InstructionSelection<JITAssembler>::prepareCallData(IR::ExprList* args, IR::
|
|||
}
|
||||
|
||||
Pointer p = _as->stackLayout().callDataAddress(offsetof(CallData, tag));
|
||||
_as->store32(TrustedImm32(QV4::Value::Integer_Type_Internal), p);
|
||||
_as->store32(TrustedImm32(quint32(JITAssembler::ValueTypeInternal::Integer)), p);
|
||||
p = _as->stackLayout().callDataAddress(offsetof(CallData, argc));
|
||||
_as->store32(TrustedImm32(argc), p);
|
||||
p = _as->stackLayout().callDataAddress(offsetof(CallData, thisObject));
|
||||
if (!thisObject)
|
||||
_as->storeValue(QV4::Primitive::undefinedValue(), p, WriteBarrier::NoBarrier);
|
||||
_as->storeValue(JITAssembler::TargetPrimitive::undefinedValue(), p, WriteBarrier::NoBarrier);
|
||||
else
|
||||
_as->copyValue(p, thisObject, WriteBarrier::NoBarrier);
|
||||
|
||||
|
@ -1464,7 +1465,7 @@ bool InstructionSelection<JITAssembler>::visitCJumpStrictNull(IR::Binop *binop,
|
|||
|
||||
RelationalCondition cond = binop->op == IR::OpStrictEqual ? RelationalCondition::Equal
|
||||
: RelationalCondition::NotEqual;
|
||||
const TrustedImm32 tag(QV4::Value::Null_Type_Internal);
|
||||
const TrustedImm32 tag{quint32(JITAssembler::ValueTypeInternal::Null)};
|
||||
_as->generateCJumpOnCompare(cond, tagReg, tag, _block, trueBlock, falseBlock);
|
||||
return true;
|
||||
}
|
||||
|
@ -1546,7 +1547,7 @@ bool InstructionSelection<JITAssembler>::visitCJumpStrictBool(IR::Binop *binop,
|
|||
// check if the tag of the var operand is indicates 'boolean'
|
||||
_as->load32(otherAddr, JITTargetPlatform::ScratchRegister);
|
||||
Jump noBool = _as->branch32(RelationalCondition::NotEqual, JITTargetPlatform::ScratchRegister,
|
||||
TrustedImm32(QV4::Value::Boolean_Type_Internal));
|
||||
TrustedImm32(quint32(JITAssembler::ValueTypeInternal::Boolean)));
|
||||
if (binop->op == IR::OpStrictEqual)
|
||||
_as->addPatch(falseBlock, noBool);
|
||||
else
|
||||
|
@ -1596,7 +1597,7 @@ bool InstructionSelection<JITAssembler>::visitCJumpNullUndefined(IR::Type nullOr
|
|||
|
||||
if (binop->op == IR::OpNotEqual)
|
||||
qSwap(trueBlock, falseBlock);
|
||||
Jump isNull = _as->branch32(RelationalCondition::Equal, tagReg, TrustedImm32(int(QV4::Value::Null_Type_Internal)));
|
||||
Jump isNull = _as->branch32(RelationalCondition::Equal, tagReg, TrustedImm32(quint32(JITAssembler::ValueTypeInternal::Null)));
|
||||
Jump isNotUndefinedTag = _as->branch32(RelationalCondition::NotEqual, tagReg, TrustedImm32(int(QV4::Value::Managed_Type_Internal)));
|
||||
tagAddr.offset -= 4;
|
||||
_as->load32(tagAddr, tagReg);
|
||||
|
@ -1648,18 +1649,18 @@ Q_QML_EXPORT QV4::EvalISelFactory *createISelForArchitecture(const QString &arch
|
|||
using ARMv7CrossAssembler = QV4::JIT::Assembler<AssemblerTargetConfiguration<JSC::MacroAssemblerARMv7, NoOperatingSystemSpecialization>>;
|
||||
using ARM64CrossAssembler = QV4::JIT::Assembler<AssemblerTargetConfiguration<JSC::MacroAssemblerARM64, NoOperatingSystemSpecialization>>;
|
||||
|
||||
if (architecture == QLatin1String("armv7"))
|
||||
if (architecture == QLatin1String("arm"))
|
||||
return new ISelFactory<ARMv7CrossAssembler>;
|
||||
else if (architecture == QLatin1String("armv8"))
|
||||
else if (architecture == QLatin1String("arm64"))
|
||||
return new ISelFactory<ARM64CrossAssembler>;
|
||||
|
||||
QString hostArch;
|
||||
#if CPU(ARM_THUMB2)
|
||||
hostArch = QStringLiteral("armv7");
|
||||
hostArch = QStringLiteral("arm");
|
||||
#elif CPU(MIPS)
|
||||
hostArch = QStringLiteral("mips");
|
||||
#elif CPU(X86)
|
||||
hostArch = QStringLiteral("x86");
|
||||
hostArch = QStringLiteral("i386");
|
||||
#elif CPU(X86_64)
|
||||
hostArch = QStringLiteral("x86_64");
|
||||
#endif
|
||||
|
|
|
@ -160,7 +160,7 @@ protected:
|
|||
// FramePointerRegister points to its old value on the stack, and above
|
||||
// it we have the return address, hence the need to step over two
|
||||
// values before reaching the first argument.
|
||||
return Address(JITTargetPlatform::FramePointerRegister, (index + 2) * sizeof(void*));
|
||||
return Address(JITTargetPlatform::FramePointerRegister, (index + 2) * JITTargetPlatform::RegisterSize);
|
||||
}
|
||||
|
||||
Pointer baseAddressForCallArguments()
|
||||
|
|
|
@ -405,7 +405,7 @@ public:
|
|||
<< 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) && !defined(V4_BOOTSTRAP)
|
||||
#if CPU(ARM_THUMB2) || defined(V4_BOOTSTRAP)
|
||||
<< 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)
|
||||
|
|
|
@ -524,7 +524,7 @@ void ExecutionEngine::initRootContext()
|
|||
sizeof(GlobalContext::Data) + sizeof(CallData)));
|
||||
r->d_unchecked()->init(this);
|
||||
r->d()->callData = reinterpret_cast<CallData *>(r->d() + 1);
|
||||
r->d()->callData->tag = QV4::Value::Integer_Type_Internal;
|
||||
r->d()->callData->tag = quint32(Value::ValueTypeInternal::Integer);
|
||||
r->d()->callData->argc = 0;
|
||||
r->d()->callData->thisObject = globalObject;
|
||||
r->d()->callData->args[0] = Encode::undefined();
|
||||
|
|
|
@ -394,6 +394,7 @@ void EvalFunction::evalCall(Scope &scope, CallData *callData, bool directCall) c
|
|||
// set the correct strict mode flag on the context
|
||||
ctx->d()->strictMode = false;
|
||||
ctx->d()->compilationUnit = function->compilationUnit;
|
||||
ctx->d()->constantTable = function->compilationUnit->constants;
|
||||
|
||||
scope.result = Q_V4_PROFILE(ctx->engine(), function);
|
||||
}
|
||||
|
|
|
@ -368,7 +368,7 @@ struct ScopedCallData {
|
|||
{
|
||||
int size = qMax(argc, QV4::Global::ReservedArgumentCount + int(offsetof(QV4::CallData, args)/sizeof(QV4::Value)));
|
||||
ptr = reinterpret_cast<CallData *>(scope.alloc(size));
|
||||
ptr->tag = QV4::Value::Integer_Type_Internal;
|
||||
ptr->tag = quint32(QV4::Value::ValueTypeInternal::Integer);
|
||||
ptr->argc = argc;
|
||||
}
|
||||
|
||||
|
|
|
@ -207,23 +207,23 @@ public:
|
|||
}
|
||||
QML_NEARLY_ALWAYS_INLINE void setInt_32(int i)
|
||||
{
|
||||
setTagValue(Integer_Type_Internal, quint32(i));
|
||||
setTagValue(quint32(ValueTypeInternal::Integer), quint32(i));
|
||||
}
|
||||
QML_NEARLY_ALWAYS_INLINE uint uint_32() const { return value(); }
|
||||
|
||||
QML_NEARLY_ALWAYS_INLINE void setEmpty()
|
||||
{
|
||||
setTagValue(Empty_Type_Internal, value());
|
||||
setTagValue(quint32(ValueTypeInternal::Empty), value());
|
||||
}
|
||||
|
||||
QML_NEARLY_ALWAYS_INLINE void setEmpty(int i)
|
||||
{
|
||||
setTagValue(Empty_Type_Internal, quint32(i));
|
||||
setTagValue(quint32(ValueTypeInternal::Empty), quint32(i));
|
||||
}
|
||||
|
||||
QML_NEARLY_ALWAYS_INLINE void setEmpty(quint32 i)
|
||||
{
|
||||
setTagValue(Empty_Type_Internal, i);
|
||||
setTagValue(quint32(ValueTypeInternal::Empty), i);
|
||||
}
|
||||
|
||||
QML_NEARLY_ALWAYS_INLINE quint32 emptyValue()
|
||||
|
@ -266,8 +266,17 @@ public:
|
|||
IsDoubleTag_Shift = IsDouble_Shift - Tag_Shift,
|
||||
Managed_Type_Internal_64 = 0
|
||||
};
|
||||
|
||||
static const quint64 Immediate_Mask_64 = 0x00020000u; // bit 49
|
||||
|
||||
enum class ValueTypeInternal_64 {
|
||||
Empty = Immediate_Mask_64| 0,
|
||||
ConvertibleToInt = Immediate_Mask_64| 0x10000u, // bit 48
|
||||
Null = ConvertibleToInt | 0x08000u,
|
||||
Boolean = ConvertibleToInt | 0x04000u,
|
||||
Integer = ConvertibleToInt | 0x02000u
|
||||
};
|
||||
|
||||
// Used only by 32-bit encoding
|
||||
enum Masks {
|
||||
SilentNaNBit = 0x00040000,
|
||||
|
@ -275,6 +284,14 @@ public:
|
|||
};
|
||||
static const quint64 Immediate_Mask_32 = NotDouble_Mask | 0x00020000u | SilentNaNBit;
|
||||
|
||||
enum class ValueTypeInternal_32 {
|
||||
Empty = Immediate_Mask_32| 0,
|
||||
ConvertibleToInt = Immediate_Mask_32| 0x10000u, // bit 48
|
||||
Null = ConvertibleToInt | 0x08000u,
|
||||
Boolean = ConvertibleToInt | 0x04000u,
|
||||
Integer = ConvertibleToInt | 0x02000u
|
||||
};
|
||||
|
||||
enum {
|
||||
Managed_Type_Internal_32 = NotDouble_Mask
|
||||
};
|
||||
|
@ -284,28 +301,23 @@ public:
|
|||
Managed_Type_Internal = Managed_Type_Internal_64
|
||||
};
|
||||
static const quint64 Immediate_Mask = Immediate_Mask_64;
|
||||
using ValueTypeInternal = ValueTypeInternal_64;
|
||||
#else
|
||||
enum {
|
||||
Managed_Type_Internal = Managed_Type_Internal_32
|
||||
};
|
||||
static const quint64 Immediate_Mask = Immediate_Mask_32;
|
||||
using ValueTypeInternal = ValueTypeInternal_32;
|
||||
#endif
|
||||
enum {
|
||||
NaN_Mask = 0x7ff80000,
|
||||
};
|
||||
enum ValueTypeInternal {
|
||||
Empty_Type_Internal = Immediate_Mask | 0,
|
||||
ConvertibleToInt = Immediate_Mask | 0x10000u, // bit 48
|
||||
Null_Type_Internal = ConvertibleToInt | 0x08000u,
|
||||
Boolean_Type_Internal = ConvertibleToInt | 0x04000u,
|
||||
Integer_Type_Internal = ConvertibleToInt | 0x02000u
|
||||
};
|
||||
|
||||
// used internally in property
|
||||
inline bool isEmpty() const { return tag() == Empty_Type_Internal; }
|
||||
inline bool isNull() const { return tag() == Null_Type_Internal; }
|
||||
inline bool isBoolean() const { return tag() == Boolean_Type_Internal; }
|
||||
inline bool isInteger() const { return tag() == Integer_Type_Internal; }
|
||||
inline bool isEmpty() const { return tag() == quint32(ValueTypeInternal::Empty); }
|
||||
inline bool isNull() const { return tag() == quint32(ValueTypeInternal::Null); }
|
||||
inline bool isBoolean() const { return tag() == quint32(ValueTypeInternal::Boolean); }
|
||||
inline bool isInteger() const { return tag() == quint32(ValueTypeInternal::Integer); }
|
||||
inline bool isNullOrUndefined() const { return isNull() || isUndefined(); }
|
||||
inline bool isNumber() const { return isDouble() || isInteger(); }
|
||||
|
||||
|
@ -330,9 +342,9 @@ public:
|
|||
inline bool isDouble() const { return (tag() & NotDouble_Mask) != NotDouble_Mask; }
|
||||
inline bool isManaged() const { return tag() == Managed_Type_Internal && !isUndefined(); }
|
||||
inline bool isManagedOrUndefined() const { return tag() == Managed_Type_Internal; }
|
||||
inline bool integerCompatible() const { return (tag() & ConvertibleToInt) == ConvertibleToInt; }
|
||||
inline bool integerCompatible() const { return (tag() & quint32(ValueTypeInternal::ConvertibleToInt)) == quint32(ValueTypeInternal::ConvertibleToInt); }
|
||||
static inline bool integerCompatible(Value a, Value b) {
|
||||
return ((a.tag() & b.tag()) & ConvertibleToInt) == ConvertibleToInt;
|
||||
return ((a.tag() & b.tag()) & quint32(ValueTypeInternal::ConvertibleToInt)) == quint32(ValueTypeInternal::ConvertibleToInt);
|
||||
}
|
||||
static inline bool bothDouble(Value a, Value b) {
|
||||
return ((a.tag() | b.tag()) & NotDouble_Mask) != NotDouble_Mask;
|
||||
|
@ -359,7 +371,7 @@ public:
|
|||
inline bool isString() const;
|
||||
inline bool isObject() const;
|
||||
inline bool isInt32() {
|
||||
if (tag() == Integer_Type_Internal)
|
||||
if (tag() == quint32(ValueTypeInternal::Integer))
|
||||
return true;
|
||||
if (isDouble()) {
|
||||
double d = doubleValue();
|
||||
|
@ -372,7 +384,7 @@ public:
|
|||
return false;
|
||||
}
|
||||
double asDouble() const {
|
||||
if (tag() == Integer_Type_Internal)
|
||||
if (tag() == quint32(ValueTypeInternal::Integer))
|
||||
return int_32();
|
||||
return doubleValue();
|
||||
}
|
||||
|
@ -427,7 +439,7 @@ public:
|
|||
inline bool tryIntegerConversion() {
|
||||
bool b = integerCompatible();
|
||||
if (b)
|
||||
setTagValue(Integer_Type_Internal, value());
|
||||
setTagValue(quint32(ValueTypeInternal::Integer), value());
|
||||
return b;
|
||||
}
|
||||
|
||||
|
@ -610,14 +622,14 @@ inline Primitive Primitive::emptyValue(uint e)
|
|||
inline Primitive Primitive::nullValue()
|
||||
{
|
||||
Primitive v;
|
||||
v.setTagValue(Null_Type_Internal, 0);
|
||||
v.setTagValue(quint32(ValueTypeInternal::Null), 0);
|
||||
return v;
|
||||
}
|
||||
|
||||
inline Primitive Primitive::fromBoolean(bool b)
|
||||
{
|
||||
Primitive v;
|
||||
v.setTagValue(Boolean_Type_Internal, b);
|
||||
v.setTagValue(quint32(ValueTypeInternal::Boolean), b);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
@ -639,7 +651,7 @@ inline Primitive Primitive::fromUInt32(uint i)
|
|||
{
|
||||
Primitive v;
|
||||
if (i < INT_MAX) {
|
||||
v.setTagValue(Integer_Type_Internal, i);
|
||||
v.setTagValue(quint32(ValueTypeInternal::Integer), i);
|
||||
} else {
|
||||
v.setDouble(i);
|
||||
}
|
||||
|
|
|
@ -251,6 +251,9 @@ int qt_v4DebuggerHook(const char *json)
|
|||
|
||||
static void qt_v4CheckForBreak(QV4::ExecutionContext *context)
|
||||
{
|
||||
if (!qt_v4IsStepping && !qt_v4Breakpoints.size())
|
||||
return;
|
||||
|
||||
const int lineNumber = context->d()->lineNumber;
|
||||
QV4::Function *function = qt_v4ExtractFunction(context);
|
||||
QString engineName = function->sourceFile();
|
||||
|
@ -585,7 +588,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
|
|||
#endif // DO_TRACE_INSTR
|
||||
Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
|
||||
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
|
||||
callData->tag = QV4::Value::Integer_Type_Internal;
|
||||
callData->tag = quint32(Value::ValueTypeInternal::Integer);
|
||||
callData->argc = instr.argc;
|
||||
callData->thisObject = QV4::Primitive::undefinedValue();
|
||||
STOREVALUE(instr.result, Runtime::method_callValue(engine, VALUE(instr.dest), callData));
|
||||
|
@ -595,7 +598,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
|
|||
TRACE(property name, "%s, args=%u, argc=%u, this=%s", qPrintable(runtimeStrings[instr.name]->toQString()), instr.callData, instr.argc, (VALUE(instr.base)).toString(context)->toQString().toUtf8().constData());
|
||||
Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
|
||||
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
|
||||
callData->tag = QV4::Value::Integer_Type_Internal;
|
||||
callData->tag = quint32(Value::ValueTypeInternal::Integer);
|
||||
callData->argc = instr.argc;
|
||||
callData->thisObject = VALUE(instr.base);
|
||||
STOREVALUE(instr.result, Runtime::method_callProperty(engine, instr.name, callData));
|
||||
|
@ -604,7 +607,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
|
|||
MOTH_BEGIN_INSTR(CallPropertyLookup)
|
||||
Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
|
||||
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
|
||||
callData->tag = QV4::Value::Integer_Type_Internal;
|
||||
callData->tag = quint32(Value::ValueTypeInternal::Integer);
|
||||
callData->argc = instr.argc;
|
||||
callData->thisObject = VALUE(instr.base);
|
||||
STOREVALUE(instr.result, Runtime::method_callPropertyLookup(engine, instr.lookupIndex, callData));
|
||||
|
@ -614,7 +617,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
|
|||
TRACE(property name, "%s, args=%u, argc=%u, this=%s", qPrintable(runtimeStrings[instr.name]->toQString()), instr.callData, instr.argc, (VALUE(instr.base)).toString(context)->toQString().toUtf8().constData());
|
||||
Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
|
||||
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
|
||||
callData->tag = QV4::Value::Integer_Type_Internal;
|
||||
callData->tag = quint32(Value::ValueTypeInternal::Integer);
|
||||
callData->argc = instr.argc;
|
||||
callData->thisObject = VALUE(instr.base);
|
||||
STOREVALUE(instr.result, Runtime::method_callQmlScopeObjectProperty(engine, instr.index, callData));
|
||||
|
@ -624,7 +627,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
|
|||
TRACE(property name, "%s, args=%u, argc=%u, this=%s", qPrintable(runtimeStrings[instr.name]->toQString()), instr.callData, instr.argc, (VALUE(instr.base)).toString(context)->toQString().toUtf8().constData());
|
||||
Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
|
||||
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
|
||||
callData->tag = QV4::Value::Integer_Type_Internal;
|
||||
callData->tag = quint32(Value::ValueTypeInternal::Integer);
|
||||
callData->argc = instr.argc;
|
||||
callData->thisObject = VALUE(instr.base);
|
||||
STOREVALUE(instr.result, Runtime::method_callQmlContextObjectProperty(engine, instr.index, callData));
|
||||
|
@ -633,7 +636,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
|
|||
MOTH_BEGIN_INSTR(CallElement)
|
||||
Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
|
||||
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
|
||||
callData->tag = QV4::Value::Integer_Type_Internal;
|
||||
callData->tag = quint32(Value::ValueTypeInternal::Integer);
|
||||
callData->argc = instr.argc;
|
||||
callData->thisObject = VALUE(instr.base);
|
||||
STOREVALUE(instr.result, Runtime::method_callElement(engine, VALUE(instr.index), callData));
|
||||
|
@ -642,7 +645,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
|
|||
MOTH_BEGIN_INSTR(CallActivationProperty)
|
||||
Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
|
||||
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
|
||||
callData->tag = QV4::Value::Integer_Type_Internal;
|
||||
callData->tag = quint32(Value::ValueTypeInternal::Integer);
|
||||
callData->argc = instr.argc;
|
||||
callData->thisObject = QV4::Primitive::undefinedValue();
|
||||
STOREVALUE(instr.result, Runtime::method_callActivationProperty(engine, instr.name, callData));
|
||||
|
@ -651,7 +654,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
|
|||
MOTH_BEGIN_INSTR(CallGlobalLookup)
|
||||
Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
|
||||
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
|
||||
callData->tag = QV4::Value::Integer_Type_Internal;
|
||||
callData->tag = quint32(Value::ValueTypeInternal::Integer);
|
||||
callData->argc = instr.argc;
|
||||
callData->thisObject = QV4::Primitive::undefinedValue();
|
||||
STOREVALUE(instr.result, Runtime::method_callGlobalLookup(engine, instr.index, callData));
|
||||
|
@ -757,7 +760,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
|
|||
MOTH_BEGIN_INSTR(CreateValue)
|
||||
Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
|
||||
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
|
||||
callData->tag = QV4::Value::Integer_Type_Internal;
|
||||
callData->tag = quint32(Value::ValueTypeInternal::Integer);
|
||||
callData->argc = instr.argc;
|
||||
callData->thisObject = QV4::Primitive::undefinedValue();
|
||||
STOREVALUE(instr.result, Runtime::method_constructValue(engine, VALUE(instr.func), callData));
|
||||
|
@ -766,7 +769,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
|
|||
MOTH_BEGIN_INSTR(CreateProperty)
|
||||
Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
|
||||
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
|
||||
callData->tag = QV4::Value::Integer_Type_Internal;
|
||||
callData->tag = quint32(Value::ValueTypeInternal::Integer);
|
||||
callData->argc = instr.argc;
|
||||
callData->thisObject = VALUE(instr.base);
|
||||
STOREVALUE(instr.result, Runtime::method_constructProperty(engine, instr.name, callData));
|
||||
|
@ -775,7 +778,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
|
|||
MOTH_BEGIN_INSTR(ConstructPropertyLookup)
|
||||
Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
|
||||
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
|
||||
callData->tag = QV4::Value::Integer_Type_Internal;
|
||||
callData->tag = quint32(Value::ValueTypeInternal::Integer);
|
||||
callData->argc = instr.argc;
|
||||
callData->thisObject = VALUE(instr.base);
|
||||
STOREVALUE(instr.result, Runtime::method_constructPropertyLookup(engine, instr.index, callData));
|
||||
|
@ -784,7 +787,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
|
|||
MOTH_BEGIN_INSTR(CreateActivationProperty)
|
||||
Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
|
||||
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
|
||||
callData->tag = QV4::Value::Integer_Type_Internal;
|
||||
callData->tag = quint32(Value::ValueTypeInternal::Integer);
|
||||
callData->argc = instr.argc;
|
||||
callData->thisObject = QV4::Primitive::undefinedValue();
|
||||
STOREVALUE(instr.result, Runtime::method_constructActivationProperty(engine, instr.name, callData));
|
||||
|
@ -793,7 +796,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
|
|||
MOTH_BEGIN_INSTR(ConstructGlobalLookup)
|
||||
Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
|
||||
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
|
||||
callData->tag = QV4::Value::Integer_Type_Internal;
|
||||
callData->tag = quint32(Value::ValueTypeInternal::Integer);
|
||||
callData->argc = instr.argc;
|
||||
callData->thisObject = QV4::Primitive::undefinedValue();
|
||||
STOREVALUE(instr.result, Runtime::method_constructGlobalLookup(engine, instr.index, callData));
|
||||
|
|
|
@ -48,7 +48,9 @@ include(jit/jit.pri)
|
|||
include(jsruntime/jsruntime.pri)
|
||||
include(qml/qml.pri)
|
||||
include(debugger/debugger.pri)
|
||||
include(animations/animations.pri)
|
||||
qtConfig(animation) {
|
||||
include(animations/animations.pri)
|
||||
}
|
||||
include(types/types.pri)
|
||||
|
||||
MODULE_PLUGIN_TYPES = \
|
||||
|
|
|
@ -82,7 +82,9 @@
|
|||
#include <private/qqmllocale_p.h>
|
||||
#include <private/qqmlbind_p.h>
|
||||
#include <private/qqmlconnections_p.h>
|
||||
#if QT_CONFIG(animation)
|
||||
#include <private/qqmltimer_p.h>
|
||||
#endif
|
||||
#include <private/qqmllistmodel_p.h>
|
||||
#include <private/qqmlplatform_p.h>
|
||||
#include <private/qquickpackage_p.h>
|
||||
|
@ -218,7 +220,9 @@ void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int
|
|||
qmlRegisterType<QQmlBind,8>(uri, versionMajor, (versionMinor < 8 ? 8 : versionMinor), "Binding"); //Only available in >=2.8
|
||||
qmlRegisterType<QQmlConnections,1>(uri, versionMajor, (versionMinor < 3 ? 3 : versionMinor), "Connections"); //Only available in >=2.3
|
||||
qmlRegisterType<QQmlConnections>(uri, versionMajor, versionMinor,"Connections");
|
||||
#if QT_CONFIG(animation)
|
||||
qmlRegisterType<QQmlTimer>(uri, versionMajor, versionMinor,"Timer");
|
||||
#endif
|
||||
qmlRegisterType<QQmlInstantiator>(uri, versionMajor, (versionMinor < 1 ? 1 : versionMinor), "Instantiator"); //Only available in >=2.1
|
||||
qmlRegisterCustomType<QQmlConnections>(uri, versionMajor, versionMinor,"Connections", new QQmlConnectionsParser);
|
||||
qmlRegisterType<QQmlInstanceModel>();
|
||||
|
|
|
@ -7,7 +7,6 @@ SOURCES += \
|
|||
$$PWD/qqmlmodelsmodule.cpp \
|
||||
$$PWD/qqmlmodelindexvaluetype.cpp \
|
||||
$$PWD/qqmlobjectmodel.cpp \
|
||||
$$PWD/qqmltimer.cpp \
|
||||
$$PWD/qquickpackage.cpp \
|
||||
$$PWD/qquickworkerscript.cpp \
|
||||
$$PWD/qqmlinstantiator.cpp
|
||||
|
@ -23,8 +22,15 @@ HEADERS += \
|
|||
$$PWD/qqmlmodelsmodule_p.h \
|
||||
$$PWD/qqmlmodelindexvaluetype_p.h \
|
||||
$$PWD/qqmlobjectmodel_p.h \
|
||||
$$PWD/qqmltimer_p.h \
|
||||
$$PWD/qquickpackage_p.h \
|
||||
$$PWD/qquickworkerscript_p.h \
|
||||
$$PWD/qqmlinstantiator_p.h \
|
||||
$$PWD/qqmlinstantiator_p_p.h
|
||||
|
||||
qtConfig(animation) {
|
||||
SOURCES += \
|
||||
$$PWD/qqmltimer.cpp
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/qqmltimer_p.h
|
||||
}
|
||||
|
|
|
@ -1104,14 +1104,17 @@ bool QQuickCanvasItem::isImageLoaded(const QUrl& url) const
|
|||
QImage QQuickCanvasItem::toImage(const QRectF& rect) const
|
||||
{
|
||||
Q_D(const QQuickCanvasItem);
|
||||
if (d->context) {
|
||||
if (rect.isEmpty())
|
||||
return d->context->toImage(canvasWindow());
|
||||
else
|
||||
return d->context->toImage(rect);
|
||||
}
|
||||
|
||||
return QImage();
|
||||
if (!d->context)
|
||||
return QImage();
|
||||
|
||||
const QRectF &rectSource = rect.isEmpty() ? canvasWindow() : rect;
|
||||
const qreal dpr = window() ? window()->effectiveDevicePixelRatio() : qreal(1);
|
||||
const QRectF rectScaled(rectSource.topLeft() * dpr, rectSource.size() * dpr);
|
||||
|
||||
QImage image = d->context->toImage(rectScaled);
|
||||
image.setDevicePixelRatio(dpr);
|
||||
return image;
|
||||
}
|
||||
|
||||
static const char* mimeToType(const QString &mime)
|
||||
|
|
|
@ -960,7 +960,7 @@ static QV4::ReturnedValue qt_create_image_data(qreal w, qreal h, QV4::ExecutionE
|
|||
*pixelData->d()->image = QImage(w, h, QImage::Format_ARGB32);
|
||||
pixelData->d()->image->fill(0x00000000);
|
||||
} else {
|
||||
Q_ASSERT(image.width() == qRound(w) && image.height() == qRound(h));
|
||||
Q_ASSERT(image.width()== qRound(w * image.devicePixelRatio()) && image.height() == qRound(h * image.devicePixelRatio()));
|
||||
*pixelData->d()->image = image.format() == QImage::Format_ARGB32 ? image : image.convertToFormat(QImage::Format_ARGB32);
|
||||
}
|
||||
|
||||
|
|
|
@ -248,7 +248,7 @@ class QQuickDragAttached : public QObject
|
|||
Q_PROPERTY(QObject *source READ source WRITE setSource NOTIFY sourceChanged RESET resetSource)
|
||||
Q_PROPERTY(QObject *target READ target NOTIFY targetChanged)
|
||||
Q_PROPERTY(QPointF hotSpot READ hotSpot WRITE setHotSpot NOTIFY hotSpotChanged)
|
||||
Q_PROPERTY(QUrl imageSource READ imageSource WRITE setImageSource NOTIFY imageSourceChanged REVISION 8)
|
||||
Q_PROPERTY(QUrl imageSource READ imageSource WRITE setImageSource NOTIFY imageSourceChanged)
|
||||
Q_PROPERTY(QStringList keys READ keys WRITE setKeys NOTIFY keysChanged)
|
||||
Q_PROPERTY(QVariantMap mimeData READ mimeData WRITE setMimeData NOTIFY mimeDataChanged)
|
||||
Q_PROPERTY(Qt::DropActions supportedActions READ supportedActions WRITE setSupportedActions NOTIFY supportedActionsChanged)
|
||||
|
|
|
@ -769,52 +769,8 @@ void QQuickTextControl::processEvent(QEvent *e, const QMatrix &matrix)
|
|||
case QEvent::ShortcutOverride:
|
||||
if (d->interactionFlags & Qt::TextEditable) {
|
||||
QKeyEvent* ke = static_cast<QKeyEvent *>(e);
|
||||
if (ke->modifiers() == Qt::NoModifier
|
||||
|| ke->modifiers() == Qt::ShiftModifier
|
||||
|| ke->modifiers() == Qt::KeypadModifier) {
|
||||
if (ke->key() < Qt::Key_Escape) {
|
||||
ke->accept();
|
||||
} else {
|
||||
switch (ke->key()) {
|
||||
case Qt::Key_Return:
|
||||
case Qt::Key_Enter:
|
||||
case Qt::Key_Delete:
|
||||
case Qt::Key_Home:
|
||||
case Qt::Key_End:
|
||||
case Qt::Key_Backspace:
|
||||
case Qt::Key_Left:
|
||||
case Qt::Key_Right:
|
||||
case Qt::Key_Up:
|
||||
case Qt::Key_Down:
|
||||
case Qt::Key_Tab:
|
||||
ke->accept();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#if QT_CONFIG(shortcut)
|
||||
} else if (ke == QKeySequence::Copy
|
||||
|| ke == QKeySequence::Paste
|
||||
|| ke == QKeySequence::Cut
|
||||
|| ke == QKeySequence::Redo
|
||||
|| ke == QKeySequence::Undo
|
||||
|| ke == QKeySequence::MoveToNextWord
|
||||
|| ke == QKeySequence::MoveToPreviousWord
|
||||
|| ke == QKeySequence::MoveToStartOfDocument
|
||||
|| ke == QKeySequence::MoveToEndOfDocument
|
||||
|| ke == QKeySequence::SelectNextWord
|
||||
|| ke == QKeySequence::SelectPreviousWord
|
||||
|| ke == QKeySequence::SelectStartOfLine
|
||||
|| ke == QKeySequence::SelectEndOfLine
|
||||
|| ke == QKeySequence::SelectStartOfBlock
|
||||
|| ke == QKeySequence::SelectEndOfBlock
|
||||
|| ke == QKeySequence::SelectStartOfDocument
|
||||
|| ke == QKeySequence::SelectEndOfDocument
|
||||
|| ke == QKeySequence::SelectAll
|
||||
) {
|
||||
if (isCommonTextEditShortcut(ke))
|
||||
ke->accept();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -419,6 +419,10 @@ void QSGMaterialShader::compile()
|
|||
\value DirtyMatrix Used to indicate that the matrix has changed and must be updated.
|
||||
|
||||
\value DirtyOpacity Used to indicate that the opacity has changed and must be updated.
|
||||
|
||||
\value DirtyCachedMaterialData Used to indicate that the cached material data have changed and must be updated.
|
||||
|
||||
\value DirtyAll Used to indicate that everything needs to be updated.
|
||||
*/
|
||||
|
||||
|
||||
|
|
|
@ -112,6 +112,7 @@ static void qt_print_node_count()
|
|||
\value DirtyGeometry The geometry of a QSGGeometryNode has changed.
|
||||
\value DirtyMaterial The material of a QSGGeometryNode has changed.
|
||||
\value DirtyOpacity The opacity of a QSGOpacityNode has changed.
|
||||
\value DirtySubtreeBlocked The subtree has been blocked.
|
||||
|
||||
\sa QSGNode::markDirty()
|
||||
*/
|
||||
|
@ -146,6 +147,7 @@ static void qt_print_node_count()
|
|||
\value TransformNodeType The type of QSGTransformNode
|
||||
\value ClipNodeType The type of QSGClipNode
|
||||
\value OpacityNodeType The type of QSGOpacityNode
|
||||
\value RenderNodeType The type of QSGRenderNode
|
||||
|
||||
\sa type()
|
||||
*/
|
||||
|
|
|
@ -84,6 +84,8 @@ QT_BEGIN_NAMESPACE
|
|||
will delete the GL texture when the texture object is deleted.
|
||||
|
||||
\value TextureCanUseAtlas The image can be uploaded into a texture atlas.
|
||||
|
||||
\value TextureIsOpaque The texture object is opaque.
|
||||
*/
|
||||
|
||||
QSGEnginePrivate::QSGEnginePrivate()
|
||||
|
|
|
@ -613,7 +613,6 @@ void QQuickImageProviderOptions::setPreserveAspectRatioFit(bool preserveAspectRa
|
|||
d->preserveAspectRatioFit = preserveAspectRatioFit;
|
||||
}
|
||||
|
||||
|
||||
QQuickImageProviderWithOptions::QQuickImageProviderWithOptions(ImageType type, Flags flags)
|
||||
: QQuickAsyncImageProvider()
|
||||
{
|
||||
|
@ -670,5 +669,49 @@ QQuickImageResponse *QQuickImageProviderWithOptions::requestImageResponse(const
|
|||
return requestImageResponse(id, requestedSize);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the recommended scaled image size for loading and storage. This is
|
||||
calculated according to the native pixel size of the image \a originalSize,
|
||||
the requested sourceSize \a requestedSize, the image file format \a format,
|
||||
and \a options. If the calculation otherwise concludes that scaled loading
|
||||
is not recommended, an invalid size is returned.
|
||||
*/
|
||||
QSize QQuickImageProviderWithOptions::loadSize(const QSize &originalSize, const QSize &requestedSize, const QByteArray &format, const QQuickImageProviderOptions &options)
|
||||
{
|
||||
QSize res;
|
||||
if ((requestedSize.width() <= 0 && requestedSize.height() <= 0) || originalSize.isEmpty())
|
||||
return res;
|
||||
|
||||
const bool preserveAspectCropOrFit = options.preserveAspectRatioCrop() || options.preserveAspectRatioFit();
|
||||
const bool force_scale = (format == "svg" || format == "svgz");
|
||||
|
||||
qreal ratio = 0.0;
|
||||
if (requestedSize.width() && (preserveAspectCropOrFit || force_scale || requestedSize.width() < originalSize.width())) {
|
||||
ratio = qreal(requestedSize.width()) / originalSize.width();
|
||||
}
|
||||
if (requestedSize.height() && (preserveAspectCropOrFit || force_scale || requestedSize.height() < originalSize.height())) {
|
||||
qreal hr = qreal(requestedSize.height()) / originalSize.height();
|
||||
if (ratio == 0.0)
|
||||
ratio = hr;
|
||||
else if (!preserveAspectCropOrFit && (hr < ratio))
|
||||
ratio = hr;
|
||||
else if (preserveAspectCropOrFit && (hr > ratio))
|
||||
ratio = hr;
|
||||
}
|
||||
if (ratio > 0.0) {
|
||||
res.setHeight(qRound(originalSize.height() * ratio));
|
||||
res.setWidth(qRound(originalSize.width() * ratio));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
QQuickImageProviderWithOptions *QQuickImageProviderWithOptions::checkedCast(QQuickImageProvider *provider)
|
||||
{
|
||||
if (provider && provider->d && provider->d->isProviderWithOptions)
|
||||
return static_cast<QQuickImageProviderWithOptions *>(provider);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
|
|
|
@ -88,7 +88,6 @@ Q_SIGNALS:
|
|||
class Q_QUICK_EXPORT QQuickImageProvider : public QQmlImageProviderBase
|
||||
{
|
||||
friend class QQuickImageProviderWithOptions; // ### Qt 6 Remove
|
||||
friend class QQuickPixmapReader; // ### Qt 6 Remove
|
||||
public:
|
||||
QQuickImageProvider(ImageType type, Flags flags = Flags());
|
||||
virtual ~QQuickImageProvider();
|
||||
|
|
|
@ -141,6 +141,7 @@ public:
|
|||
QUrl url;
|
||||
|
||||
bool loading;
|
||||
QQuickImageProviderOptions providerOptions;
|
||||
int redirectCount;
|
||||
|
||||
class Event : public QEvent {
|
||||
|
@ -204,7 +205,7 @@ protected:
|
|||
private:
|
||||
friend class QQuickPixmapReaderThreadObject;
|
||||
void processJobs();
|
||||
void processJob(QQuickPixmapReply *, const QUrl &, const QString &, const QQuickImageProviderOptions &, QQuickImageProvider::ImageType, QQuickImageProvider *);
|
||||
void processJob(QQuickPixmapReply *, const QUrl &, const QString &, QQuickImageProvider::ImageType, QQuickImageProvider *);
|
||||
#if QT_CONFIG(qml_network)
|
||||
void networkRequestDone(QNetworkReply *);
|
||||
#endif
|
||||
|
@ -386,37 +387,15 @@ static bool readImage(const QUrl& url, QIODevice *dev, QImage *image, QString *e
|
|||
const QSize &requestSize, const QQuickImageProviderOptions &providerOptions,
|
||||
QQuickImageProviderOptions::AutoTransform *appliedTransform = nullptr)
|
||||
{
|
||||
const bool preserveAspectCropOrFit = providerOptions.preserveAspectRatioCrop() || providerOptions.preserveAspectRatioFit();
|
||||
|
||||
QImageReader imgio(dev);
|
||||
if (providerOptions.autoTransform() != QQuickImageProviderOptions::UsePluginDefaultTransform)
|
||||
imgio.setAutoTransform(providerOptions.autoTransform() == QQuickImageProviderOptions::ApplyTransform);
|
||||
else if (appliedTransform)
|
||||
*appliedTransform = imgio.autoTransform() ? QQuickImageProviderOptions::ApplyTransform : QQuickImageProviderOptions::DoNotApplyTransform;
|
||||
|
||||
const bool force_scale = imgio.format() == "svg" || imgio.format() == "svgz";
|
||||
|
||||
if (requestSize.width() > 0 || requestSize.height() > 0) {
|
||||
QSize s = imgio.size();
|
||||
qreal ratio = 0.0;
|
||||
if (requestSize.width() && (preserveAspectCropOrFit || force_scale || requestSize.width() < s.width())) {
|
||||
ratio = qreal(requestSize.width())/s.width();
|
||||
}
|
||||
if (requestSize.height() && (preserveAspectCropOrFit || force_scale || requestSize.height() < s.height())) {
|
||||
qreal hr = qreal(requestSize.height())/s.height();
|
||||
if (ratio == 0.0)
|
||||
ratio = hr;
|
||||
else if (!preserveAspectCropOrFit && (hr < ratio))
|
||||
ratio = hr;
|
||||
else if (preserveAspectCropOrFit && (hr > ratio))
|
||||
ratio = hr;
|
||||
}
|
||||
if (ratio > 0.0) {
|
||||
s.setHeight(qRound(s.height() * ratio));
|
||||
s.setWidth(qRound(s.width() * ratio));
|
||||
imgio.setScaledSize(s);
|
||||
}
|
||||
}
|
||||
QSize scSize = QQuickImageProviderWithOptions::loadSize(imgio.size(), requestSize, imgio.format(), providerOptions);
|
||||
if (scSize.isValid())
|
||||
imgio.setScaledSize(scSize);
|
||||
|
||||
if (impsize)
|
||||
*impsize = imgio.size();
|
||||
|
@ -664,7 +643,7 @@ void QQuickPixmapReader::processJobs()
|
|||
PIXMAP_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingStarted>(url));
|
||||
|
||||
locker.unlock();
|
||||
processJob(job, url, localFile, job->data->providerOptions, imageType, provider);
|
||||
processJob(job, url, localFile, imageType, provider);
|
||||
locker.relock();
|
||||
}
|
||||
}
|
||||
|
@ -676,7 +655,6 @@ void QQuickPixmapReader::processJobs()
|
|||
}
|
||||
|
||||
void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &url, const QString &localFile,
|
||||
const QQuickImageProviderOptions &providerOptions,
|
||||
QQuickImageProvider::ImageType imageType, QQuickImageProvider *provider)
|
||||
{
|
||||
// fetch
|
||||
|
@ -693,8 +671,7 @@ void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &u
|
|||
return;
|
||||
}
|
||||
|
||||
QQuickImageProviderWithOptions *providerV2 = provider->d->isProviderWithOptions ? static_cast<QQuickImageProviderWithOptions *>(provider)
|
||||
: nullptr;
|
||||
QQuickImageProviderWithOptions *providerV2 = QQuickImageProviderWithOptions::checkedCast(provider);
|
||||
|
||||
switch (imageType) {
|
||||
case QQuickImageProvider::Invalid:
|
||||
|
@ -707,7 +684,7 @@ void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &u
|
|||
{
|
||||
QImage image;
|
||||
if (providerV2) {
|
||||
image = providerV2->requestImage(imageId(url), &readSize, runningJob->requestSize, providerOptions);
|
||||
image = providerV2->requestImage(imageId(url), &readSize, runningJob->requestSize, runningJob->providerOptions);
|
||||
} else {
|
||||
image = provider->requestImage(imageId(url), &readSize, runningJob->requestSize);
|
||||
}
|
||||
|
@ -728,7 +705,7 @@ void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &u
|
|||
{
|
||||
QPixmap pixmap;
|
||||
if (providerV2) {
|
||||
pixmap = providerV2->requestPixmap(imageId(url), &readSize, runningJob->requestSize, providerOptions);
|
||||
pixmap = providerV2->requestPixmap(imageId(url), &readSize, runningJob->requestSize, runningJob->providerOptions);
|
||||
} else {
|
||||
pixmap = provider->requestPixmap(imageId(url), &readSize, runningJob->requestSize);
|
||||
}
|
||||
|
@ -749,7 +726,7 @@ void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &u
|
|||
{
|
||||
QQuickTextureFactory *t;
|
||||
if (providerV2) {
|
||||
t = providerV2->requestTexture(imageId(url), &readSize, runningJob->requestSize, providerOptions);
|
||||
t = providerV2->requestTexture(imageId(url), &readSize, runningJob->requestSize, runningJob->providerOptions);
|
||||
} else {
|
||||
t = provider->requestTexture(imageId(url), &readSize, runningJob->requestSize);
|
||||
}
|
||||
|
@ -772,7 +749,7 @@ void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &u
|
|||
{
|
||||
QQuickImageResponse *response;
|
||||
if (providerV2) {
|
||||
response = providerV2->requestImageResponse(imageId(url), runningJob->requestSize, providerOptions);
|
||||
response = providerV2->requestImageResponse(imageId(url), runningJob->requestSize, runningJob->providerOptions);
|
||||
} else {
|
||||
QQuickAsyncImageProvider *asyncProvider = static_cast<QQuickAsyncImageProvider*>(provider);
|
||||
response = asyncProvider->requestImageResponse(imageId(url), runningJob->requestSize);
|
||||
|
@ -794,7 +771,7 @@ void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &u
|
|||
QFile f(localFile);
|
||||
QSize readSize;
|
||||
if (f.open(QIODevice::ReadOnly)) {
|
||||
if (!readImage(url, &f, &image, &errorStr, &readSize, runningJob->requestSize, providerOptions))
|
||||
if (!readImage(url, &f, &image, &errorStr, &readSize, runningJob->requestSize, runningJob->providerOptions))
|
||||
errorCode = QQuickPixmapReply::Loading;
|
||||
} else {
|
||||
errorStr = QQuickPixmap::tr("Cannot open: %1").arg(url.toString());
|
||||
|
@ -1075,7 +1052,7 @@ void QQuickPixmap::purgeCache()
|
|||
}
|
||||
|
||||
QQuickPixmapReply::QQuickPixmapReply(QQuickPixmapData *d)
|
||||
: data(d), engineForReader(0), requestSize(d->requestSize), url(d->url), loading(false), redirectCount(0)
|
||||
: data(d), engineForReader(0), requestSize(d->requestSize), url(d->url), loading(false), providerOptions(d->providerOptions), redirectCount(0)
|
||||
{
|
||||
if (finishedIndex == -1) {
|
||||
finishedIndex = QMetaMethod::fromSignal(&QQuickPixmapReply::finished).methodIndex();
|
||||
|
@ -1196,6 +1173,7 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q
|
|||
|
||||
QQuickImageProvider::ImageType imageType = QQuickImageProvider::Invalid;
|
||||
QQuickImageProvider *provider = static_cast<QQuickImageProvider *>(engine->imageProvider(imageProviderId(url)));
|
||||
QQuickImageProviderWithOptions *providerV2 = QQuickImageProviderWithOptions::checkedCast(provider);
|
||||
if (provider)
|
||||
imageType = provider->imageType();
|
||||
|
||||
|
@ -1205,7 +1183,8 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q
|
|||
QQuickPixmap::tr("Invalid image provider: %1").arg(url.toString()));
|
||||
case QQuickImageProvider::Texture:
|
||||
{
|
||||
QQuickTextureFactory *texture = provider->requestTexture(imageId(url), &readSize, requestSize);
|
||||
QQuickTextureFactory *texture = providerV2 ? providerV2->requestTexture(imageId(url), &readSize, requestSize, providerOptions)
|
||||
: provider->requestTexture(imageId(url), &readSize, requestSize);
|
||||
if (texture) {
|
||||
*ok = true;
|
||||
return new QQuickPixmapData(declarativePixmap, url, texture, readSize, requestSize, providerOptions, QQuickImageProviderOptions::UsePluginDefaultTransform);
|
||||
|
@ -1215,7 +1194,8 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q
|
|||
|
||||
case QQuickImageProvider::Image:
|
||||
{
|
||||
QImage image = provider->requestImage(imageId(url), &readSize, requestSize);
|
||||
QImage image = providerV2 ? providerV2->requestImage(imageId(url), &readSize, requestSize, providerOptions)
|
||||
: provider->requestImage(imageId(url), &readSize, requestSize);
|
||||
if (!image.isNull()) {
|
||||
*ok = true;
|
||||
return new QQuickPixmapData(declarativePixmap, url, QQuickTextureFactory::textureFactoryForImage(image), readSize, requestSize, providerOptions, QQuickImageProviderOptions::UsePluginDefaultTransform);
|
||||
|
@ -1224,7 +1204,8 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q
|
|||
}
|
||||
case QQuickImageProvider::Pixmap:
|
||||
{
|
||||
QPixmap pixmap = provider->requestPixmap(imageId(url), &readSize, requestSize);
|
||||
QPixmap pixmap = providerV2 ? providerV2->requestPixmap(imageId(url), &readSize, requestSize, providerOptions)
|
||||
: provider->requestPixmap(imageId(url), &readSize, requestSize);
|
||||
if (!pixmap.isNull()) {
|
||||
*ok = true;
|
||||
return new QQuickPixmapData(declarativePixmap, url, QQuickTextureFactory::textureFactoryForImage(pixmap.toImage()), readSize, requestSize, providerOptions, QQuickImageProviderOptions::UsePluginDefaultTransform);
|
||||
|
|
|
@ -204,6 +204,9 @@ public:
|
|||
virtual QPixmap requestPixmap(const QString &id, QSize *size, const QSize& requestedSize, const QQuickImageProviderOptions &options);
|
||||
virtual QQuickTextureFactory *requestTexture(const QString &id, QSize *size, const QSize &requestedSize, const QQuickImageProviderOptions &options);
|
||||
virtual QQuickImageResponse *requestImageResponse(const QString &id, const QSize &requestedSize, const QQuickImageProviderOptions &options);
|
||||
|
||||
static QSize loadSize(const QSize &originalSize, const QSize &requestedSize, const QByteArray &format, const QQuickImageProviderOptions &options);
|
||||
static QQuickImageProviderWithOptions *checkedCast(QQuickImageProvider *provider);
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
@ -157,6 +157,16 @@ void QQuickWidgetPrivate::invalidateRenderControl()
|
|||
#endif
|
||||
|
||||
renderControl->invalidate();
|
||||
|
||||
// Many things can happen inside the above invalidate() call, including a
|
||||
// change of current context. Restore if needed since some code will rely
|
||||
// on the fact that this function makes and leaves the context current.
|
||||
#if QT_CONFIG(opengl)
|
||||
if (!useSoftwareRenderer && context) {
|
||||
if (QOpenGLContext::currentContext() != context)
|
||||
context->makeCurrent(offscreenSurface);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void QQuickWidgetPrivate::handleWindowChange()
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2017 reMarkable A/S
|
||||
** Contact: http://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the test suite of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL21$
|
||||
** 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 The Qt Company. For licensing terms
|
||||
** and conditions see http://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free
|
||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||
** following information to ensure the GNU Lesser General Public License
|
||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** As a special exception, The Qt Company gives you certain additional
|
||||
** rights. These rights are described in The Qt Company LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.6
|
||||
import QtQuick.Particles 2.0
|
||||
|
||||
ParticleSystem {
|
||||
running: false
|
||||
Affector { Component.onCompleted: destroy() }
|
||||
Emitter {
|
||||
Timer { interval: 1; running: true; onTriggered: parent.lifeSpan = 1 }
|
||||
}
|
||||
}
|
|
@ -42,6 +42,7 @@ public:
|
|||
private slots:
|
||||
void initTestCase();
|
||||
void test_basic();
|
||||
void test_affectorscrash();
|
||||
};
|
||||
|
||||
void tst_qquickparticlesystem::initTestCase()
|
||||
|
@ -78,6 +79,12 @@ void tst_qquickparticlesystem::test_basic()
|
|||
delete view;
|
||||
QVERIFY(extremelyFuzzyCompare(stillAlive, 500, 5));//Small simulation variance is permissible.
|
||||
}
|
||||
void tst_qquickparticlesystem::test_affectorscrash()
|
||||
{
|
||||
QScopedPointer<QQuickView> view (createView(testFileUrl("crashaffectors.qml"), 600));
|
||||
|
||||
// This should have crashed by now
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_qquickparticlesystem);
|
||||
|
||||
|
|
|
@ -180,14 +180,9 @@ void tst_QQmlEngineDebugService::recursiveObjectTest(
|
|||
{
|
||||
const QMetaObject *meta = o->metaObject();
|
||||
|
||||
QQmlType *type = QQmlMetaType::qmlType(meta);
|
||||
QString className = type ? QString(type->qmlTypeName())
|
||||
: QString(meta->className());
|
||||
className = className.mid(className.lastIndexOf(QLatin1Char('/'))+1);
|
||||
|
||||
QCOMPARE(oref.debugId, QQmlDebugService::idForObject(o));
|
||||
QCOMPARE(oref.name, o->objectName());
|
||||
QCOMPARE(oref.className, className);
|
||||
QCOMPARE(oref.className, QQmlMetaType::prettyTypeName(o));
|
||||
QCOMPARE(oref.contextDebugId, QQmlDebugService::idForObject(
|
||||
qmlContext(o)));
|
||||
|
||||
|
@ -201,6 +196,7 @@ void tst_QQmlEngineDebugService::recursiveObjectTest(
|
|||
|
||||
QmlDebugObjectReference cref;
|
||||
foreach (const QmlDebugObjectReference &ref, oref.children) {
|
||||
QVERIFY(!ref.className.isEmpty());
|
||||
if (ref.debugId == debugId) {
|
||||
cref = ref;
|
||||
break;
|
||||
|
@ -369,6 +365,7 @@ void tst_QQmlEngineDebugService::setMethodBody()
|
|||
{
|
||||
bool success;
|
||||
QmlDebugObjectReference obj = findRootObject(2);
|
||||
QVERIFY(!obj.className.isEmpty());
|
||||
|
||||
QObject *root = m_components.at(2);
|
||||
// Without args
|
||||
|
@ -410,6 +407,7 @@ void tst_QQmlEngineDebugService::setMethodBody()
|
|||
void tst_QQmlEngineDebugService::watch_property()
|
||||
{
|
||||
QmlDebugObjectReference obj = findRootObject();
|
||||
QVERIFY(!obj.className.isEmpty());
|
||||
QmlDebugPropertyReference prop = findProperty(obj.properties, "width");
|
||||
|
||||
bool success;
|
||||
|
@ -454,6 +452,7 @@ void tst_QQmlEngineDebugService::watch_property()
|
|||
void tst_QQmlEngineDebugService::watch_object()
|
||||
{
|
||||
QmlDebugObjectReference obj = findRootObject();
|
||||
QVERIFY(!obj.className.isEmpty());
|
||||
|
||||
bool success;
|
||||
|
||||
|
@ -519,6 +518,7 @@ void tst_QQmlEngineDebugService::watch_expression()
|
|||
int origWidth = m_rootItem->property("width").toInt();
|
||||
|
||||
QmlDebugObjectReference obj = findRootObject();
|
||||
QVERIFY(!obj.className.isEmpty());
|
||||
|
||||
bool success;
|
||||
|
||||
|
@ -654,6 +654,7 @@ void tst_QQmlEngineDebugService::queryObject()
|
|||
bool success;
|
||||
|
||||
QmlDebugObjectReference rootObject = findRootObject();
|
||||
QVERIFY(!rootObject.className.isEmpty());
|
||||
|
||||
QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(0);
|
||||
recursive ? unconnected->queryObjectRecursive(rootObject, &success) : unconnected->queryObject(rootObject, &success);
|
||||
|
@ -665,6 +666,7 @@ void tst_QQmlEngineDebugService::queryObject()
|
|||
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
||||
|
||||
QmlDebugObjectReference obj = m_dbg->object();
|
||||
QVERIFY(!obj.className.isEmpty());
|
||||
|
||||
// check source as defined in main()
|
||||
QmlDebugFileReference source = obj.source;
|
||||
|
@ -676,12 +678,15 @@ void tst_QQmlEngineDebugService::queryObject()
|
|||
recursiveObjectTest(m_rootItem, obj, recursive);
|
||||
|
||||
if (recursive) {
|
||||
foreach (const QmlDebugObjectReference &child, obj.children)
|
||||
foreach (const QmlDebugObjectReference &child, obj.children) {
|
||||
QVERIFY(!child.className.isEmpty());
|
||||
QVERIFY(child.properties.count() > 0);
|
||||
}
|
||||
|
||||
QmlDebugObjectReference rect;
|
||||
QmlDebugObjectReference text;
|
||||
foreach (const QmlDebugObjectReference &child, obj.children) {
|
||||
QVERIFY(!child.className.isEmpty());
|
||||
if (child.className == "Rectangle")
|
||||
rect = child;
|
||||
else if (child.className == "Text")
|
||||
|
@ -695,8 +700,10 @@ void tst_QQmlEngineDebugService::queryObject()
|
|||
|
||||
QCOMPARE(findProperty(text.properties, "color").value, qVariantFromValue(QColor("blue")));
|
||||
} else {
|
||||
foreach (const QmlDebugObjectReference &child, obj.children)
|
||||
foreach (const QmlDebugObjectReference &child, obj.children) {
|
||||
QVERIFY(!child.className.isEmpty());
|
||||
QCOMPARE(child.properties.count(), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -715,6 +722,7 @@ void tst_QQmlEngineDebugService::queryObjectsForLocation()
|
|||
bool success;
|
||||
|
||||
QmlDebugObjectReference rootObject = findRootObject();
|
||||
QVERIFY(!rootObject.className.isEmpty());
|
||||
|
||||
const QString fileName = QFileInfo(rootObject.source.url.toString()).fileName();
|
||||
int lineNumber = rootObject.source.lineNumber;
|
||||
|
@ -737,6 +745,7 @@ void tst_QQmlEngineDebugService::queryObjectsForLocation()
|
|||
|
||||
QCOMPARE(m_dbg->objects().count(), 1);
|
||||
QmlDebugObjectReference obj = m_dbg->objects().first();
|
||||
QVERIFY(!obj.className.isEmpty());
|
||||
|
||||
// check source as defined in main()
|
||||
QmlDebugFileReference source = obj.source;
|
||||
|
@ -748,12 +757,15 @@ void tst_QQmlEngineDebugService::queryObjectsForLocation()
|
|||
recursiveObjectTest(m_rootItem, obj, recursive);
|
||||
|
||||
if (recursive) {
|
||||
foreach (const QmlDebugObjectReference &child, obj.children)
|
||||
foreach (const QmlDebugObjectReference &child, obj.children) {
|
||||
QVERIFY(!child.className.isEmpty());
|
||||
QVERIFY(child.properties.count() > 0);
|
||||
}
|
||||
|
||||
QmlDebugObjectReference rect;
|
||||
QmlDebugObjectReference text;
|
||||
foreach (const QmlDebugObjectReference &child, obj.children) {
|
||||
QVERIFY(!child.className.isEmpty());
|
||||
if (child.className == "Rectangle")
|
||||
rect = child;
|
||||
else if (child.className == "Text")
|
||||
|
@ -767,8 +779,10 @@ void tst_QQmlEngineDebugService::queryObjectsForLocation()
|
|||
|
||||
QCOMPARE(findProperty(text.properties, "color").value, qVariantFromValue(QColor("blue")));
|
||||
} else {
|
||||
foreach (const QmlDebugObjectReference &child, obj.children)
|
||||
foreach (const QmlDebugObjectReference &child, obj.children) {
|
||||
QVERIFY(!child.className.isEmpty());
|
||||
QCOMPARE(child.properties.count(), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -783,6 +797,7 @@ void tst_QQmlEngineDebugService::queryObjectsForLocation_data()
|
|||
void tst_QQmlEngineDebugService::regression_QTCREATORBUG_7451()
|
||||
{
|
||||
QmlDebugObjectReference rootObject = findRootObject();
|
||||
QVERIFY(!rootObject.className.isEmpty());
|
||||
int contextId = rootObject.contextDebugId;
|
||||
QQmlContext *context = qobject_cast<QQmlContext *>(QQmlDebugService::objectForId(contextId));
|
||||
QQmlComponent component(context->engine());
|
||||
|
@ -809,6 +824,7 @@ void tst_QQmlEngineDebugService::regression_QTCREATORBUG_7451()
|
|||
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
||||
|
||||
foreach (QmlDebugObjectReference child, rootObject.children) {
|
||||
QVERIFY(!child.className.isEmpty());
|
||||
success = false;
|
||||
lineNumber = child.source.lineNumber;
|
||||
columnNumber = child.source.columnNumber;
|
||||
|
@ -831,6 +847,7 @@ void tst_QQmlEngineDebugService::regression_QTCREATORBUG_7451()
|
|||
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
||||
|
||||
foreach (QmlDebugObjectReference child, rootObject.children) {
|
||||
QVERIFY(!child.className.isEmpty());
|
||||
success = false;
|
||||
lineNumber = child.source.lineNumber;
|
||||
columnNumber = child.source.columnNumber;
|
||||
|
@ -846,6 +863,7 @@ void tst_QQmlEngineDebugService::queryObjectWithNonStreamableTypes()
|
|||
bool success;
|
||||
|
||||
QmlDebugObjectReference rootObject = findRootObject(4, true);
|
||||
QVERIFY(!rootObject.className.isEmpty());
|
||||
|
||||
QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(0);
|
||||
unconnected->queryObject(rootObject, &success);
|
||||
|
@ -857,6 +875,7 @@ void tst_QQmlEngineDebugService::queryObjectWithNonStreamableTypes()
|
|||
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
||||
|
||||
QmlDebugObjectReference obj = m_dbg->object();
|
||||
QVERIFY(!obj.className.isEmpty());
|
||||
|
||||
QCOMPARE(findProperty(obj.properties, "modelIndex").value, QVariant());
|
||||
}
|
||||
|
@ -950,6 +969,7 @@ void tst_QQmlEngineDebugService::queryExpressionResultBC_data()
|
|||
void tst_QQmlEngineDebugService::setBindingForObject()
|
||||
{
|
||||
QmlDebugObjectReference rootObject = findRootObject();
|
||||
QVERIFY(!rootObject.className.isEmpty());
|
||||
QVERIFY(rootObject.debugId != -1);
|
||||
QmlDebugPropertyReference widthPropertyRef = findProperty(rootObject.properties, "width");
|
||||
|
||||
|
@ -967,6 +987,7 @@ void tst_QQmlEngineDebugService::setBindingForObject()
|
|||
QCOMPARE(m_dbg->valid(), true);
|
||||
|
||||
rootObject = findRootObject();
|
||||
QVERIFY(!rootObject.className.isEmpty());
|
||||
widthPropertyRef = findProperty(rootObject.properties, "width");
|
||||
|
||||
QCOMPARE(widthPropertyRef.value, QVariant(15));
|
||||
|
@ -982,6 +1003,7 @@ void tst_QQmlEngineDebugService::setBindingForObject()
|
|||
QCOMPARE(m_dbg->valid(), true);
|
||||
|
||||
rootObject = findRootObject();
|
||||
QVERIFY(!rootObject.className.isEmpty());
|
||||
widthPropertyRef = findProperty(rootObject.properties, "width");
|
||||
|
||||
QCOMPARE(widthPropertyRef.value, QVariant(20));
|
||||
|
@ -992,13 +1014,14 @@ void tst_QQmlEngineDebugService::setBindingForObject()
|
|||
// set handler
|
||||
//
|
||||
rootObject = findRootObject();
|
||||
QVERIFY(!rootObject.className.isEmpty());
|
||||
QCOMPARE(rootObject.children.size(), 5); // Rectangle, Text, MouseArea, Component.onCompleted, NonScriptPropertyElement
|
||||
QmlDebugObjectReference mouseAreaObject = rootObject.children.at(2);
|
||||
QVERIFY(!mouseAreaObject.className.isEmpty());
|
||||
m_dbg->queryObjectRecursive(mouseAreaObject, &success);
|
||||
QVERIFY(success);
|
||||
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
||||
mouseAreaObject = m_dbg->object();
|
||||
|
||||
QCOMPARE(mouseAreaObject.className, QString("MouseArea"));
|
||||
|
||||
QmlDebugPropertyReference onEnteredRef = findProperty(mouseAreaObject.properties, "onEntered");
|
||||
|
@ -1015,11 +1038,14 @@ void tst_QQmlEngineDebugService::setBindingForObject()
|
|||
QCOMPARE(m_dbg->valid(), true);
|
||||
|
||||
rootObject = findRootObject();
|
||||
QVERIFY(!rootObject.className.isEmpty());
|
||||
mouseAreaObject = rootObject.children.at(2);
|
||||
QVERIFY(!mouseAreaObject.className.isEmpty());
|
||||
m_dbg->queryObjectRecursive(mouseAreaObject, &success);
|
||||
QVERIFY(success);
|
||||
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
||||
mouseAreaObject = m_dbg->object();
|
||||
QVERIFY(!mouseAreaObject.className.isEmpty());
|
||||
onEnteredRef = findProperty(mouseAreaObject.properties, "onEntered");
|
||||
QCOMPARE(onEnteredRef.name, QString("onEntered"));
|
||||
QCOMPARE(onEnteredRef.value, QVariant("function() { [code] }"));
|
||||
|
@ -1028,6 +1054,7 @@ void tst_QQmlEngineDebugService::setBindingForObject()
|
|||
void tst_QQmlEngineDebugService::resetBindingForObject()
|
||||
{
|
||||
QmlDebugObjectReference rootObject = findRootObject();
|
||||
QVERIFY(!rootObject.className.isEmpty());
|
||||
QVERIFY(rootObject.debugId != -1);
|
||||
QmlDebugPropertyReference widthPropertyRef = findProperty(rootObject.properties, "width");
|
||||
|
||||
|
@ -1048,6 +1075,7 @@ void tst_QQmlEngineDebugService::resetBindingForObject()
|
|||
QCOMPARE(m_dbg->valid(), true);
|
||||
|
||||
rootObject = findRootObject();
|
||||
QVERIFY(!rootObject.className.isEmpty());
|
||||
widthPropertyRef = findProperty(rootObject.properties, "width");
|
||||
|
||||
QCOMPARE(widthPropertyRef.value, QVariant(0));
|
||||
|
@ -1063,6 +1091,7 @@ void tst_QQmlEngineDebugService::resetBindingForObject()
|
|||
QCOMPARE(m_dbg->valid(), true);
|
||||
|
||||
rootObject = findRootObject();
|
||||
QVERIFY(!rootObject.className.isEmpty());
|
||||
QmlDebugPropertyReference boldPropertyRef = findProperty(rootObject.properties, "font.bold");
|
||||
|
||||
QCOMPARE(boldPropertyRef.value.toBool(), false);
|
||||
|
@ -1076,7 +1105,7 @@ void tst_QQmlEngineDebugService::setBindingInStates()
|
|||
const int sourceIndex = 3;
|
||||
|
||||
QmlDebugObjectReference obj = findRootObject(sourceIndex);
|
||||
|
||||
QVERIFY(!obj.className.isEmpty());
|
||||
QVERIFY(obj.debugId != -1);
|
||||
QVERIFY(obj.children.count() >= 2);
|
||||
bool success;
|
||||
|
@ -1092,6 +1121,7 @@ void tst_QQmlEngineDebugService::setBindingInStates()
|
|||
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
||||
|
||||
obj = findRootObject(sourceIndex);
|
||||
QVERIFY(!obj.className.isEmpty());
|
||||
QCOMPARE(findProperty(obj.properties,"width").value.toInt(),200);
|
||||
|
||||
|
||||
|
@ -1102,6 +1132,7 @@ void tst_QQmlEngineDebugService::setBindingInStates()
|
|||
|
||||
|
||||
obj = findRootObject(sourceIndex, true);
|
||||
QVERIFY(!obj.className.isEmpty());
|
||||
QCOMPARE(findProperty(obj.properties,"width").value.toInt(),100);
|
||||
|
||||
|
||||
|
@ -1111,6 +1142,7 @@ void tst_QQmlEngineDebugService::setBindingInStates()
|
|||
QVERIFY(state.children.count() > 0);
|
||||
|
||||
QmlDebugObjectReference propertyChange = state.children[0];
|
||||
QVERIFY(!propertyChange.className.isEmpty());
|
||||
QVERIFY(propertyChange.debugId != -1);
|
||||
|
||||
m_dbg->setBindingForObject(propertyChange.debugId, "width",QVariant(300),true,
|
||||
|
@ -1120,6 +1152,7 @@ void tst_QQmlEngineDebugService::setBindingInStates()
|
|||
|
||||
// check properties changed in state
|
||||
obj = findRootObject(sourceIndex);
|
||||
QVERIFY(!obj.className.isEmpty());
|
||||
QCOMPARE(findProperty(obj.properties,"width").value.toInt(),100);
|
||||
|
||||
|
||||
|
@ -1128,6 +1161,7 @@ void tst_QQmlEngineDebugService::setBindingInStates()
|
|||
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
||||
|
||||
obj = findRootObject(sourceIndex);
|
||||
QVERIFY(!obj.className.isEmpty());
|
||||
QCOMPARE(findProperty(obj.properties,"width").value.toInt(),300);
|
||||
|
||||
// check changing properties of base state from within a state
|
||||
|
@ -1141,6 +1175,7 @@ void tst_QQmlEngineDebugService::setBindingInStates()
|
|||
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
||||
|
||||
obj = findRootObject(sourceIndex);
|
||||
QVERIFY(!obj.className.isEmpty());
|
||||
QCOMPARE(findProperty(obj.properties,"width").value.toInt(),300);
|
||||
|
||||
m_dbg->queryExpressionResult(obj.debugId,QString("state=\"\""), &success);
|
||||
|
@ -1148,6 +1183,7 @@ void tst_QQmlEngineDebugService::setBindingInStates()
|
|||
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
||||
|
||||
obj = findRootObject(sourceIndex);
|
||||
QVERIFY(!obj.className.isEmpty());
|
||||
QCOMPARE(findProperty(obj.properties,"width").value.toInt(), 400);
|
||||
|
||||
// reset binding while in a state
|
||||
|
@ -1156,6 +1192,7 @@ void tst_QQmlEngineDebugService::setBindingInStates()
|
|||
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
|
||||
|
||||
obj = findRootObject(sourceIndex);
|
||||
QVERIFY(!obj.className.isEmpty());
|
||||
QCOMPARE(findProperty(obj.properties,"width").value.toInt(), 300);
|
||||
|
||||
m_dbg->resetBindingForObject(propertyChange.debugId, "width", &success);
|
||||
|
@ -1164,6 +1201,7 @@ void tst_QQmlEngineDebugService::setBindingInStates()
|
|||
QCOMPARE(m_dbg->valid(), true);
|
||||
|
||||
obj = findRootObject(sourceIndex);
|
||||
QVERIFY(!obj.className.isEmpty());
|
||||
QCOMPARE(findProperty(obj.properties,"width").value.toInt(), 400);
|
||||
|
||||
// re-add binding
|
||||
|
@ -1174,6 +1212,7 @@ void tst_QQmlEngineDebugService::setBindingInStates()
|
|||
QCOMPARE(m_dbg->valid(), true);
|
||||
|
||||
obj = findRootObject(sourceIndex);
|
||||
QVERIFY(!obj.className.isEmpty());
|
||||
QCOMPARE(findProperty(obj.properties,"width").value.toInt(), 300);
|
||||
}
|
||||
|
||||
|
@ -1182,7 +1221,7 @@ void tst_QQmlEngineDebugService::queryObjectTree()
|
|||
const int sourceIndex = 3;
|
||||
|
||||
QmlDebugObjectReference obj = findRootObject(sourceIndex, true);
|
||||
|
||||
QVERIFY(!obj.className.isEmpty());
|
||||
QVERIFY(obj.debugId != -1);
|
||||
QVERIFY(obj.children.count() >= 2);
|
||||
|
||||
|
@ -1192,16 +1231,16 @@ void tst_QQmlEngineDebugService::queryObjectTree()
|
|||
QVERIFY(state.children.count() > 0);
|
||||
|
||||
QmlDebugObjectReference propertyChange = state.children[0];
|
||||
QVERIFY(!propertyChange.className.isEmpty());
|
||||
QVERIFY(propertyChange.debugId != -1);
|
||||
|
||||
QmlDebugPropertyReference propertyChangeTarget = findProperty(propertyChange.properties,"target");
|
||||
QCOMPARE(propertyChangeTarget.objectDebugId, propertyChange.debugId);
|
||||
|
||||
QmlDebugObjectReference targetReference = qvariant_cast<QmlDebugObjectReference>(propertyChangeTarget.value);
|
||||
QVERIFY(!targetReference.className.isEmpty());
|
||||
QVERIFY(targetReference.debugId != -1);
|
||||
|
||||
|
||||
|
||||
// check transition
|
||||
QmlDebugObjectReference transition = obj.children[0];
|
||||
QCOMPARE(transition.className, QString("Transition"));
|
||||
|
@ -1210,12 +1249,14 @@ void tst_QQmlEngineDebugService::queryObjectTree()
|
|||
QVERIFY(transition.children.count() > 0);
|
||||
|
||||
QmlDebugObjectReference animation = transition.children[0];
|
||||
QVERIFY(!animation.className.isEmpty());
|
||||
QVERIFY(animation.debugId != -1);
|
||||
|
||||
QmlDebugPropertyReference animationTarget = findProperty(animation.properties,"target");
|
||||
QCOMPARE(animationTarget.objectDebugId, animation.debugId);
|
||||
|
||||
targetReference = qvariant_cast<QmlDebugObjectReference>(animationTarget.value);
|
||||
QVERIFY(!targetReference.className.isEmpty());
|
||||
QVERIFY(targetReference.debugId != -1);
|
||||
|
||||
QCOMPARE(findProperty(animation.properties,"property").value.toString(), QString("width"));
|
||||
|
|
|
@ -315,8 +315,8 @@ private slots:
|
|||
void stepToEndOfScript_data() { redundancy_data(); }
|
||||
void stepToEndOfScript();
|
||||
|
||||
void lastLineOfLoop_data();
|
||||
void lastLineOfLoop();
|
||||
void lastLineOfConditional_data();
|
||||
void lastLineOfConditional();
|
||||
private:
|
||||
QV4Debugger *debugger() const
|
||||
{
|
||||
|
@ -801,32 +801,60 @@ void tst_qv4debugger::stepToEndOfScript()
|
|||
QCOMPARE(state.lineNumber, -4); // A return instruction without proper line number.
|
||||
}
|
||||
|
||||
void tst_qv4debugger::lastLineOfLoop_data()
|
||||
void tst_qv4debugger::lastLineOfConditional_data()
|
||||
{
|
||||
QTest::addColumn<QString>("loopHead");
|
||||
QTest::addColumn<QString>("loopTail");
|
||||
QTest::addColumn<QString>("head");
|
||||
QTest::addColumn<QString>("tail");
|
||||
QTest::addColumn<int>("breakPoint");
|
||||
QTest::addColumn<int>("lastLine");
|
||||
|
||||
QTest::newRow("for") << "for (var i = 0; i < 10; ++i) {\n" << "}\n";
|
||||
QTest::newRow("for..in") << "for (var i in [0, 1, 2, 3, 4]) {\n" << "}\n";
|
||||
QTest::newRow("while") << "while (ret < 10) {\n" << "}\n";
|
||||
QTest::newRow("do..while") << "do {\n" << "} while (ret < 10);\n";
|
||||
QTest::newRow("for {block}") << "for (var i = 0; i < 10; ++i) {\n" << "}" << 4 << 7;
|
||||
QTest::newRow("for..in {block}") << "for (var i in [0, 1, 2, 3, 4]) {\n" << "}" << 4 << 7;
|
||||
QTest::newRow("while {block}") << "while (ret < 10) {\n" << "}" << 4 << 7;
|
||||
QTest::newRow("do..while {block}") << "do {\n" << "} while (ret < 10);" << 4 << 7;
|
||||
|
||||
QTest::newRow("if true {block}") << "if (true) {\n" << "}"
|
||||
<< 4 << 7;
|
||||
QTest::newRow("if false {block}") << "if (false) {\n" << "}"
|
||||
<< 2 << 8;
|
||||
QTest::newRow("if true else {block}") << "if (true) {\n" << "} else {\n ret += 8;\n}"
|
||||
<< 4 << 7;
|
||||
QTest::newRow("if false else {block}") << "if (false) {\n" << "} else {\n ret += 8;\n}"
|
||||
<< 8 << 9;
|
||||
|
||||
QTest::newRow("for statement") << "for (var i = 0; i < 10; ++i)\n" << "" << 4 << 2;
|
||||
QTest::newRow("for..in statement") << "for (var i in [0, 1, 2, 3, 4])\n" << "" << 4 << 2;
|
||||
QTest::newRow("while statement") << "while (ret < 10)\n" << "" << 4 << 2;
|
||||
QTest::newRow("do..while statement") << "do\n" << "while (ret < 10);" << 4 << 7;
|
||||
|
||||
// For two nested if statements without blocks, we need to map the jump from the inner to the
|
||||
// outer one on the outer "if". There is just no better place.
|
||||
QTest::newRow("if true statement") << "if (true)\n" << "" << 4 << 2;
|
||||
QTest::newRow("if false statement") << "if (false)\n" << "" << 2 << 8;
|
||||
|
||||
// Also two nested ifs without blocks.
|
||||
QTest::newRow("if true else statement") << "if (true)\n" << "else\n ret += 8;" << 4 << 2;
|
||||
QTest::newRow("if false else statement") << "if (false)\n" << "else\n ret += 8;" << 8 << 9;
|
||||
}
|
||||
|
||||
void tst_qv4debugger::lastLineOfLoop()
|
||||
void tst_qv4debugger::lastLineOfConditional()
|
||||
{
|
||||
QFETCH(QString, loopHead);
|
||||
QFETCH(QString, loopTail);
|
||||
QFETCH(QString, head);
|
||||
QFETCH(QString, tail);
|
||||
QFETCH(int, breakPoint);
|
||||
QFETCH(int, lastLine);
|
||||
|
||||
QString script =
|
||||
"var ret = 0;\n"
|
||||
+ loopHead +
|
||||
"var ret = 2;\n"
|
||||
+ head +
|
||||
" if (ret == 2)\n"
|
||||
" ret += 4;\n" // breakpoint, then step over
|
||||
" else \n"
|
||||
" else\n"
|
||||
" ret += 1;\n"
|
||||
+ loopTail;
|
||||
+ tail + "\n" +
|
||||
"ret -= 5;";
|
||||
|
||||
debugger()->addBreakPoint("trueBranch", 4);
|
||||
debugger()->addBreakPoint("trueBranch", breakPoint);
|
||||
m_debuggerAgent->m_resumeSpeed = QV4Debugger::StepOver;
|
||||
evaluateJavaScript(script, "trueBranch");
|
||||
QVERIFY(m_debuggerAgent->m_wasPaused);
|
||||
|
@ -834,10 +862,10 @@ void tst_qv4debugger::lastLineOfLoop()
|
|||
QVERIFY(m_debuggerAgent->m_statesWhenPaused.count() > 1);
|
||||
QV4Debugger::ExecutionState firstState = m_debuggerAgent->m_statesWhenPaused.first();
|
||||
QCOMPARE(firstState.fileName, QString("trueBranch"));
|
||||
QCOMPARE(firstState.lineNumber, 4);
|
||||
QCOMPARE(firstState.lineNumber, breakPoint);
|
||||
QV4Debugger::ExecutionState secondState = m_debuggerAgent->m_statesWhenPaused.at(1);
|
||||
QCOMPARE(secondState.fileName, QString("trueBranch"));
|
||||
QCOMPARE(secondState.lineNumber, 7);
|
||||
QCOMPARE(secondState.lineNumber, lastLine);
|
||||
}
|
||||
|
||||
void tst_qv4debugger::redundancy_data()
|
||||
|
|
|
@ -386,6 +386,7 @@ void QQmlEngineDebugClient::decode(QPacket &ds,
|
|||
{
|
||||
QmlDebugObjectReference obj;
|
||||
obj.debugId = prop.value.toInt();
|
||||
obj.className = prop.valueTypeName;
|
||||
prop.value = qVariantFromValue(obj);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ PRIVATETESTS += \
|
|||
qqmlcpputils \
|
||||
qqmldirparser \
|
||||
v4misc \
|
||||
qmlcachegen
|
||||
|
||||
!boot2qt {
|
||||
PRIVATETESTS += \
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
CONFIG += testcase
|
||||
TARGET = tst_qmlcachegen
|
||||
macos:CONFIG -= app_bundle
|
||||
|
||||
SOURCES += tst_qmlcachegen.cpp
|
||||
|
||||
QT += core-private qml-private testlib
|
|
@ -0,0 +1,163 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the test suite of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
|
||||
** 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 The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <qtest.h>
|
||||
|
||||
#include <QQmlComponent>
|
||||
#include <QQmlEngine>
|
||||
#include <QProcess>
|
||||
#include <QLibraryInfo>
|
||||
#include <QSysInfo>
|
||||
|
||||
class tst_qmlcachegen: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private slots:
|
||||
void initTestCase();
|
||||
|
||||
void loadGeneratedFile();
|
||||
void translationExpressionSupport();
|
||||
};
|
||||
|
||||
// A wrapper around QQmlComponent to ensure the temporary reference counts
|
||||
// on the type data as a result of the main thread <> loader thread communication
|
||||
// are dropped. Regular Synchronous loading will leave us with an event posted
|
||||
// to the gui thread and an extra refcount that will only be dropped after the
|
||||
// event delivery. A plain sendPostedEvents() however is insufficient because
|
||||
// we can't be sure that the event is posted after the constructor finished.
|
||||
class CleanlyLoadingComponent : public QQmlComponent
|
||||
{
|
||||
public:
|
||||
CleanlyLoadingComponent(QQmlEngine *engine, const QUrl &url)
|
||||
: QQmlComponent(engine, url, QQmlComponent::Asynchronous)
|
||||
{ waitForLoad(); }
|
||||
CleanlyLoadingComponent(QQmlEngine *engine, const QString &fileName)
|
||||
: QQmlComponent(engine, fileName, QQmlComponent::Asynchronous)
|
||||
{ waitForLoad(); }
|
||||
|
||||
void waitForLoad()
|
||||
{
|
||||
QTRY_VERIFY(status() == QQmlComponent::Ready || status() == QQmlComponent::Error);
|
||||
}
|
||||
};
|
||||
|
||||
static bool generateCache(const QString &qmlFileName)
|
||||
{
|
||||
QProcess proc;
|
||||
proc.setProcessChannelMode(QProcess::ForwardedChannels);
|
||||
proc.setProgram(QLibraryInfo::location(QLibraryInfo::BinariesPath) + QDir::separator() + QLatin1String("qmlcachegen"));
|
||||
proc.setArguments(QStringList() << (QLatin1String("--target-architecture=") + QSysInfo::buildCpuArchitecture()) << (QLatin1String("--target-abi=") + QSysInfo::buildAbi()) << qmlFileName);
|
||||
proc.start();
|
||||
if (!proc.waitForFinished())
|
||||
return false;
|
||||
if (proc.exitStatus() != QProcess::NormalExit)
|
||||
return false;
|
||||
return proc.exitCode() == 0;
|
||||
}
|
||||
|
||||
void tst_qmlcachegen::initTestCase()
|
||||
{
|
||||
qputenv("QML_FORCE_DISK_CACHE", "1");
|
||||
}
|
||||
|
||||
void tst_qmlcachegen::loadGeneratedFile()
|
||||
{
|
||||
QTemporaryDir tempDir;
|
||||
QVERIFY(tempDir.isValid());
|
||||
|
||||
const auto writeTempFile = [&tempDir](const QString &fileName, const char *contents) {
|
||||
QFile f(tempDir.path() + '/' + fileName);
|
||||
const bool ok = f.open(QIODevice::WriteOnly | QIODevice::Truncate);
|
||||
Q_ASSERT(ok);
|
||||
f.write(contents);
|
||||
return f.fileName();
|
||||
};
|
||||
|
||||
const QString testFilePath = writeTempFile("test.qml", "import QtQml 2.0\n"
|
||||
"QtObject {\n"
|
||||
" property int value: Math.min(100, 42);\n"
|
||||
"}");
|
||||
|
||||
QVERIFY(generateCache(testFilePath));
|
||||
|
||||
const QString cacheFilePath = testFilePath + QLatin1Char('c');
|
||||
QVERIFY(QFile::exists(cacheFilePath));
|
||||
QVERIFY(QFile::remove(testFilePath));
|
||||
|
||||
QQmlEngine engine;
|
||||
CleanlyLoadingComponent component(&engine, QUrl::fromLocalFile(testFilePath));
|
||||
QScopedPointer<QObject> obj(component.create());
|
||||
QVERIFY(!obj.isNull());
|
||||
QCOMPARE(obj->property("value").toInt(), 42);
|
||||
}
|
||||
|
||||
void tst_qmlcachegen::translationExpressionSupport()
|
||||
{
|
||||
QTemporaryDir tempDir;
|
||||
QVERIFY(tempDir.isValid());
|
||||
|
||||
const auto writeTempFile = [&tempDir](const QString &fileName, const char *contents) {
|
||||
QFile f(tempDir.path() + '/' + fileName);
|
||||
const bool ok = f.open(QIODevice::WriteOnly | QIODevice::Truncate);
|
||||
Q_ASSERT(ok);
|
||||
f.write(contents);
|
||||
return f.fileName();
|
||||
};
|
||||
|
||||
const QString testFilePath = writeTempFile("test.qml", "import QtQml.Models 2.2\n"
|
||||
"import QtQml 2.2\n"
|
||||
"QtObject {\n"
|
||||
" property ListModel model: ListModel {\n"
|
||||
" ListElement {\n"
|
||||
" text: qsTr(\"All\")\n"
|
||||
" }\n"
|
||||
" ListElement {\n"
|
||||
" text: QT_TR_NOOP(\"Ok\")\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" property string text: model.get(0).text + \" \" + model.get(1).text\n"
|
||||
"}");
|
||||
|
||||
|
||||
QVERIFY(generateCache(testFilePath));
|
||||
|
||||
const QString cacheFilePath = testFilePath + QLatin1Char('c');
|
||||
QVERIFY(QFile::exists(cacheFilePath));
|
||||
QVERIFY(QFile::remove(testFilePath));
|
||||
|
||||
QQmlEngine engine;
|
||||
CleanlyLoadingComponent component(&engine, QUrl::fromLocalFile(testFilePath));
|
||||
QScopedPointer<QObject> obj(component.create());
|
||||
QVERIFY(!obj.isNull());
|
||||
QCOMPARE(obj->property("text").toString(), QString("All Ok"));
|
||||
}
|
||||
|
||||
QTEST_GUILESS_MAIN(tst_qmlcachegen)
|
||||
|
||||
#include "tst_qmlcachegen.moc"
|
|
@ -10,3 +10,7 @@ linux
|
|||
[ListView::test_listInteractiveCurrentIndexEnforce]
|
||||
linux
|
||||
macos-10.12
|
||||
[TextEdit::test_textentry]
|
||||
macos-10.12
|
||||
[TextEdit::test_textentry_char]
|
||||
macos-10.12
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
[active]
|
||||
osx-10.11
|
|
@ -17,3 +17,5 @@ osx
|
|||
osx-10.10
|
||||
[flickVelocity]
|
||||
osx-10.10
|
||||
[nestedSliderUsingTouch:keepNeither]
|
||||
ubuntu-16.04
|
||||
|
|
|
@ -63,9 +63,7 @@ public:
|
|||
, touchReleases(0)
|
||||
, ungrabs(0)
|
||||
, m_active(false)
|
||||
{
|
||||
setFlags(ItemAcceptsDrops);
|
||||
}
|
||||
{ }
|
||||
|
||||
QPointF pos() const { return m_pos; }
|
||||
|
||||
|
@ -2044,10 +2042,10 @@ void tst_qquickflickable::nestedSliderUsingTouch()
|
|||
QCOMPARE(tda->active(), !ungrabs);
|
||||
QTest::touchEvent(window, touchDevice).release(0, p0, window);
|
||||
QQuickTouchUtils::flush(window);
|
||||
QCOMPARE(tda->touchPointStates.first(), Qt::TouchPointPressed);
|
||||
QCOMPARE(tda->touchUpdates, updates);
|
||||
QCOMPARE(tda->touchReleases, releases);
|
||||
QCOMPARE(tda->ungrabs, ungrabs);
|
||||
QTRY_COMPARE(tda->touchPointStates.first(), Qt::TouchPointPressed);
|
||||
QTRY_COMPARE(tda->touchUpdates, updates);
|
||||
QTRY_COMPARE(tda->touchReleases, releases);
|
||||
QTRY_COMPARE(tda->ungrabs, ungrabs);
|
||||
}
|
||||
|
||||
// QTBUG-31328
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
[nonOverlapping]
|
||||
ubuntu-16.04
|
||||
[nested]
|
||||
ubuntu-16.04
|
|
@ -0,0 +1,2 @@
|
|||
[requestActivate]
|
||||
osx-10.11
|
|
@ -55,7 +55,9 @@
|
|||
#include <QLibraryInfo>
|
||||
#include <qqml.h>
|
||||
#include <qqmldebug.h>
|
||||
#if QT_CONFIG(animation)
|
||||
#include <private/qabstractanimation_p.h>
|
||||
#endif
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
@ -476,10 +478,12 @@ int main(int argc, char *argv[])
|
|||
break;
|
||||
else if (arg == QLatin1String("-verbose"))
|
||||
verboseMode = true;
|
||||
#if QT_CONFIG(animation)
|
||||
else if (arg == QLatin1String("-slow-animations"))
|
||||
QUnifiedTimer::instance()->setSlowModeEnabled(true);
|
||||
else if (arg == QLatin1String("-fixed-animations"))
|
||||
QUnifiedTimer::instance()->setConsistentTiming(true);
|
||||
#endif
|
||||
else if (arg == QLatin1String("-I")) {
|
||||
if (i+1 == argList.count())
|
||||
continue;//Invalid usage, but just ignore it
|
||||
|
|
|
@ -10,7 +10,10 @@ isEmpty(TARGETPATH): error("Must set TARGETPATH (QML import name) for ahead-of-t
|
|||
!isEmpty(QT_TARGET_ARCH):QML_CACHEGEN_ARCH=$$QT_TARGET_ARCH
|
||||
else:QML_CACHEGEN_ARCH=$$QT_ARCH
|
||||
|
||||
QML_CACHEGEN_ARGS=--target-architecture=$$QML_CACHEGEN_ARCH
|
||||
!isEmpty(QT_TARGET_BUILDABI):QML_CACHEGEN_ABI=$$QT_TARGET_BUILDABI
|
||||
else:QML_CACHEGEN_ABI=$$QT_BUILDABI
|
||||
|
||||
QML_CACHEGEN_ARGS=--target-architecture=$$QML_CACHEGEN_ARCH --target-abi=$$QML_CACHEGEN_ABI
|
||||
|
||||
!system($$QML_CACHEGEN_ARCH_CHECK $$QML_CACHEGEN_ARGS --check-if-supported) {
|
||||
message("QML cache generation requested but target architecture $$QML_CACHEGEN_ARCH is not supported.")
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include <private/qqmlirbuilder_p.h>
|
||||
#include <private/qv4isel_moth_p.h>
|
||||
#include <private/qqmljsparser_p.h>
|
||||
#include <private/qv4jssimplifier_p.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
|
@ -113,9 +114,10 @@ static void annotateListElements(QmlIR::Document *document)
|
|||
}
|
||||
}
|
||||
|
||||
static bool compileQmlFile(const QString &inputFileName, const QString &outputFileName, QV4::EvalISelFactory *iselFactory, Error *error)
|
||||
static bool compileQmlFile(const QString &inputFileName, const QString &outputFileName, QV4::EvalISelFactory *iselFactory, const QString &targetABI, Error *error)
|
||||
{
|
||||
QmlIR::Document irDocument(/*debugMode*/false);
|
||||
irDocument.jsModule.targetABI = targetABI;
|
||||
|
||||
QString sourceCode;
|
||||
{
|
||||
|
@ -173,7 +175,10 @@ static bool compileQmlFile(const QString &inputFileName, const QString &outputFi
|
|||
|
||||
QmlIR::QmlUnitGenerator generator;
|
||||
|
||||
// ### translation binding simplification
|
||||
{
|
||||
QQmlJavaScriptBindingExpressionSimplificationPass pass(irDocument.objects, &irDocument.jsModule, &irDocument.jsGenerator);
|
||||
pass.reduceTranslationBindings();
|
||||
}
|
||||
|
||||
QV4::ExecutableAllocator allocator;
|
||||
QScopedPointer<QV4::EvalInstructionSelection> isel(iselFactory->create(/*engine*/nullptr, &allocator, &irDocument.jsModule, &irDocument.jsGenerator));
|
||||
|
@ -193,9 +198,10 @@ static bool compileQmlFile(const QString &inputFileName, const QString &outputFi
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool compileJSFile(const QString &inputFileName, const QString &outputFileName, QV4::EvalISelFactory *iselFactory, Error *error)
|
||||
static bool compileJSFile(const QString &inputFileName, const QString &outputFileName, QV4::EvalISelFactory *iselFactory, const QString &targetABI, Error *error)
|
||||
{
|
||||
QmlIR::Document irDocument(/*debugMode*/false);
|
||||
irDocument.jsModule.targetABI = targetABI;
|
||||
|
||||
QString sourceCode;
|
||||
{
|
||||
|
@ -262,8 +268,6 @@ static bool compileJSFile(const QString &inputFileName, const QString &outputFil
|
|||
|
||||
QmlIR::QmlUnitGenerator generator;
|
||||
|
||||
// ### translation binding simplification
|
||||
|
||||
QV4::ExecutableAllocator allocator;
|
||||
QScopedPointer<QV4::EvalInstructionSelection> isel(iselFactory->create(/*engine*/nullptr, &allocator, &irDocument.jsModule, &irDocument.jsGenerator));
|
||||
// Disable lookups in non-standalone (aka QML) mode
|
||||
|
@ -300,6 +304,9 @@ int main(int argc, char **argv)
|
|||
QCommandLineOption targetArchitectureOption(QStringLiteral("target-architecture"), QCoreApplication::translate("main", "Target architecture"), QCoreApplication::translate("main", "architecture"));
|
||||
parser.addOption(targetArchitectureOption);
|
||||
|
||||
QCommandLineOption targetABIOption(QStringLiteral("target-abi"), QCoreApplication::translate("main", "Target architecture binary interface"), QCoreApplication::translate("main", "abi"));
|
||||
parser.addOption(targetABIOption);
|
||||
|
||||
QCommandLineOption outputFileOption(QStringLiteral("o"), QCoreApplication::translate("main", "Output file name"), QCoreApplication::translate("main", "file name"));
|
||||
parser.addOption(outputFileOption);
|
||||
|
||||
|
@ -347,13 +354,15 @@ int main(int argc, char **argv)
|
|||
if (parser.isSet(outputFileOption))
|
||||
outputFileName = parser.value(outputFileOption);
|
||||
|
||||
const QString targetABI = parser.value(targetABIOption);
|
||||
|
||||
if (inputFile.endsWith(QLatin1String(".qml"))) {
|
||||
if (!compileQmlFile(inputFile, outputFileName, isel.data(), &error)) {
|
||||
if (!compileQmlFile(inputFile, outputFileName, isel.data(), targetABI, &error)) {
|
||||
error.augment(QLatin1String("Error compiling qml file: ")).print();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
} else if (inputFile.endsWith(QLatin1String(".js"))) {
|
||||
if (!compileJSFile(inputFile, outputFileName, isel.data(), &error)) {
|
||||
if (!compileJSFile(inputFile, outputFileName, isel.data(), targetABI, &error)) {
|
||||
error.augment(QLatin1String("Error compiling qml file: ")).print();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
|
|
@ -2,8 +2,9 @@ TEMPLATE = subdirs
|
|||
QT_FOR_CONFIG += qml-private
|
||||
SUBDIRS += \
|
||||
qmlmin \
|
||||
qmlimportscanner \
|
||||
qmlcachegen
|
||||
qmlimportscanner
|
||||
|
||||
qtConfig(commandlineparser): SUBDIRS += qmlcachegen
|
||||
|
||||
!android|android_app {
|
||||
SUBDIRS += \
|
||||
|
|
Loading…
Reference in New Issue