aboutsummaryrefslogtreecommitdiffstats
path: root/qv4codegen.cpp
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@digia.com>2012-12-17 15:18:38 +0100
committerSimon Hausmann <simon.hausmann@digia.com>2012-12-17 20:26:38 +0100
commit4f22fcb2494e1e770edae4d08f394f93ed519740 (patch)
tree93a71571fa0f7f4ae73f94d67de62cc4ccf52df6 /qv4codegen.cpp
parent2d4daa564719d61191aa4907494e8a728fbe335b (diff)
Fix a bug in catch{}finally{} and simplify code
There was a bug in the implementation of unwindException(), that caused failures when called twice from one catch statement. Also refactor and simplify the TryStatement code further by introducing a rethrow builtin. Change-Id: I77bf37f1707042f402488ef2dfaf4e59bf8dc82a Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'qv4codegen.cpp')
-rw-r--r--qv4codegen.cpp56
1 files changed, 16 insertions, 40 deletions
diff --git a/qv4codegen.cpp b/qv4codegen.cpp
index 063243ad15..a15ba22ca4 100644
--- a/qv4codegen.cpp
+++ b/qv4codegen.cpp
@@ -2174,9 +2174,6 @@ bool Codegen::visit(TryStatement *ast)
TryCleanup tcf(_tryCleanup, ast->finallyExpression);
_tryCleanup = &tcf;
- IR::BasicBlock *after = _function->newBasicBlock();
- assert(catchBody || finallyBody);
-
int inCatch = 0;
if (catchBody) {
inCatch = _block->newTemp();
@@ -2190,7 +2187,7 @@ bool Codegen::visit(TryStatement *ast)
_block = tryBody;
statement(ast->statement);
- _block->JUMP(finallyBody ? finallyBody : after);
+ _block->JUMP(finallyBody);
// regular flow does not go into the catch statement
if (catchBody) {
@@ -2219,51 +2216,29 @@ bool Codegen::visit(TryStatement *ast)
// reset the variable name to the one from the outer scope
_env->members.insert(ast->catchExpression->name.toString(), hiddenIndex);
- _block->JUMP(finallyBody ? finallyBody : after);
+ _block->JUMP(finallyBody);
}
_tryCleanup = tcf.parent;
- if (finallyBody)
- generateFinallyBlock(finallyBody, !catchBody, ast->finallyExpression, hasException, after);
-
- _block = after;
-
- return false;
-}
-
-void Codegen::generateFinallyBlock(IR::BasicBlock *finallyBlock, bool exceptionNeedsSaving, Finally *ast, int hasException, IR::BasicBlock *after)
-{
- _block = finallyBlock;
-
- int exception;
- if (exceptionNeedsSaving) {
- // save the exception so we can rethrow it later.
- IR::BasicBlock *saveExceptionBlock = _function->newBasicBlock();
- IR::BasicBlock *realFinallyBlock = _function->newBasicBlock();
- _block->CJUMP(_block->TEMP(hasException), saveExceptionBlock, realFinallyBlock);
-
- _block = saveExceptionBlock;
- exception = saveExceptionBlock->newTemp();
- move(_block->TEMP(exception), _block->CALL(_block->NAME(IR::Name::builtin_get_exception, 0, 0), 0));
- _block->JUMP(realFinallyBlock);
-
- _block = realFinallyBlock;
- }
+ IR::BasicBlock *after = _function->newBasicBlock();
+ _block = finallyBody;
_block->EXP(_block->CALL(_block->NAME(IR::Name::builtin_delete_exception_handler, 0, 0), 0));
- if (ast && ast->statement)
- statement(ast->statement);
-
- if (exceptionNeedsSaving) {
- IR::BasicBlock *restoreExceptionBlock = _function->newBasicBlock();
- _block->CJUMP(_block->TEMP(hasException), restoreExceptionBlock, after);
- _block = restoreExceptionBlock;
- _block->MOVE(_block->TEMP(_returnAddress), _block->TEMP(exception));
- _block->JUMP(_throwBlock);
+ if (ast->finallyExpression && ast->finallyExpression->statement)
+ statement(ast->finallyExpression->statement);
+
+ if (!catchBody) {
+ IR::BasicBlock *rethrowBlock = _function->newBasicBlock();
+ _block->CJUMP(_block->TEMP(hasException), rethrowBlock, after);
+ _block = rethrowBlock;
+ _block->EXP(_block->CALL(_block->NAME(IR::Name::builtin_rethrow, 0, 0), 0));
} else {
_block->CJUMP(_block->TEMP(hasException), _throwBlock, after);
}
+ _block = after;
+
+ return false;
}
void Codegen::unwindException(Codegen::TryCleanup *outest)
@@ -2277,6 +2252,7 @@ void Codegen::unwindException(Codegen::TryCleanup *outest)
if (tc->finally && tc->finally->statement)
statement(tc->finally->statement);
}
+ qSwap(_tryCleanup, tryCleanup);
}
bool Codegen::visit(VariableStatement *ast)