Index: src/fast-codegen.cc |
diff --git a/src/fast-codegen.cc b/src/fast-codegen.cc |
index e01da2d5e9bac67ad9e2ec2d406d8aebcb6bc10d..f1bee8bd51f3065a94226898e9d54e1c2ca25dbd 100644 |
--- a/src/fast-codegen.cc |
+++ b/src/fast-codegen.cc |
@@ -489,7 +489,53 @@ void FastCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { |
void FastCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) { |
- UNREACHABLE(); |
+ // The try-finally construct can enter the finally block in three ways: |
Kevin Millikin (Chromium)
2009/12/10 13:51:12
Consider some judicious code generator comments, t
|
+ // 1. By exiting the try-block normally, |
+ // 2. by exiting the try-block with a function-local control flow transfer |
+ // (break/continue/return), or |
+ // 3. by exiting the try-block with a thrown exception. |
+ // |
+ // Normal exit and local control flow removes the try-handler before calling |
+ // the fially block through finally_entry label. |
Kevin Millikin (Chromium)
2009/12/10 13:51:12
"fially" ==> "finally"
Lasse Reichstein
2009/12/16 08:43:30
Fixed
|
+ // Throwing an exception follows the try-handler chain, which consumes |
+ // the try handler, and then enters the finally block through the |
+ // finally_entry label. |
+ // The finally block must assume a return address on top of the stack |
+ // and a value in the result register (rax/eax/r0), both of which must |
Kevin Millikin (Chromium)
2009/12/10 13:51:12
Probably should note that the value may be the ret
Lasse Reichstein
2009/12/16 08:43:30
Done
|
+ // be preserved. The return address isn't GC-safe, so it should be |
+ // cooked before GC. |
+ Label finally_entry; |
+ Label try_handler_setup; |
+ |
+ // Jump to try-handler setup and try-block code. Use call to put try-handler |
+ // address on stack. |
+ __ Call(&try_handler_setup); |
+ |
+ // This code is only executed during stack-handler traversal when an |
+ // exception is thrown. |
+ // Call the finally block and then rethrow the exception. |
+ __ Call(&finally_entry); |
+ ThrowException(); |
+ |
+ { |
+ // Finally block implementation. |
+ __ bind(&finally_entry); |
+ Finally finally_block(this); |
+ EnterFinallyBlock(); |
+ Visit(stmt->finally_block()); |
Kevin Millikin (Chromium)
2009/12/10 13:51:12
Isn't it OK to VisitStatements the body of this bl
Lasse Reichstein
2009/12/16 08:43:30
It should be ok (you can't label the blocks, so th
|
+ ReturnFromFinallyBlock(); // Performs a return to the calling code. |
Kevin Millikin (Chromium)
2009/12/10 13:51:12
Can we call this ExitFinallyBlock, to parallel Ent
Lasse Reichstein
2009/12/16 08:43:30
Fixed.
(The point was that it actually did a retur
|
+ } |
+ |
+ __ bind(&try_handler_setup); |
+ { |
+ // Setup try handler (stack pointer registers). |
+ __ PushTryHandler(IN_JAVASCRIPT, TRY_FINALLY_HANDLER); |
Kevin Millikin (Chromium)
2009/12/10 13:51:12
It seems nicer to properly nest the Push/Pop of th
Lasse Reichstein
2009/12/16 08:43:30
Done
|
+ TryFinally try_block(this, &finally_entry); |
+ VisitStatements(stmt->try_block()->statements()); |
+ __ PopTryHandler(); |
+ } |
+ // Execute the finally block on the way out. |
+ __ Call(&finally_entry); |
} |
@@ -627,6 +673,21 @@ int FastCodeGenerator::TryCatch::Exit(int stack_depth) { |
} |
+int FastCodeGenerator::TryFinally::Exit(int stack_depth) { |
+ __ Drop(stack_depth); |
+ __ PopTryHandler(); |
+ __ Call(finally_entry_); |
+ return 0; |
+} |
+ |
+ |
+int FastCodeGenerator::TryCatch::Exit(int stack_depth) { |
+ __ Drop(stack_depth); |
+ __ PopTryHandler(); |
+ return 0; |
+} |
+ |
+ |
#undef __ |