aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-05-11 21:10:11 +0200
committerLars Knoll <lars.knoll@qt.io>2018-05-11 20:52:40 +0000
commit2d6b08bd17377aa6bcb663029a196a8d19cac6ac (patch)
tree4bce8e27455c38b919a5a1706c6bb5b8b7f8813a
parentbde97ab6a72acafaa29d2da0f7a31ae23918a6b0 (diff)
Give for loops a per-iteration context as well
Regular for loops also have a per iteration context for lexically declared variables as well. Change-Id: I35cb58bfb198c7dc32d70f41ea0ced7ddefcc37e Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-rw-r--r--src/qml/compiler/qv4codegen.cpp4
-rw-r--r--src/qml/compiler/qv4instr_moth.cpp3
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h2
-rw-r--r--src/qml/jit/qv4jit.cpp16
-rw-r--r--src/qml/jit/qv4jit_p.h1
-rw-r--r--src/qml/jsruntime/qv4context.cpp15
-rw-r--r--src/qml/jsruntime/qv4context_p.h1
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp6
-rw-r--r--src/qml/jsruntime/qv4runtimeapi_p.h1
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp7
-rw-r--r--tests/auto/qml/ecmascripttests/TestExpectations6
11 files changed, 55 insertions, 7 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 9c63360107..49f0511116 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -2708,6 +2708,10 @@ bool Codegen::visit(ForStatement *ast)
setJumpOutLocation(bytecodeGenerator, ast->statement, ast->forToken);
step.link();
+ if (_context->requiresExecutionContext) {
+ Instruction::CloneBlockContext clone;
+ bytecodeGenerator->addInstruction(clone);
+ }
statement(ast->expression);
bytecodeGenerator->jump().link(cond);
diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp
index d4abc59a8b..7d9dc25ced 100644
--- a/src/qml/compiler/qv4instr_moth.cpp
+++ b/src/qml/compiler/qv4instr_moth.cpp
@@ -415,6 +415,9 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
d << dumpRegister(reg, nFormals) << ", " << index;
MOTH_END_INSTR(PushBlockContext)
+ MOTH_BEGIN_INSTR(CloneBlockContext)
+ MOTH_END_INSTR(CloneBlockContext)
+
MOTH_BEGIN_INSTR(PushScriptContext)
d << index;
MOTH_END_INSTR(PushScriptContext)
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index d12d1a53cc..96ab593609 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -117,6 +117,7 @@ QT_BEGIN_NAMESPACE
#define INSTR_PushCatchContext(op) INSTRUCTION(op, PushCatchContext, 3, reg, index, name)
#define INSTR_PushWithContext(op) INSTRUCTION(op, PushWithContext, 1, reg)
#define INSTR_PushBlockContext(op) INSTRUCTION(op, PushBlockContext, 2, reg, index)
+#define INSTR_CloneBlockContext(op) INSTRUCTION(op, CloneBlockContext, 0)
#define INSTR_PushScriptContext(op) INSTRUCTION(op, PushScriptContext, 1, index)
#define INSTR_PopScriptContext(op) INSTRUCTION(op, PopScriptContext, 0)
#define INSTR_PopContext(op) INSTRUCTION(op, PopContext, 1, reg)
@@ -242,6 +243,7 @@ QT_BEGIN_NAMESPACE
F(PushCatchContext) \
F(PushWithContext) \
F(PushBlockContext) \
+ F(CloneBlockContext) \
F(PushScriptContext) \
F(PopScriptContext) \
F(PopContext) \
diff --git a/src/qml/jit/qv4jit.cpp b/src/qml/jit/qv4jit.cpp
index f659ddfb00..4f95232f0d 100644
--- a/src/qml/jit/qv4jit.cpp
+++ b/src/qml/jit/qv4jit.cpp
@@ -659,6 +659,19 @@ void BaselineJIT::generate_PushBlockContext(int reg, int index)
JIT_GENERATE_RUNTIME_CALL(pushBlockContextHelper, Assembler::IgnoreResult);
}
+static void cloneBlockContextHelper(QV4::Value *contextSlot)
+{
+ *contextSlot = Runtime::method_cloneBlockContext(static_cast<QV4::ExecutionContext *>(contextSlot));
+}
+
+void BaselineJIT::generate_CloneBlockContext()
+{
+ as->saveAccumulatorInFrame();
+ as->prepareCallWithArgCount(1);
+ as->passRegAsArg(CallData::Context, 0);
+ JIT_GENERATE_RUNTIME_CALL(cloneBlockContextHelper, Assembler::IgnoreResult);
+}
+
static void pushScriptContextHelper(QV4::Value *stack, ExecutionEngine *engine, int index)
{
stack[CallData::Context] = Runtime::method_createScriptContext(engine, index);
@@ -1236,6 +1249,9 @@ void BaselineJIT::collectLabelsInBytecode()
MOTH_BEGIN_INSTR(PushBlockContext)
MOTH_END_INSTR(PushBlockContext)
+ MOTH_BEGIN_INSTR(CloneBlockContext)
+ MOTH_END_INSTR(CloneBlockContext)
+
MOTH_BEGIN_INSTR(PushScriptContext)
MOTH_END_INSTR(PushScriptContext)
diff --git a/src/qml/jit/qv4jit_p.h b/src/qml/jit/qv4jit_p.h
index 97dd2ef2a5..333cf05f09 100644
--- a/src/qml/jit/qv4jit_p.h
+++ b/src/qml/jit/qv4jit_p.h
@@ -181,6 +181,7 @@ public:
void generate_PushCatchContext(int reg, int index, int name) override;
void generate_PushWithContext(int reg) override;
void generate_PushBlockContext(int reg, int index) override;
+ void generate_CloneBlockContext() override;
void generate_PushScriptContext(int index) override;
void generate_PopScriptContext() override;
void generate_PopContext(int reg) override;
diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp
index 8a6f1044b9..59b88c3160 100644
--- a/src/qml/jsruntime/qv4context.cpp
+++ b/src/qml/jsruntime/qv4context.cpp
@@ -59,7 +59,7 @@ Heap::CallContext *ExecutionContext::newBlockContext(CppStackFrame *frame, int b
Function *function = frame->v4Function;
Heap::InternalClass *ic = function->compilationUnit->runtimeBlocks.at(blockIndex);
- int nLocals = ic->size;
+ uint nLocals = ic->size;
size_t requiredMemory = sizeof(CallContext::Data) - sizeof(Value) + sizeof(Value) * nLocals;
ExecutionEngine *v4 = function->internalClass->engine;
@@ -77,6 +77,19 @@ Heap::CallContext *ExecutionContext::newBlockContext(CppStackFrame *frame, int b
return c;
}
+Heap::CallContext *ExecutionContext::cloneBlockContext(Heap::CallContext *context)
+{
+ uint nLocals = context->locals.alloc;
+ size_t requiredMemory = sizeof(CallContext::Data) - sizeof(Value) + sizeof(Value) * nLocals;
+
+ ExecutionEngine *v4 = context->internalClass->engine;
+ Heap::CallContext *c = v4->memoryManager->allocManaged<CallContext>(requiredMemory, context->internalClass);
+ memcpy(c, context, requiredMemory);
+
+ return c;
+
+}
+
Heap::CallContext *ExecutionContext::newCallContext(CppStackFrame *frame)
{
Function *function = frame->v4Function;
diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h
index cd99f162d2..26e64728dc 100644
--- a/src/qml/jsruntime/qv4context_p.h
+++ b/src/qml/jsruntime/qv4context_p.h
@@ -182,6 +182,7 @@ struct Q_QML_EXPORT ExecutionContext : public Managed
V4_INTERNALCLASS(ExecutionContext)
static Heap::CallContext *newBlockContext(QV4::CppStackFrame *frame, int blockIndex);
+ static Heap::CallContext *cloneBlockContext(Heap::CallContext *context);
static Heap::CallContext *newCallContext(QV4::CppStackFrame *frame);
Heap::ExecutionContext *newWithContext(Heap::Object *with);
static Heap::ExecutionContext *newCatchContext(CppStackFrame *frame, int blockIndex, Heap::String *exceptionVarName);
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 8bf6d6b73f..986684302c 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -1230,6 +1230,12 @@ ReturnedValue Runtime::method_createBlockContext(ExecutionContext *parent, int i
return parent->newBlockContext(e->currentStackFrame, index)->asReturnedValue();
}
+ReturnedValue Runtime::method_cloneBlockContext(ExecutionContext *previous)
+{
+ return ExecutionContext::cloneBlockContext(static_cast<Heap::CallContext *>(previous->d()))->asReturnedValue();
+}
+
+
ReturnedValue Runtime::method_createScriptContext(ExecutionEngine *engine, int index)
{
Q_ASSERT(engine->currentStackFrame->context()->d()->type == Heap::ExecutionContext::Type_GlobalContext ||
diff --git a/src/qml/jsruntime/qv4runtimeapi_p.h b/src/qml/jsruntime/qv4runtimeapi_p.h
index f707de00f8..c98433359b 100644
--- a/src/qml/jsruntime/qv4runtimeapi_p.h
+++ b/src/qml/jsruntime/qv4runtimeapi_p.h
@@ -128,6 +128,7 @@ struct ExceptionCheck<void (*)(QV4::NoThrowEngine *, A, B, C)> {
F(ReturnedValue, createCatchContext, (ExecutionContext *parent, int blockIndex, int exceptionVarNameIndex)) \
F(ReturnedValue, createBlockContext, (ExecutionContext *parent, int index)) \
F(ReturnedValue, createScriptContext, (ExecutionEngine *engine, int index)) \
+ F(ReturnedValue, cloneBlockContext, (ExecutionContext *previous)) \
F(ReturnedValue, popScriptContext, (ExecutionEngine *engine)) \
\
/* closures */ \
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index 3fadb6e670..5daead19d2 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -929,11 +929,18 @@ QV4::ReturnedValue VME::interpret(CppStackFrame &frame, const uchar *code)
MOTH_END_INSTR(PushWithContext)
MOTH_BEGIN_INSTR(PushBlockContext)
+ STORE_ACC();
STACK_VALUE(reg) = STACK_VALUE(CallData::Context);
ExecutionContext *c = static_cast<ExecutionContext *>(stack + CallData::Context);
STACK_VALUE(CallData::Context) = Runtime::method_createBlockContext(c, index);
MOTH_END_INSTR(PushBlockContext)
+ MOTH_BEGIN_INSTR(CloneBlockContext)
+ STORE_ACC();
+ ExecutionContext *c = static_cast<ExecutionContext *>(stack + CallData::Context);
+ STACK_VALUE(CallData::Context) = Runtime::method_cloneBlockContext(c);
+ MOTH_END_INSTR(CloneBlockContext)
+
MOTH_BEGIN_INSTR(PushScriptContext)
STACK_VALUE(CallData::Context) = Runtime::method_createScriptContext(engine, index);
MOTH_END_INSTR(PushScriptContext)
diff --git a/tests/auto/qml/ecmascripttests/TestExpectations b/tests/auto/qml/ecmascripttests/TestExpectations
index bb442e0125..991af3c63b 100644
--- a/tests/auto/qml/ecmascripttests/TestExpectations
+++ b/tests/auto/qml/ecmascripttests/TestExpectations
@@ -6414,7 +6414,6 @@ language/statements/for/dstr-var-obj-ptrn-id-init-fn-name-fn.js fails
language/statements/for/dstr-var-obj-ptrn-id-init-fn-name-gen.js fails
language/statements/for/head-lhs-let.js sloppyFails
language/statements/for/let-identifier-with-newline.js sloppyFails
-language/statements/for/scope-body-lex-boundary.js fails
language/statements/for/scope-body-lex-open.js fails
language/statements/for/tco-const-body.js strictFails
language/statements/for/tco-let-body.js strictFails
@@ -6620,11 +6619,6 @@ language/statements/let/global-closure-get-before-initialization.js fails
language/statements/let/global-closure-set-before-initialization.js fails
language/statements/let/global-use-before-initialization-in-declaration-statement.js fails
language/statements/let/global-use-before-initialization-in-prior-statement.js fails
-language/statements/let/syntax/let-closure-inside-condition.js fails
-language/statements/let/syntax/let-closure-inside-initialization.js fails
-language/statements/let/syntax/let-closure-inside-next-expression.js fails
-language/statements/let/syntax/let-iteration-variable-is-freshly-allocated-for-each-iteration-multi-let-binding.js fails
-language/statements/let/syntax/let-iteration-variable-is-freshly-allocated-for-each-iteration-single-let-binding.js fails
language/statements/let/syntax/let.js fails
language/statements/return/tco.js strictFails
language/statements/switch/scope-lex-open-case.js fails