aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRoberto Raggi <roberto.raggi@nokia.com>2012-04-02 16:35:51 +0200
committerQt by Nokia <qt-info@nokia.com>2012-04-03 16:22:04 +0200
commit66e6b017190df4216d765da8c09a2e75501e38b4 (patch)
tree6a3267b91139881a5c3f864d0540827136fd83ef /src
parent373d78837d1d5049c5b1c2790d6f4023e6ecf974 (diff)
Add Throw instruction to the V4 virtual machine
Also, throw an exception when trying to assign something that is not a QUrl or a QString to a QUrl. Change-Id: Ic48fd519c8318d391706ebca1955a5dd2ef6e80e Reviewed-by: Aaron Kennedy <aaron.kennedy@nokia.com>
Diffstat (limited to 'src')
-rw-r--r--src/qml/qml/v4/qv4bindings.cpp9
-rw-r--r--src/qml/qml/v4/qv4compiler.cpp26
-rw-r--r--src/qml/qml/v4/qv4compiler_p_p.h2
-rw-r--r--src/qml/qml/v4/qv4instruction.cpp3
-rw-r--r--src/qml/qml/v4/qv4instruction_p.h8
-rw-r--r--src/qml/qml/v4/qv4ir.cpp2
-rw-r--r--src/qml/qml/v4/qv4ir_p.h1
7 files changed, 49 insertions, 2 deletions
diff --git a/src/qml/qml/v4/qv4bindings.cpp b/src/qml/qml/v4/qv4bindings.cpp
index 97d37400ac..3158f8fc2a 100644
--- a/src/qml/qml/v4/qv4bindings.cpp
+++ b/src/qml/qml/v4/qv4bindings.cpp
@@ -592,6 +592,11 @@ inline quint32 QV4Bindings::toUint32(double n)
goto exceptionExit; \
}
+#define THROW_VALUE_EXCEPTION_STR(id, str) { \
+ throwException((id), error, program, context, (str)); \
+ goto exceptionExit; \
+}
+
#define THROW_EXCEPTION(id) THROW_EXCEPTION_STR(id, QString())
#define MARK_REGISTER(reg) cleanupRegisterMask |= (1 << (reg))
@@ -1672,6 +1677,10 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
registers[instr->cleanup.reg].cleanup();
QML_V4_END_INSTR(CleanupRegister, cleanup)
+ QML_V4_BEGIN_INSTR(Throw, throwop)
+ THROW_VALUE_EXCEPTION_STR(instr->throwop.exceptionId, *registers[instr->throwop.message].getstringptr());
+ QML_V4_END_INSTR(Throw, throwop)
+
#ifdef QML_THREADED_INTERPRETER
// nothing to do
#else
diff --git a/src/qml/qml/v4/qv4compiler.cpp b/src/qml/qml/v4/qv4compiler.cpp
index 08cfed9383..e833aed3fd 100644
--- a/src/qml/qml/v4/qv4compiler.cpp
+++ b/src/qml/qml/v4/qv4compiler.cpp
@@ -63,6 +63,7 @@ static bool qmlEnableV4 = true;
using namespace QQmlJS;
QV4CompilerPrivate::QV4CompilerPrivate()
: _function(0) , _block(0) , _discarded(false), registerCount(0)
+ , bindingLine(0), bindingColumn(0)
{
}
@@ -73,6 +74,8 @@ void QV4CompilerPrivate::trace(int line, int column)
{
bytecode.clear();
+ this->bindingLine = line;
+ this->bindingColumn = column;
this->currentReg = _function->tempCount;
this->registerCount = qMax(this->registerCount, this->currentReg);
@@ -317,7 +320,7 @@ void QV4CompilerPrivate::visitName(IR::Name *e)
Instr::LoadAttached attached;
attached.output = currentReg;
attached.reg = currentReg;
- attached.exceptionId = exceptionId(e->line, e->column);
+ attached.exceptionId = exceptionId(bindingLine, bindingColumn);
if (e->declarativeType->attachedPropertiesId() == -1)
discard();
attached.id = e->declarativeType->attachedPropertiesId();
@@ -966,6 +969,16 @@ void QV4CompilerPrivate::visitMove(IR::Move *s)
// url-to-xxx conversions.
break;
default: {
+ if (s->isMoveForReturn) {
+ V4Instr instr;
+ instr.throwop.exceptionId = exceptionId(bindingLine, bindingColumn);
+ registerLiteralString(dest, _function->newString(QString::fromUtf8("Unable to assign %1 to %2")
+ .arg(QLatin1String(IR::typeName(sourceTy)))
+ .arg(QLatin1String(IR::typeName(targetTy)))));
+ instr.throwop.message = dest;
+ gen(V4Instr::Throw, instr);
+ return;
+ }
// generate a UrlToString conversion and fix
// the type of the source expression.
V4Instr conv;
@@ -1018,6 +1031,17 @@ void QV4CompilerPrivate::visitMove(IR::Move *s)
default: break;
} // switch
} else if (targetTy == IR::UrlType) {
+ if (s->isMoveForReturn && sourceTy != IR::StringType) {
+ V4Instr instr;
+ instr.throwop.exceptionId = exceptionId(bindingLine, bindingColumn);
+ registerLiteralString(dest, _function->newString(QString::fromUtf8("Unable to assign %1 to %2")
+ .arg(QLatin1String(IR::typeName(sourceTy)))
+ .arg(QLatin1String(IR::typeName(targetTy)))));
+ instr.throwop.message = dest;
+ gen(V4Instr::Throw, instr);
+ return;
+ }
+
V4Instr convToString;
convToString.unaryop.output = dest;
convToString.unaryop.src = src;
diff --git a/src/qml/qml/v4/qv4compiler_p_p.h b/src/qml/qml/v4/qv4compiler_p_p.h
index 984f20b1b8..782ca594ae 100644
--- a/src/qml/qml/v4/qv4compiler_p_p.h
+++ b/src/qml/qml/v4/qv4compiler_p_p.h
@@ -235,6 +235,8 @@ private:
bool usedSubscriptionIdsChanged;
quint32 currentBlockMask;
+ int bindingLine;
+ int bindingColumn;
};
diff --git a/src/qml/qml/v4/qv4instruction.cpp b/src/qml/qml/v4/qv4instruction.cpp
index 26029046f6..4298be28ae 100644
--- a/src/qml/qml/v4/qv4instruction.cpp
+++ b/src/qml/qml/v4/qv4instruction.cpp
@@ -382,6 +382,9 @@ void Bytecode::dump(const V4Instr *i, int address) const
case V4Instr::Block:
INSTR_DUMP << "\t" << "Block" << "\t\t\t" << "Mask(" << QByteArray::number(i->blockop.block, 16).constData() << ")";
break;
+ case V4Instr::Throw:
+ INSTR_DUMP << "\t" << "Throw" << "\t\t\t" << "InputReg(" << i->throwop.message << ")";
+ break;
default:
INSTR_DUMP << "\t" << "Unknown";
break;
diff --git a/src/qml/qml/v4/qv4instruction_p.h b/src/qml/qml/v4/qv4instruction_p.h
index 49ac65ccf0..46a03b37c7 100644
--- a/src/qml/qml/v4/qv4instruction_p.h
+++ b/src/qml/qml/v4/qv4instruction_p.h
@@ -160,6 +160,7 @@ QT_BEGIN_NAMESPACE
F(BranchFalse, branchop) \
F(Branch, branchop) \
F(Block, blockop) \
+ F(Throw, throwop) \
/* Speculative property resolution */ \
F(InitString, initstring)
@@ -359,6 +360,12 @@ union Q_AUTOTEST_EXPORT V4Instr {
quint32 block;
};
+ struct instr_throwop {
+ QML_V4_INSTR_HEADER
+ quint8 exceptionId;
+ quint32 message;
+ };
+
instr_common common;
instr_id id;
instr_init init;
@@ -384,6 +391,7 @@ union Q_AUTOTEST_EXPORT V4Instr {
instr_initstring initstring;
instr_branchop branchop;
instr_blockop blockop;
+ instr_throwop throwop;
};
template<int N>
diff --git a/src/qml/qml/v4/qv4ir.cpp b/src/qml/qml/v4/qv4ir.cpp
index 8fc4719791..2bd0720260 100644
--- a/src/qml/qml/v4/qv4ir.cpp
+++ b/src/qml/qml/v4/qv4ir.cpp
@@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE
namespace QQmlJS {
namespace IR {
-inline const char *typeName(Type t)
+const char *typeName(Type t)
{
switch (t) {
case InvalidType: return "invalid";
diff --git a/src/qml/qml/v4/qv4ir_p.h b/src/qml/qml/v4/qv4ir_p.h
index d670876786..26bd43c406 100644
--- a/src/qml/qml/v4/qv4ir_p.h
+++ b/src/qml/qml/v4/qv4ir_p.h
@@ -155,6 +155,7 @@ enum Type {
};
Type maxType(IR::Type left, IR::Type right);
bool isRealType(IR::Type type);
+const char *typeName(IR::Type t);
struct ExprVisitor {
virtual ~ExprVisitor() {}