Chromium Code Reviews| 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 __ |