diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2019-04-18 15:37:17 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2019-04-30 16:24:45 +0000 |
commit | 9b6c20cb719542cfcf3e031afd5b2b0b1cd3833e (patch) | |
tree | 2130fe9f9179eccb604c3e3eacc18cbd62202b0b /src/qml/compiler | |
parent | d7db2ef07bf6f0f7c39f342aed94d51cca42df11 (diff) |
Make JavaScript execution interruptible
Add an atomic isInterrupted flag to BaseEngine and check that in
addition to the hasException flag on checkException(). Add some more
exception checks to cover all possible infinite loops. Also, remove the
writeBarrierActive member from QV4::EngineBase. It isn't used.
Fixes: QTBUG-49080
Change-Id: I86b3114e3e61aff3e5eb9b020749a908ed801c2b
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/compiler')
-rw-r--r-- | src/qml/compiler/qv4bytecodegenerator_p.h | 6 | ||||
-rw-r--r-- | src/qml/compiler/qv4codegen.cpp | 7 | ||||
-rw-r--r-- | src/qml/compiler/qv4instr_moth.cpp | 3 | ||||
-rw-r--r-- | src/qml/compiler/qv4instr_moth_p.h | 2 |
4 files changed, 18 insertions, 0 deletions
diff --git a/src/qml/compiler/qv4bytecodegenerator_p.h b/src/qml/compiler/qv4bytecodegenerator_p.h index ab8661dbe3..acd4aa62ea 100644 --- a/src/qml/compiler/qv4bytecodegenerator_p.h +++ b/src/qml/compiler/qv4bytecodegenerator_p.h @@ -209,6 +209,12 @@ QT_WARNING_POP addJumpInstruction(Instruction::JumpTrue()).link(target); } + void checkException() + { + Instruction::CheckException chk; + addInstruction(chk); + } + void setUnwindHandler(ExceptionHandler *handler) { currentExceptionHandler = handler; diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index 1537ce408d..1bf0e7147d 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -1201,6 +1201,7 @@ bool Codegen::visit(ArrayPattern *ast) lhsValue.loadInAccumulator(); pushAccumulator(); + bytecodeGenerator->checkException(); bytecodeGenerator->jump().link(in); end.link(); } @@ -3201,11 +3202,13 @@ bool Codegen::visit(DoWhileStatement *ast) cond.link(); if (AST::cast<TrueLiteral *>(ast->expression)) { // do {} while (true) -> just jump back to the loop body, no need to generate a condition + bytecodeGenerator->checkException(); bytecodeGenerator->jump().link(body); } else if (AST::cast<FalseLiteral *>(ast->expression)) { // do {} while (false) -> fall through, no need to generate a condition } else { TailCallBlocker blockTailCalls(this); + bytecodeGenerator->checkException(); condition(ast->expression, &body, &end, false); } @@ -3322,6 +3325,7 @@ bool Codegen::visit(ForEachStatement *ast) setJumpOutLocation(bytecodeGenerator, ast->statement, ast->forToken); } + bytecodeGenerator->checkException(); bytecodeGenerator->jump().link(in); error: @@ -3370,6 +3374,7 @@ bool Codegen::visit(ForStatement *ast) bytecodeGenerator->addInstruction(clone); } statement(ast->expression); + bytecodeGenerator->checkException(); bytecodeGenerator->jump().link(cond); end.link(); @@ -3652,6 +3657,8 @@ bool Codegen::visit(WhileStatement *ast) ControlFlowLoop flow(this, &end, &cond); bytecodeGenerator->addLoopStart(cond); + bytecodeGenerator->checkException(); + if (!AST::cast<TrueLiteral *>(ast->expression)) { TailCallBlocker blockTailCalls(this); condition(ast->expression, &start, &end, true); diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp index e022d14264..5148154a6a 100644 --- a/src/qml/compiler/qv4instr_moth.cpp +++ b/src/qml/compiler/qv4instr_moth.cpp @@ -539,6 +539,9 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st d << ABSOLUTE_OFFSET(); MOTH_END_INSTR(JumpNoException) + MOTH_BEGIN_INSTR(CheckException) + MOTH_END_INSTR(CheckException) + MOTH_BEGIN_INSTR(CmpEqNull) MOTH_END_INSTR(CmpEqNull) diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h index 6421fc9d67..35a5fdfba5 100644 --- a/src/qml/compiler/qv4instr_moth_p.h +++ b/src/qml/compiler/qv4instr_moth_p.h @@ -152,6 +152,7 @@ QT_BEGIN_NAMESPACE #define INSTR_JumpFalse(op) INSTRUCTION(op, JumpFalse, 1, offset) #define INSTR_JumpNotUndefined(op) INSTRUCTION(op, JumpNotUndefined, 1, offset) #define INSTR_JumpNoException(op) INSTRUCTION(op, JumpNoException, 1, offset) +#define INSTR_CheckException(op) INSTRUCTION(op, CheckException, 0) #define INSTR_CmpEqNull(op) INSTRUCTION(op, CmpEqNull, 0) #define INSTR_CmpNeNull(op) INSTRUCTION(op, CmpNeNull, 0) #define INSTR_CmpEqInt(op) INSTRUCTION(op, CmpEqInt, 1, lhs) @@ -241,6 +242,7 @@ QT_BEGIN_NAMESPACE F(JumpFalse) \ F(JumpNoException) \ F(JumpNotUndefined) \ + F(CheckException) \ F(CmpEqNull) \ F(CmpNeNull) \ F(CmpEqInt) \ |