Author: [email protected]
Date: Thu Jan 8 01:42:14 2009
New Revision: 1043
Modified:
branches/experimental/toiger/src/codegen-ia32.cc
branches/experimental/toiger/src/codegen-ia32.h
Log:
Experimental: fix a bug where we could have returns from a function
but never generate the return sequence.
Review URL: http://codereview.chromium.org/16579
Modified: branches/experimental/toiger/src/codegen-ia32.cc
==============================================================================
--- branches/experimental/toiger/src/codegen-ia32.cc (original)
+++ branches/experimental/toiger/src/codegen-ia32.cc Thu Jan 8 01:42:14
2009
@@ -286,14 +286,29 @@
#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 (has_valid_frame()) {
+ // If there is a valid frame, control flow can fall off the end of
+ // the body. In that case there is an implicit return statement.
+ // Compiling a return statement will jump to the return sequence if
+ // it is already generated or generate it if not.
+ ASSERT(!function_return_is_shadowed_);
Literal undefined(Factory::undefined_value());
ReturnStatement statement(&undefined);
statement.set_statement_pos(fun->end_position());
VisitReturnStatement(&statement);
+ } else if (function_return_.is_linked()) {
+ // 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.
+ //
+ // There is no valid frame here but it is safe (also necessary) to
+ // load the return value into eax.
+ __ mov(eax, Immediate(Factory::undefined_value()));
+ function_return_.Bind();
+ GenerateReturnSequence();
}
}
}
@@ -1648,27 +1663,37 @@
function_return_.Jump();
} else {
function_return_.Bind();
- if (FLAG_trace) {
- frame_->Push(eax); // Materialize result on the stack.
- frame_->CallRuntime(Runtime::kTraceExit, 1);
- }
-
- // 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();
-
- // 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));
+ GenerateReturnSequence();
}
}
+}
+
+
+void CodeGenerator::GenerateReturnSequence() {
+ // The return value is a live (but not currently reference counted)
+ // reference to eax. This is safe because the current frame does not
+ // contain a reference to eax (it is prepared for the return by spilling
+ // all registers).
+ ASSERT(has_valid_frame());
+ if (FLAG_trace) {
+ frame_->Push(eax); // Materialize result on the stack.
+ frame_->CallRuntime(Runtime::kTraceExit, 1);
+ }
+
+ // 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();
+
+ // 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));
}
Modified: branches/experimental/toiger/src/codegen-ia32.h
==============================================================================
--- branches/experimental/toiger/src/codegen-ia32.h (original)
+++ branches/experimental/toiger/src/codegen-ia32.h Thu Jan 8 01:42:14 2009
@@ -264,6 +264,12 @@
// Main code generation function
void GenCode(FunctionLiteral* fun);
+ // Generate the return sequence code. Should be called no more than once
+ // per compiled function (it binds the return target, which can not be
+ // done more than once). The return value is assumed to be in eax by the
+ // code generated.
+ void GenerateReturnSequence();
+
// The following are used by class Reference.
void LoadReference(Reference* ref);
void UnloadReference(Reference* ref);
--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---