Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(191)

Unified Diff: src/full-codegen.cc

Issue 8462010: Add a level of indirection to exception handler addresses. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Incorporate review changes. Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/full-codegen.h ('k') | src/heap.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/full-codegen.cc
diff --git a/src/full-codegen.cc b/src/full-codegen.cc
index 1589b86a59785ea3928aa4ae8b4e724354462131..79427524860b3c1d99e26a443f606969ff9deb0a 100644
--- a/src/full-codegen.cc
+++ b/src/full-codegen.cc
@@ -286,6 +286,7 @@ bool FullCodeGenerator::MakeCode(CompilationInfo* info) {
code->set_optimizable(info->IsOptimizable());
cgen.PopulateDeoptimizationData(code);
code->set_has_deoptimization_support(info->HasDeoptimizationSupport());
+ code->set_handler_table(*cgen.handler_table());
#ifdef ENABLE_DEBUGGER_SUPPORT
code->set_has_debug_break_slots(
info->isolate()->debugger()->IsDebuggerActive());
@@ -1086,20 +1087,17 @@ void FullCodeGenerator::VisitForStatement(ForStatement* stmt) {
void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
Comment cmnt(masm_, "[ TryCatchStatement");
SetStatementPosition(stmt);
- // The try block adds a handler to the exception handler chain
- // before entering, and removes it again when exiting normally.
- // If an exception is thrown during execution of the try block,
- // control is passed to the handler, which also consumes the handler.
- // At this point, the exception is in a register, and store it in
- // the temporary local variable (prints as ".catch-var") before
- // executing the catch block. The catch block has been rewritten
- // to introduce a new scope to bind the catch variable and to remove
- // that scope again afterwards.
-
- Label try_handler_setup, done;
- __ Call(&try_handler_setup);
- // Try handler code, exception in result register.
-
+ // The try block adds a handler to the exception handler chain before
+ // entering, and removes it again when exiting normally. If an exception
+ // is thrown during execution of the try block, the handler is consumed
+ // and control is passed to the catch block with the exception in the
+ // result register.
+
+ Label try_entry, handler_entry, exit;
+ __ jmp(&try_entry);
+ __ bind(&handler_entry);
+ handler_table()->set(stmt->index(), Smi::FromInt(handler_entry.pos()));
+ // Exception handler code, the exception is in the result register.
// Extend the context before executing the catch block.
{ Comment cmnt(masm_, "[ Extend catch context");
__ Push(stmt->variable()->name());
@@ -1113,24 +1111,23 @@ void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
Scope* saved_scope = scope();
scope_ = stmt->scope();
ASSERT(scope_->declarations()->is_empty());
- { WithOrCatch body(this);
+ { WithOrCatch catch_body(this);
Visit(stmt->catch_block());
}
// Restore the context.
LoadContextField(context_register(), Context::PREVIOUS_INDEX);
StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
scope_ = saved_scope;
- __ jmp(&done);
+ __ jmp(&exit);
// Try block code. Sets up the exception handler chain.
- __ bind(&try_handler_setup);
- {
- TryCatch try_block(this);
- __ PushTryHandler(IN_JAVASCRIPT, TRY_CATCH_HANDLER);
+ __ bind(&try_entry);
+ __ PushTryHandler(IN_JAVASCRIPT, TRY_CATCH_HANDLER, stmt->index());
+ { TryCatch try_body(this);
Visit(stmt->try_block());
- __ PopTryHandler();
}
- __ bind(&done);
+ __ PopTryHandler();
+ __ bind(&exit);
}
@@ -1142,12 +1139,12 @@ void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
//
// The try-finally construct can enter the finally block in three ways:
// 1. By exiting the try-block normally. This removes the try-handler and
- // calls the finally block code before continuing.
+ // calls the finally block code before continuing.
// 2. By exiting the try-block with a function-local control flow transfer
// (break/continue/return). The site of the, e.g., break removes the
// try handler and calls the finally block code before continuing
// its outward control transfer.
- // 3. by exiting the try-block with a thrown exception.
+ // 3. By exiting the try-block with a thrown exception.
// This can happen in nested function calls. It traverses the try-handler
// chain and consumes the try-handler entry before jumping to the
// handler code. The handler code then calls the finally-block before
@@ -1158,44 +1155,39 @@ void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
// exception) in the result register (rax/eax/r0), both of which must
// be preserved. The return address isn't GC-safe, so it should be
// cooked before GC.
- Label finally_entry;
- Label try_handler_setup;
-
- // Setup the try-handler chain. Use a call to
- // Jump to try-handler setup and try-block code. Use call to put try-handler
- // address on stack.
- __ Call(&try_handler_setup);
- // Try handler code. Return address of call is pushed on handler stack.
- {
- // This code is only executed during stack-handler traversal when an
- // exception is thrown. The exception is in the result register, which
- // is retained by the finally block.
- // Call the finally block and then rethrow the exception if it returns.
- __ Call(&finally_entry);
- __ push(result_register());
- __ CallRuntime(Runtime::kReThrow, 1);
- }
+ Label try_entry, handler_entry, finally_entry;
+
+ // Jump to try-handler setup and try-block code.
+ __ jmp(&try_entry);
+ __ bind(&handler_entry);
+ handler_table()->set(stmt->index(), Smi::FromInt(handler_entry.pos()));
+ // Exception handler code. This code is only executed when an exception
+ // is thrown. The exception is in the result register, and must be
+ // preserved by the finally block. Call the finally block and then
+ // rethrow the exception if it returns.
+ __ Call(&finally_entry);
+ __ push(result_register());
+ __ CallRuntime(Runtime::kReThrow, 1);
+ // Finally block implementation.
__ bind(&finally_entry);
- {
- // Finally block implementation.
- Finally finally_block(this);
- EnterFinallyBlock();
+ EnterFinallyBlock();
+ { Finally finally_body(this);
Visit(stmt->finally_block());
- ExitFinallyBlock(); // Return to the calling code.
}
+ ExitFinallyBlock(); // Return to the calling code.
- __ bind(&try_handler_setup);
- {
- // Setup try handler (stack pointer registers).
- TryFinally try_block(this, &finally_entry);
- __ PushTryHandler(IN_JAVASCRIPT, TRY_FINALLY_HANDLER);
+ // Setup try handler.
+ __ bind(&try_entry);
+ __ PushTryHandler(IN_JAVASCRIPT, TRY_FINALLY_HANDLER, stmt->index());
+ { TryFinally try_body(this, &finally_entry);
Visit(stmt->try_block());
- __ PopTryHandler();
}
+ __ PopTryHandler();
// Execute the finally block on the way out. Clobber the unpredictable
- // value in the accumulator with one that's safe for GC. The finally
- // block will unconditionally preserve the accumulator on the stack.
+ // value in the result register with one that's safe for GC because the
+ // finally block will unconditionally preserve the result register on the
+ // stack.
ClearAccumulator();
__ Call(&finally_entry);
}
« no previous file with comments | « src/full-codegen.h ('k') | src/heap.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698