aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRoberto Raggi <roberto.raggi@nokia.com>2011-12-14 11:27:18 +0100
committerQt by Nokia <qt-info@nokia.com>2011-12-15 12:17:28 +0100
commitb21f63763d43cecf96c9359d95705411dbdc4ecd (patch)
treea7172e42145431a0b0cede37a02d5517f6f98c09 /src
parentb6291c914d9a6f24dbfb0e92e8caedae889b709b (diff)
Add support for QUrl types to V4
Extended the V4 instruction set with instructions to `fast convert' url registers to string and bool registers and `resolve' urls using QDeclarativeContext::resolvedUrl. Also, made IR::UrlType a special `string' type. It's a little trick to ensure that the compiler will generate correct conversions for the binary expressions. Change-Id: Ibc9e5b99302bd513f0cc52b598a1b198b11d4d30 Reviewed-by: Aaron Kennedy <aaron.kennedy@nokia.com>
Diffstat (limited to 'src')
-rw-r--r--src/declarative/qml/v4/qv4bindings.cpp74
-rw-r--r--src/declarative/qml/v4/qv4compiler.cpp67
-rw-r--r--src/declarative/qml/v4/qv4instruction.cpp12
-rw-r--r--src/declarative/qml/v4/qv4instruction_p.h4
-rw-r--r--src/declarative/qml/v4/qv4ir.cpp24
5 files changed, 169 insertions, 12 deletions
diff --git a/src/declarative/qml/v4/qv4bindings.cpp b/src/declarative/qml/v4/qv4bindings.cpp
index 04c410c15d..0ccf25cebd 100644
--- a/src/declarative/qml/v4/qv4bindings.cpp
+++ b/src/declarative/qml/v4/qv4bindings.cpp
@@ -999,6 +999,80 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
}
QML_V4_END_INSTR(ConvertStringToReal, unaryop)
+ QML_V4_BEGIN_INSTR(ConvertStringToUrl, unaryop)
+ {
+ const Register &src = registers[instr->unaryop.src];
+ Register &output = registers[instr->unaryop.output];
+ // ### NaN
+ if (src.isUndefined()) {
+ output.setUndefined();
+ } else {
+ const QString tmp(*src.getstringptr());
+ if (instr->unaryop.src == instr->unaryop.output) {
+ output.cleanupString();
+ MARK_CLEAN_REGISTER(instr->unaryop.output);
+ }
+ new (output.geturlptr()) QUrl(tmp);
+ URL_REGISTER(instr->unaryop.output);
+ }
+ }
+ QML_V4_END_INSTR(ConvertStringToUrl, unaryop)
+
+ QML_V4_BEGIN_INSTR(ConvertUrlToBool, unaryop)
+ {
+ const Register &src = registers[instr->unaryop.src];
+ Register &output = registers[instr->unaryop.output];
+ // ### NaN
+ if (src.isUndefined()) {
+ output.setUndefined();
+ } else {
+ const QUrl tmp(*src.geturlptr());
+ if (instr->unaryop.src == instr->unaryop.output) {
+ output.cleanupUrl();
+ MARK_CLEAN_REGISTER(instr->unaryop.output);
+ }
+ output.setbool(!tmp.isEmpty());
+ }
+ }
+ QML_V4_END_INSTR(ConvertUrlToBool, unaryop)
+
+ QML_V4_BEGIN_INSTR(ConvertUrlToString, unaryop)
+ {
+ const Register &src = registers[instr->unaryop.src];
+ Register &output = registers[instr->unaryop.output];
+ // ### NaN
+ if (src.isUndefined()) {
+ output.setUndefined();
+ } else {
+ const QUrl tmp(*src.geturlptr());
+ if (instr->unaryop.src == instr->unaryop.output) {
+ output.cleanupUrl();
+ MARK_CLEAN_REGISTER(instr->unaryop.output);
+ }
+ new (output.getstringptr()) QString(tmp.toString());
+ STRING_REGISTER(instr->unaryop.output);
+ }
+ }
+ QML_V4_END_INSTR(ConvertUrlToString, unaryop)
+
+ QML_V4_BEGIN_INSTR(ResolveUrl, unaryop)
+ {
+ const Register &src = registers[instr->unaryop.src];
+ Register &output = registers[instr->unaryop.output];
+ if (src.isUndefined()) {
+ output.setUndefined();
+ } else {
+ const QUrl tmp(*src.geturlptr());
+ if (instr->unaryop.src == instr->unaryop.output) {
+ *output.geturlptr() = context->resolvedUrl(tmp);
+ } else {
+ new (output.geturlptr()) QUrl(context->resolvedUrl(tmp));
+ URL_REGISTER(instr->unaryop.output);
+ }
+ }
+ }
+ QML_V4_END_INSTR(ResolveUrl, unaryop)
+
QML_V4_BEGIN_INSTR(MathSinReal, unaryop)
{
const Register &src = registers[instr->unaryop.src];
diff --git a/src/declarative/qml/v4/qv4compiler.cpp b/src/declarative/qml/v4/qv4compiler.cpp
index e091ce2731..5d732d5603 100644
--- a/src/declarative/qml/v4/qv4compiler.cpp
+++ b/src/declarative/qml/v4/qv4compiler.cpp
@@ -340,6 +340,9 @@ void QV4CompilerPrivate::visitName(IR::Name *e)
case QMetaType::QString:
regType = QStringType;
break;
+ case QMetaType::QUrl:
+ regType = QUrlType;
+ break;
default:
if (propTy == qMetaTypeId<QDeclarative1AnchorLine>()) {
@@ -848,15 +851,40 @@ void QV4CompilerPrivate::visitMove(IR::Move *s)
traceExpression(s->source, dest);
V4Instr::Type opcode = V4Instr::Noop;
- if (target->type == IR::BoolType) {
- switch (s->source->type) {
+ IR::Type targetTy = s->target->type;
+ IR::Type sourceTy = s->source->type;
+
+ if (sourceTy == IR::UrlType) {
+ switch (targetTy) {
+ case IR::BoolType:
+ case IR::StringType:
+ // nothing to do. V4 will generate optimized
+ // url-to-xxx conversions.
+ break;
+ default: {
+ // generate a UrlToString conversion and fix
+ // the type of the source expression.
+ V4Instr conv;
+ conv.unaryop.output = V4Instr::ConvertUrlToString;
+ conv.unaryop.src = src;
+ gen(opcode, conv);
+
+ sourceTy = IR::StringType;
+ break;
+ }
+ } // switch
+ }
+
+ if (targetTy == IR::BoolType) {
+ switch (sourceTy) {
case IR::IntType: opcode = V4Instr::ConvertIntToBool; break;
case IR::RealType: opcode = V4Instr::ConvertRealToBool; break;
case IR::StringType: opcode = V4Instr::ConvertStringToBool; break;
+ case IR::UrlType: opcode = V4Instr::ConvertUrlToBool; break;
default: break;
} // switch
- } else if (target->type == IR::IntType) {
- switch (s->source->type) {
+ } else if (targetTy == IR::IntType) {
+ switch (sourceTy) {
case IR::BoolType: opcode = V4Instr::ConvertBoolToInt; break;
case IR::RealType: {
if (s->isMoveForReturn)
@@ -868,26 +896,49 @@ void QV4CompilerPrivate::visitMove(IR::Move *s)
case IR::StringType: opcode = V4Instr::ConvertStringToInt; break;
default: break;
} // switch
- } else if (target->type == IR::RealType) {
- switch (s->source->type) {
+ } else if (targetTy == IR::RealType) {
+ switch (sourceTy) {
case IR::BoolType: opcode = V4Instr::ConvertBoolToReal; break;
case IR::IntType: opcode = V4Instr::ConvertIntToReal; break;
case IR::StringType: opcode = V4Instr::ConvertStringToReal; break;
default: break;
} // switch
- } else if (target->type == IR::StringType) {
- switch (s->source->type) {
+ } else if (targetTy == IR::StringType) {
+ switch (sourceTy) {
case IR::BoolType: opcode = V4Instr::ConvertBoolToString; break;
case IR::IntType: opcode = V4Instr::ConvertIntToString; break;
case IR::RealType: opcode = V4Instr::ConvertRealToString; break;
+ case IR::UrlType: opcode = V4Instr::ConvertUrlToString; break;
+ default: break;
+ } // switch
+ } else if (targetTy == IR::UrlType) {
+ V4Instr convToString;
+ convToString.unaryop.output = dest;
+ convToString.unaryop.src = src;
+
+ // try to convert the source expression to a string.
+ switch (sourceTy) {
+ case IR::BoolType: gen(V4Instr::ConvertBoolToString, convToString); sourceTy = IR::StringType; break;
+ case IR::IntType: gen(V4Instr::ConvertIntToString, convToString); sourceTy = IR::StringType; break;
+ case IR::RealType: gen(V4Instr::ConvertRealToString, convToString); sourceTy = IR::StringType; break;
default: break;
} // switch
+
+ if (sourceTy == IR::StringType)
+ opcode = V4Instr::ConvertStringToUrl;
}
if (opcode != V4Instr::Noop) {
V4Instr conv;
conv.unaryop.output = dest;
conv.unaryop.src = src;
gen(opcode, conv);
+
+ if (s->isMoveForReturn && opcode == V4Instr::ConvertStringToUrl) {
+ V4Instr resolveUrl;
+ resolveUrl.unaryop.output = dest;
+ resolveUrl.unaryop.src = dest;
+ gen(V4Instr::ResolveUrl, resolveUrl);
+ }
} else {
discard();
}
diff --git a/src/declarative/qml/v4/qv4instruction.cpp b/src/declarative/qml/v4/qv4instruction.cpp
index ccf91d567b..18b2a24c1b 100644
--- a/src/declarative/qml/v4/qv4instruction.cpp
+++ b/src/declarative/qml/v4/qv4instruction.cpp
@@ -168,6 +168,18 @@ void Bytecode::dump(const V4Instr *i, int address) const
case V4Instr::ConvertStringToReal:
INSTR_DUMP << "\t" << "ConvertStringToReal" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
+ case V4Instr::ConvertStringToUrl:
+ INSTR_DUMP << "\t" << "ConvertStringToUrl" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ break;
+ case V4Instr::ConvertUrlToBool:
+ INSTR_DUMP << "\t" << "ConvertUrlToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ break;
+ case V4Instr::ConvertUrlToString:
+ INSTR_DUMP << "\t" << "ConvertUrlToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ break;
+ case V4Instr::ResolveUrl:
+ INSTR_DUMP << "\t" << "ResolveUrl" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ break;
case V4Instr::MathSinReal:
INSTR_DUMP << "\t" << "MathSinReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
diff --git a/src/declarative/qml/v4/qv4instruction_p.h b/src/declarative/qml/v4/qv4instruction_p.h
index 6f90117c7c..f1966bb875 100644
--- a/src/declarative/qml/v4/qv4instruction_p.h
+++ b/src/declarative/qml/v4/qv4instruction_p.h
@@ -91,6 +91,10 @@ QT_BEGIN_NAMESPACE
F(ConvertStringToBool, unaryop) \
F(ConvertStringToInt, unaryop) \
F(ConvertStringToReal, unaryop) \
+ F(ConvertStringToUrl, unaryop) \
+ F(ConvertUrlToBool, unaryop) \
+ F(ConvertUrlToString, unaryop) \
+ F(ResolveUrl, unaryop) \
F(MathSinReal, unaryop) \
F(MathCosReal, unaryop) \
F(MathRoundReal, unaryop) \
diff --git a/src/declarative/qml/v4/qv4ir.cpp b/src/declarative/qml/v4/qv4ir.cpp
index 48d6c9b81c..0a0228b894 100644
--- a/src/declarative/qml/v4/qv4ir.cpp
+++ b/src/declarative/qml/v4/qv4ir.cpp
@@ -71,14 +71,30 @@ inline const char *typeName(Type t)
}
}
+inline bool isNumberType(IR::Type ty)
+{
+ return ty >= IR::FirstNumberType;
+}
+
+inline bool isStringType(IR::Type ty)
+{
+ return ty == IR::StringType || ty == IR::UrlType;
+}
+
IR::Type maxType(IR::Type left, IR::Type right)
{
- if (left == right)
+ if (isStringType(left) && isStringType(right)) {
+ // String promotions (url to string) are more specific than
+ // identity conversions (AKA left == right). That's because
+ // we want to ensure we convert urls to strings in binary
+ // expressions.
+ return IR::StringType;
+ } else if (left == right)
return left;
- else if (left >= IR::FirstNumberType && right >= IR::FirstNumberType)
+ else if (isNumberType(left) && isNumberType(right))
return qMax(left, right);
- else if ((left >= IR::FirstNumberType && right == IR::StringType) ||
- (right >= IR::FirstNumberType && left == IR::StringType))
+ else if ((isNumberType(left) && isStringType(right)) ||
+ (isNumberType(right) && isStringType(left)))
return IR::StringType;
else
return IR::InvalidType;