diff options
author | Roberto Raggi <roberto.raggi@nokia.com> | 2011-12-14 11:27:18 +0100 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2011-12-15 12:17:28 +0100 |
commit | b21f63763d43cecf96c9359d95705411dbdc4ecd (patch) | |
tree | a7172e42145431a0b0cede37a02d5517f6f98c09 /src | |
parent | b6291c914d9a6f24dbfb0e92e8caedae889b709b (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.cpp | 74 | ||||
-rw-r--r-- | src/declarative/qml/v4/qv4compiler.cpp | 67 | ||||
-rw-r--r-- | src/declarative/qml/v4/qv4instruction.cpp | 12 | ||||
-rw-r--r-- | src/declarative/qml/v4/qv4instruction_p.h | 4 | ||||
-rw-r--r-- | src/declarative/qml/v4/qv4ir.cpp | 24 |
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; |