Author: [email protected]
Date: Mon Feb 23 03:36:53 2009
New Revision: 1336
Modified:
branches/experimental/toiger/src/codegen-arm.cc
branches/experimental/toiger/src/codegen-ia32.cc
Log:
Experimental: cleanup the handling of try...catch and try...finally on
ARM. This fixes some debug test failures that were due to failed
assertions about stack height.
Review URL: http://codereview.chromium.org/28021
Modified: branches/experimental/toiger/src/codegen-arm.cc
==============================================================================
--- branches/experimental/toiger/src/codegen-arm.cc (original)
+++ branches/experimental/toiger/src/codegen-arm.cc Mon Feb 23 03:36:53 2009
@@ -2025,18 +2025,21 @@
// label.
int nof_escapes = node->escaping_targets()->length();
List<ShadowTarget*> shadows(1 + nof_escapes);
+
+ // Add the shadow target for the function return.
+ static const int kReturnShadowIndex = 0;
shadows.Add(new ShadowTarget(&function_return_));
+ bool function_return_was_shadowed = function_return_is_shadowed_;
+ function_return_is_shadowed_ = true;
+ ASSERT(shadows[kReturnShadowIndex]->other_target() == &function_return_);
+
+ // Add the remaining shadow targets.
for (int i = 0; i < nof_escapes; i++) {
shadows.Add(new ShadowTarget(node->escaping_targets()->at(i)));
}
- bool function_return_was_shadowed = function_return_is_shadowed_;
- function_return_is_shadowed_ = true;
// Generate code for the statements in the try block.
VisitStatementsAndSpill(node->try_block()->statements());
- if (frame_ != NULL) {
- frame_->Drop(); // Discard the result.
- }
// Stop the introduced shadowing and count the number of required
unlinks.
// After shadowing stops, the original labels are unshadowed and the
@@ -2048,17 +2051,14 @@
}
function_return_is_shadowed_ = function_return_was_shadowed;
- const int kNextIndex = (StackHandlerConstants::kNextOffset
- + StackHandlerConstants::kAddressDisplacement)
- / kPointerSize;
+ const int kNextIndex = StackHandlerConstants::kNextOffset / kPointerSize;
// If we can fall off the end of the try block, unlink from try chain.
- if (frame_ != NULL) {
- __ ldr(r1, frame_->ElementAt(kNextIndex)); // read next_sp
+ if (has_valid_frame()) {
+ // The next handler address is at kNextIndex in the stack.
+ __ ldr(r1, frame_->ElementAt(kNextIndex));
__ mov(r3, Operand(ExternalReference(Top::k_handler_address)));
__ str(r1, MemOperand(r3));
- ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is
code
- frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
- // Code slot popped.
+ frame_->Drop(StackHandlerConstants::kSize / kPointerSize);
if (nof_unlinks > 0) {
exit.Jump();
}
@@ -2070,19 +2070,27 @@
if (shadows[i]->is_linked()) {
// Unlink from try chain;
shadows[i]->Bind();
+ // Because we can be jumping here (to spilled code) from unspilled
+ // code, we need to reestablish a spilled frame at this block.
+ frame_->SpillAll();
// Reload sp from the top handler, because some statements that we
// break from (eg, for...in) may have left stuff on the stack.
__ mov(r3, Operand(ExternalReference(Top::k_handler_address)));
__ ldr(sp, MemOperand(r3));
- frame_->Forget(frame_->height() - handler_height);
-
- __ ldr(r1, frame_->ElementAt(kNextIndex));
+ // The stack pointer was restored to just below the code slot
+ // (the topmost slot) in the handler.
+ frame_->Forget(frame_->height() - handler_height + 1);
+
+ // kNextIndex is off by one because the code slot has already
+ // been dropped.
+ __ ldr(r1, frame_->ElementAt(kNextIndex - 1));
__ str(r1, MemOperand(r3));
- ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is
code
frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
- // Code slot popped.
- frame_->Forget(1);
+
+ if (!function_return_is_shadowed_ && i == kReturnShadowIndex) {
+ frame_->PrepareForReturn();
+ }
shadows[i]->other_target()->Jump();
}
}
@@ -2116,7 +2124,6 @@
__ mov(r2, Operand(Smi::FromInt(THROWING)));
finally_block.Jump();
-
// --- Try block ---
try_block.Bind();
@@ -2131,12 +2138,18 @@
// label.
int nof_escapes = node->escaping_targets()->length();
List<ShadowTarget*> shadows(1 + nof_escapes);
+
+ // Add the shadow target for the function return.
+ static const int kReturnShadowIndex = 0;
shadows.Add(new ShadowTarget(&function_return_));
+ bool function_return_was_shadowed = function_return_is_shadowed_;
+ function_return_is_shadowed_ = true;
+ ASSERT(shadows[kReturnShadowIndex]->other_target() == &function_return_);
+
+ // Add the remaining shadow targets.
for (int i = 0; i < nof_escapes; i++) {
shadows.Add(new ShadowTarget(node->escaping_targets()->at(i)));
}
- bool function_return_was_shadowed = function_return_is_shadowed_;
- function_return_is_shadowed_ = true;
// Generate code for the statements in the try block.
VisitStatementsAndSpill(node->try_block()->statements());
@@ -2153,7 +2166,7 @@
// If we can fall off the end of the try block, set the state on the
stack
// to FALLING.
- if (frame_ != NULL) {
+ if (has_valid_frame()) {
__ mov(r0, Operand(Factory::undefined_value())); // fake TOS
frame_->EmitPush(r0);
__ mov(r2, Operand(Smi::FromInt(FALLING)));
@@ -2166,13 +2179,17 @@
// have been jumped to.
for (int i = 0; i <= nof_escapes; i++) {
if (shadows[i]->is_linked()) {
+ // Because we can be jumping here (to spilled code) from
+ // unspilled code, we need to reestablish a spilled frame at
+ // this block.
shadows[i]->Bind();
- if (shadows[i]->other_target() == &function_return_) {
+ frame_->SpillAll();
+ if (i == kReturnShadowIndex) {
// If this label shadowed the function return, materialize the
// return value on the stack.
frame_->EmitPush(r0);
} else {
- // Fake TOS for labels that shadowed breaks and continues.
+ // Fake TOS for targets that shadowed breaks and continues.
__ mov(r0, Operand(Factory::undefined_value()));
frame_->EmitPush(r0);
}
@@ -2184,21 +2201,25 @@
// Unlink from try chain;
unlink.Bind();
- frame_->EmitPop(r0); // Store TOS in r0 across stack manipulation
+ // Preserve TOS result in r0 across stack manipulation.
+ frame_->EmitPop(r0);
// Reload sp from the top handler, because some statements that we
// break from (eg, for...in) may have left stuff on the stack.
__ mov(r3, Operand(ExternalReference(Top::k_handler_address)));
__ ldr(sp, MemOperand(r3));
- frame_->Forget(frame_->height() - handler_height);
+ // The stack pointer was restored to just below the code slot
+ // (the topmost slot) in the handler.
+ frame_->Forget(frame_->height() - handler_height + 1);
const int kNextIndex = (StackHandlerConstants::kNextOffset
+ StackHandlerConstants::kAddressDisplacement)
/ kPointerSize;
__ ldr(r1, frame_->ElementAt(kNextIndex));
__ str(r1, MemOperand(r3));
ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code
+ // Drop the rest of the handler (not including the already dropped
+ // code slot).
frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
- // Code slot popped.
- frame_->Forget(1);
+ // Restore the result to TOS.
frame_->EmitPush(r0);
// --- Finally block ---
@@ -2218,7 +2239,7 @@
VisitStatementsAndSpill(node->finally_block()->statements());
break_stack_height_ -= kFinallyStackSize;
- if (frame_ != NULL) {
+ if (has_valid_frame()) {
JumpTarget exit(this);
// Restore state and return value or faked TOS.
frame_->EmitPop(r2);
@@ -2228,14 +2249,16 @@
// shadowing labels.
for (int i = 0; i <= nof_escapes; i++) {
if (shadows[i]->is_bound()) {
+ JumpTarget* original = shadows[i]->other_target();
__ cmp(r2, Operand(Smi::FromInt(JUMPING + i)));
- if (shadows[i]->other_target() != &function_return_) {
- JumpTarget next(this);
- next.Branch(ne);
- shadows[i]->other_target()->Jump();
- next.Bind();
+ if (!function_return_is_shadowed_ && i == kReturnShadowIndex) {
+ JumpTarget skip(this);
+ skip.Branch(ne);
+ frame_->PrepareForReturn();
+ original->Jump();
+ skip.Bind();
} else {
- shadows[i]->other_target()->Branch(eq);
+ original->Branch(eq);
}
}
}
Modified: branches/experimental/toiger/src/codegen-ia32.cc
==============================================================================
--- branches/experimental/toiger/src/codegen-ia32.cc (original)
+++ branches/experimental/toiger/src/codegen-ia32.cc Mon Feb 23 03:36:53
2009
@@ -2654,10 +2654,10 @@
// If we can fall off the end of the try block, unlink from try chain.
if (has_valid_frame()) {
+ // The TOS is the next handler address.
frame_->EmitPop(eax);
- __ mov(Operand::StaticVariable(handler_address), eax); // TOS ==
next_sp
+ __ mov(Operand::StaticVariable(handler_address), eax);
frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
- // next_sp popped.
if (nof_unlinks > 0) {
exit.Jump();
}
@@ -2668,10 +2668,9 @@
for (int i = 0; i <= nof_escapes; i++) {
if (shadows[i]->is_linked()) {
// Unlink from try chain; be careful not to destroy the TOS.
- //
+ shadows[i]->Bind();
// Because we can be jumping here (to spilled code) from unspilled
// code, we need to reestablish a spilled frame at this block.
- shadows[i]->Bind();
frame_->SpillAll();
// Reload sp from the top handler, because some statements that we
@@ -2718,7 +2717,6 @@
// In case of thrown exceptions, this is where we continue.
__ Set(ecx, Immediate(Smi::FromInt(THROWING)));
finally_block.Jump();
-
// --- Try block ---
try_block.Bind();
--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---