aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-05-11 22:23:56 +0200
committerLars Knoll <lars.knoll@qt.io>2018-05-13 12:55:20 +0000
commit3d5ba9f86e32950204bfcdf6591c4740a8ef7507 (patch)
tree9c599ad6b7fd2bd06d0880dde70ff21d6f522bef /src/qml/jsruntime
parent2d6b08bd17377aa6bcb663029a196a8d19cac6ac (diff)
Add instructions to simplify for-of loops
Added an IteratorNext instruction to fetch the next iteration value (empty if the iterator is done). This will also help to implement array destructuring without requiring huge amounts of byte code. Change-Id: If96c1e81471e5e2b0b7b2af122238d87741aa371 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r--src/qml/jsruntime/qv4engine.cpp2
-rw-r--r--src/qml/jsruntime/qv4engine_p.h5
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp18
-rw-r--r--src/qml/jsruntime/qv4runtimeapi_p.h3
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp11
5 files changed, 38 insertions, 1 deletions
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index b703f6e4f3..8227fe0184 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -268,6 +268,8 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
jsStrings[String_byteOffset] = newIdentifier(QStringLiteral("byteOffset"));
jsStrings[String_buffer] = newIdentifier(QStringLiteral("buffer"));
jsStrings[String_lastIndex] = newIdentifier(QStringLiteral("lastIndex"));
+ jsStrings[String_next] = newIdentifier(QStringLiteral("next"));
+ jsStrings[String_done] = newIdentifier(QStringLiteral("done"));
jsSymbols[Symbol_hasInstance] = Symbol::create(this, QStringLiteral("@Symbol.hasInstance"));
jsSymbols[Symbol_isConcatSpreadable] = Symbol::create(this, QStringLiteral("@Symbol.isConcatSpreadable"));
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index e8218d0d1c..46bf58de07 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -327,6 +327,9 @@ public:
String_byteOffset,
String_buffer,
String_lastIndex,
+ String_next,
+ String_done,
+
NJSStrings
};
Value *jsStrings;
@@ -384,6 +387,8 @@ public:
String *id_byteOffset() const { return reinterpret_cast<String *>(jsStrings + String_byteOffset); }
String *id_buffer() const { return reinterpret_cast<String *>(jsStrings + String_buffer); }
String *id_lastIndex() const { return reinterpret_cast<String *>(jsStrings + String_lastIndex); }
+ String *id_next() const { return reinterpret_cast<String *>(jsStrings + String_next); }
+ String *id_done() const { return reinterpret_cast<String *>(jsStrings + String_done); }
Symbol *symbol_hasInstance() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_hasInstance); }
Symbol *symbol_isConcatSpreadable() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_isConcatSpreadable); }
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 986684302c..eadbcb9557 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -715,6 +715,24 @@ ReturnedValue Runtime::method_getIterator(ExecutionEngine *engine, const Value &
return engine->newForInIteratorObject(o)->asReturnedValue();
}
+ReturnedValue Runtime::method_iteratorNext(ExecutionEngine *engine, const Value &iterator)
+{
+ Q_ASSERT(iterator.isObject());
+
+ Scope scope(engine);
+ ScopedFunctionObject f(scope, static_cast<const Object &>(iterator).get(engine->id_next()));
+ if (!f)
+ return engine->throwTypeError();
+ JSCallData cData(scope, 0, nullptr, &iterator);
+ ScopedObject o(scope, f->call(cData));
+ if (!o)
+ return engine->throwTypeError();
+ ScopedValue v(scope, o->get(engine->id_done()));
+ if (v->toBoolean() == true)
+ return Primitive::emptyValue().asReturnedValue();
+ return o->get(engine->id_value());
+}
+
void Runtime::method_storeNameSloppy(ExecutionEngine *engine, int nameIndex, const Value &value)
{
Scope scope(engine);
diff --git a/src/qml/jsruntime/qv4runtimeapi_p.h b/src/qml/jsruntime/qv4runtimeapi_p.h
index c98433359b..1e14c23d7e 100644
--- a/src/qml/jsruntime/qv4runtimeapi_p.h
+++ b/src/qml/jsruntime/qv4runtimeapi_p.h
@@ -144,8 +144,9 @@ struct ExceptionCheck<void (*)(QV4::NoThrowEngine *, A, B, C)> {
F(ReturnedValue, arrayLiteral, (ExecutionEngine *engine, Value *values, uint length)) \
F(ReturnedValue, objectLiteral, (ExecutionEngine *engine, const Value *args, int classId, int arrayValueCount, int arrayGetterSetterCountAndFlags)) \
\
- /* for-in and for-of */ \
+ /* for-in, for-of and array destructuring */ \
F(ReturnedValue, getIterator, (ExecutionEngine *engine, const Value &in, int iterator)) \
+ F(ReturnedValue, iteratorNext, (ExecutionEngine *engine, const Value &iterator)) \
\
/* unary operators */ \
F(ReturnedValue, uMinus, (const Value &value)) \
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index 5daead19d2..9fd57e0dcb 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -959,6 +959,12 @@ QV4::ReturnedValue VME::interpret(CppStackFrame &frame, const uchar *code)
CHECK_EXCEPTION;
MOTH_END_INSTR(GetIterator)
+ MOTH_BEGIN_INSTR(IteratorNext)
+ STORE_ACC();
+ acc = Runtime::method_iteratorNext(engine, accumulator);
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(IteratorNext)
+
MOTH_BEGIN_INSTR(DeleteMember)
if (!Runtime::method_deleteMember(engine, STACK_VALUE(base), member)) {
if (function->isStrict()) {
@@ -1086,6 +1092,11 @@ QV4::ReturnedValue VME::interpret(CppStackFrame &frame, const uchar *code)
code += offset;
MOTH_END_INSTR(JumpNotUndefined)
+ MOTH_BEGIN_INSTR(JumpEmpty)
+ if (Q_UNLIKELY(acc == QV4::Primitive::emptyValue().asReturnedValue()))
+ code += offset;
+ MOTH_END_INSTR(JumpEmpty)
+
MOTH_BEGIN_INSTR(CmpEqNull)
acc = Encode(ACC.isNullOrUndefined());
MOTH_END_INSTR(CmpEqNull)