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

Unified Diff: src/codegen-ia32.cc

Issue 16579: Experimental: fix a bug where we could have returns from a function... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: Created 11 years, 11 months 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/codegen-ia32.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/codegen-ia32.cc
===================================================================
--- src/codegen-ia32.cc (revision 1041)
+++ src/codegen-ia32.cc (working copy)
@@ -286,15 +286,33 @@
#endif
VisitStatements(body);
- // Generate a return statement if necessary. A NULL frame indicates
- // that control flow leaves the body on all paths and cannot fall
- // through.
+ // Handle the return from the function. If there is a valid frame,
+ // control flow can fall off the end of the body. Compiling a return
+ // statement will jump to the return sequence if it is already
+ // generated or generate it if not.
if (has_valid_frame()) {
+ ASSERT(!function_return_is_shadowed_);
Literal undefined(Factory::undefined_value());
ReturnStatement statement(&undefined);
statement.set_statement_pos(fun->end_position());
VisitReturnStatement(&statement);
}
+
+ // If the return target has dangling jumps to it, then we have not yet
+ // generated the return sequence. This can happen when (a) control
+ // does not flow off the end of the body so we did not compile an
+ // artificial return statement just above, and (b) there are return
+ // statements in the body but (c) they are all shadowed.
+ if (function_return_.is_linked()) {
Kasper Lund 2009/01/08 06:55:13 Should (or could) this really be an else if?
Kevin Millikin (Chromium) 2009/01/08 09:32:08 (It could and) maybe it should. I've changed it.
+ // There is no valid frame here. It is safe (also necessary) to
+ // load the return value into eax because the frame we will pick up by
+ // binding the function return target is prepared for the return by
+ // spilling all registers, and binding it will not generate merge
+ // code that could use eax.
+ ASSERT(!has_valid_frame());
+ __ mov(eax, Immediate(Factory::undefined_value()));
+ GenerateReturnSequence();
+ }
}
}
@@ -1647,28 +1665,38 @@
if (function_return_.is_bound()) {
function_return_.Jump();
} else {
- function_return_.Bind();
- if (FLAG_trace) {
- frame_->Push(eax); // Materialize result on the stack.
- frame_->CallRuntime(Runtime::kTraceExit, 1);
- }
+ GenerateReturnSequence();
+ }
+ }
+}
- // Add a label for checking the size of the code used for returning.
- Label check_exit_codesize;
- __ bind(&check_exit_codesize);
- // Leave the frame and return popping the arguments and the
- // receiver.
- frame_->Exit();
- __ ret((scope_->num_parameters() + 1) * kPointerSize);
- DeleteFrame();
+void CodeGenerator::GenerateReturnSequence() {
+ // The return value is a live (but not currently reference counted)
+ // reference to eax. This is safe because the frame we will pick up by
+ // binding the function return target does not contain a reference to eax
+ // (it is prepared for the return by spilling all registers) and binding
+ // will not emit merge code that could potentially use eax.
+ function_return_.Bind();
+ if (FLAG_trace) {
+ frame_->Push(eax); // Materialize result on the stack.
Kasper Lund 2009/01/08 06:55:13 Is this really okay when the frame is invalid? Can
Kevin Millikin (Chromium) 2009/01/08 09:32:08 It's OK here because we actually have a valid fram
+ frame_->CallRuntime(Runtime::kTraceExit, 1);
+ }
- // Check that the size of the code used for returning matches what is
- // expected by the debugger.
- ASSERT_EQ(Debug::kIa32JSReturnSequenceLength,
- __ SizeOfCodeGeneratedSince(&check_exit_codesize));
- }
- }
+ // Add a label for checking the size of the code used for returning.
+ Label check_exit_codesize;
Kasper Lund 2009/01/08 06:55:13 The more I look at this size checking construct, t
Kevin Millikin (Chromium) 2009/01/08 09:32:08 I think it's OK. The label's lifetime ends pretty
+ __ bind(&check_exit_codesize);
+
+ // Leave the frame and return popping the arguments and the
+ // receiver.
+ frame_->Exit();
+ __ ret((scope_->num_parameters() + 1) * kPointerSize);
+ DeleteFrame();
+
+ // Check that the size of the code used for returning matches what is
+ // expected by the debugger.
+ ASSERT_EQ(Debug::kIa32JSReturnSequenceLength,
+ __ SizeOfCodeGeneratedSince(&check_exit_codesize));
}
« no previous file with comments | « src/codegen-ia32.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698