aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-02-10 19:02:34 +0100
committerLars Knoll <lars.knoll@qt.io>2018-04-25 17:49:15 +0000
commit219485d898556368a833576f1c55e210c1cf7189 (patch)
treec6f8faf247711f4ba36eb3605e5fc89f84c6aff6 /src
parentb59b727035c4c1a4d235432cc67e5d89d3a24cd3 (diff)
Add support for ES6 rest parameters
function foo(a, b, ...c) {...} now works correctly. Change-Id: Ie442a0e7cc5e9dc4156e56b348bba305cced8531 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/qml/compiler/qv4codegen.cpp10
-rw-r--r--src/qml/compiler/qv4instr_moth.cpp4
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h2
-rw-r--r--src/qml/jit/qv4jit.cpp11
-rw-r--r--src/qml/jit/qv4jit_p.h1
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp10
-rw-r--r--src/qml/jsruntime/qv4runtimeapi_p.h1
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp4
8 files changed, 41 insertions, 2 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index bc0c62e9be..52dd32dcc5 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -2339,10 +2339,15 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast,
bytecodeGenerator->addInstruction(convert);
}
+ int argc = 0;
while (formals) {
if (formals->isRest) {
- // #### implement me
- throwSyntaxError(formals->firstSourceLocation(), QString::fromLatin1("Support for rest parameters not implemented!"));
+ Q_ASSERT(!formals->next);
+ Instruction::CreateRestParameter rest;
+ rest.argIndex = argc;
+ bytecodeGenerator->addInstruction(rest);
+ Reference f = referenceForName(formals->name.toString(), true);
+ f.storeConsumeAccumulator();
}
if (formals->defaultExpression) {
RegisterScope scope(this);
@@ -2354,6 +2359,7 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast,
jump.link();
}
formals = formals->next;
+ ++argc;
}
beginFunctionBodyHook();
diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp
index 362bc40b31..3a9cecdae0 100644
--- a/src/qml/compiler/qv4instr_moth.cpp
+++ b/src/qml/compiler/qv4instr_moth.cpp
@@ -454,6 +454,10 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
MOTH_BEGIN_INSTR(CreateUnmappedArgumentsObject)
MOTH_END_INSTR(CreateUnmappedArgumentsObject)
+ MOTH_BEGIN_INSTR(CreateRestParameter)
+ d << argIndex;
+ MOTH_END_INSTR(CreateRestParameter)
+
MOTH_BEGIN_INSTR(ConvertThisToObject)
MOTH_END_INSTR(ConvertThisToObject)
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index df9be62672..8ce72f4942 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -128,6 +128,7 @@ QT_BEGIN_NAMESPACE
#define INSTR_DefineObjectLiteral(op) INSTRUCTION(op, DefineObjectLiteral, 4, internalClassId, arrayValueCount, arrayGetterSetterCountAndFlags, args)
#define INSTR_CreateMappedArgumentsObject(op) INSTRUCTION(op, CreateMappedArgumentsObject, 0)
#define INSTR_CreateUnmappedArgumentsObject(op) INSTRUCTION(op, CreateUnmappedArgumentsObject, 0)
+#define INSTR_CreateRestParameter(op) INSTRUCTION(op, CreateRestParameter, 1, argIndex)
#define INSTR_ConvertThisToObject(op) INSTRUCTION(op, ConvertThisToObject, 0)
#define INSTR_Construct(op) INSTRUCTION(op, Construct, 3, func, argc, argv)
#define INSTR_Jump(op) INSTRUCTION(op, Jump, 1, offset)
@@ -245,6 +246,7 @@ QT_BEGIN_NAMESPACE
F(DefineObjectLiteral) \
F(CreateMappedArgumentsObject) \
F(CreateUnmappedArgumentsObject) \
+ F(CreateRestParameter) \
F(ConvertThisToObject) \
F(Construct) \
F(Jump) \
diff --git a/src/qml/jit/qv4jit.cpp b/src/qml/jit/qv4jit.cpp
index ec446b63ec..b2dde4fca2 100644
--- a/src/qml/jit/qv4jit.cpp
+++ b/src/qml/jit/qv4jit.cpp
@@ -781,6 +781,14 @@ void BaselineJIT::generate_CreateUnmappedArgumentsObject()
Assembler::ResultInAccumulator);
}
+void BaselineJIT::generate_CreateRestParameter(int argIndex)
+{
+ as->prepareCallWithArgCount(2);
+ as->passInt32AsArg(argIndex, 1);
+ as->passEngineAsArg(0);
+ JIT_GENERATE_RUNTIME_CALL(Runtime::method_createRestParameter, Assembler::ResultInAccumulator);
+}
+
static void convertThisToObjectHelper(ExecutionEngine *engine, Value *t)
{
if (!t->isObject()) {
@@ -1173,6 +1181,9 @@ void BaselineJIT::collectLabelsInBytecode()
MOTH_BEGIN_INSTR(CreateUnmappedArgumentsObject)
MOTH_END_INSTR(CreateUnmappedArgumentsObject)
+ MOTH_BEGIN_INSTR(CreateRestParameter)
+ MOTH_END_INSTR(CreateRestParameter)
+
MOTH_BEGIN_INSTR(ConvertThisToObject)
MOTH_END_INSTR(ConvertThisToObject)
diff --git a/src/qml/jit/qv4jit_p.h b/src/qml/jit/qv4jit_p.h
index 93fa7e7576..9ff2d99191 100644
--- a/src/qml/jit/qv4jit_p.h
+++ b/src/qml/jit/qv4jit_p.h
@@ -192,6 +192,7 @@ public:
int args) override;
void generate_CreateMappedArgumentsObject() override;
void generate_CreateUnmappedArgumentsObject() override;
+ void generate_CreateRestParameter(int argIndex) override;
void generate_ConvertThisToObject() override;
void generate_Construct(int func, int argc, int argv) override;
void generate_Jump(int offset) override;
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index c984a70a14..b14395b507 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -1269,6 +1269,16 @@ QV4::ReturnedValue Runtime::method_createUnmappedArgumentsObject(ExecutionEngine
return engine->memoryManager->allocObject<StrictArgumentsObject>(ic, engine->currentStackFrame)->asReturnedValue();
}
+QV4::ReturnedValue Runtime::method_createRestParameter(ExecutionEngine *engine, int argIndex)
+{
+ const Value *values = engine->currentStackFrame->originalArguments + argIndex;
+ int nValues = engine->currentStackFrame->originalArgumentsCount - argIndex;
+ if (nValues <= 0)
+ return engine->newArrayObject(0)->asReturnedValue();
+ return engine->newArrayObject(values, nValues)->asReturnedValue();
+}
+
+
ReturnedValue Runtime::method_loadQmlContext(NoThrowEngine *engine)
{
Heap::QmlContext *ctx = engine->qmlContext();
diff --git a/src/qml/jsruntime/qv4runtimeapi_p.h b/src/qml/jsruntime/qv4runtimeapi_p.h
index 91232256a9..9bdb41b19e 100644
--- a/src/qml/jsruntime/qv4runtimeapi_p.h
+++ b/src/qml/jsruntime/qv4runtimeapi_p.h
@@ -134,6 +134,7 @@ struct ExceptionCheck<void (*)(QV4::NoThrowEngine *, A, B, C)> {
F(void, declareVar, (ExecutionEngine *engine, bool deletable, int nameIndex)) \
F(ReturnedValue, createMappedArgumentsObject, (ExecutionEngine *engine)) \
F(ReturnedValue, createUnmappedArgumentsObject, (ExecutionEngine *engine)) \
+ F(ReturnedValue, createRestParameter, (ExecutionEngine *engine, int argIndex)) \
\
/* literals */ \
F(ReturnedValue, arrayLiteral, (ExecutionEngine *engine, Value *values, uint length)) \
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index 88d859eef5..fae917dbb5 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -981,6 +981,10 @@ QV4::ReturnedValue VME::exec(const FunctionObject *fo, const Value *thisObject,
acc = Runtime::method_createUnmappedArgumentsObject(engine);
MOTH_END_INSTR(CreateUnmappedArgumentsObject)
+ MOTH_BEGIN_INSTR(CreateRestParameter)
+ acc = Runtime::method_createRestParameter(engine, argIndex);
+ MOTH_END_INSTR(CreateRestParameter)
+
MOTH_BEGIN_INSTR(ConvertThisToObject)
Value *t = &stack[CallData::This];
if (!t->isObject()) {