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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/codegen-ia32.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after
279 bool is_builtin = Bootstrapper::IsActive(); 279 bool is_builtin = Bootstrapper::IsActive();
280 bool should_trace = 280 bool should_trace =
281 is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls; 281 is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls;
282 if (should_trace) { 282 if (should_trace) {
283 frame_->CallRuntime(Runtime::kDebugTrace, 0); 283 frame_->CallRuntime(Runtime::kDebugTrace, 0);
284 // Ignore the return value. 284 // Ignore the return value.
285 } 285 }
286 #endif 286 #endif
287 VisitStatements(body); 287 VisitStatements(body);
288 288
289 // Generate a return statement if necessary. A NULL frame indicates 289 // Handle the return from the function. If there is a valid frame,
290 // that control flow leaves the body on all paths and cannot fall 290 // control flow can fall off the end of the body. Compiling a return
291 // through. 291 // statement will jump to the return sequence if it is already
292 // generated or generate it if not.
292 if (has_valid_frame()) { 293 if (has_valid_frame()) {
294 ASSERT(!function_return_is_shadowed_);
293 Literal undefined(Factory::undefined_value()); 295 Literal undefined(Factory::undefined_value());
294 ReturnStatement statement(&undefined); 296 ReturnStatement statement(&undefined);
295 statement.set_statement_pos(fun->end_position()); 297 statement.set_statement_pos(fun->end_position());
296 VisitReturnStatement(&statement); 298 VisitReturnStatement(&statement);
297 } 299 }
300
301 // If the return target has dangling jumps to it, then we have not yet
302 // generated the return sequence. This can happen when (a) control
303 // does not flow off the end of the body so we did not compile an
304 // artificial return statement just above, and (b) there are return
305 // statements in the body but (c) they are all shadowed.
306 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.
307 // There is no valid frame here. It is safe (also necessary) to
308 // load the return value into eax because the frame we will pick up by
309 // binding the function return target is prepared for the return by
310 // spilling all registers, and binding it will not generate merge
311 // code that could use eax.
312 ASSERT(!has_valid_frame());
313 __ mov(eax, Immediate(Factory::undefined_value()));
314 GenerateReturnSequence();
315 }
298 } 316 }
299 } 317 }
300 318
301 // Adjust for function-level loop nesting. 319 // Adjust for function-level loop nesting.
302 loop_nesting_ -= fun->loop_nesting(); 320 loop_nesting_ -= fun->loop_nesting();
303 321
304 // Code generation state must be reset. 322 // Code generation state must be reset.
305 ASSERT(state_ == NULL); 323 ASSERT(state_ == NULL);
306 ASSERT(loop_nesting() == 0); 324 ASSERT(loop_nesting() == 0);
307 ASSERT(!function_return_is_shadowed_); 325 ASSERT(!function_return_is_shadowed_);
(...skipping 1332 matching lines...) Expand 10 before | Expand all | Expand 10 after
1640 result.ToRegister(eax); 1658 result.ToRegister(eax);
1641 // TODO(): Instead of explictly calling Unuse on the result, it 1659 // TODO(): Instead of explictly calling Unuse on the result, it
1642 // might be better to pass the result to Jump and Bind below. 1660 // might be better to pass the result to Jump and Bind below.
1643 result.Unuse(); 1661 result.Unuse();
1644 1662
1645 // If the function return label is already bound, we reuse the 1663 // If the function return label is already bound, we reuse the
1646 // code by jumping to the return site. 1664 // code by jumping to the return site.
1647 if (function_return_.is_bound()) { 1665 if (function_return_.is_bound()) {
1648 function_return_.Jump(); 1666 function_return_.Jump();
1649 } else { 1667 } else {
1650 function_return_.Bind(); 1668 GenerateReturnSequence();
1651 if (FLAG_trace) {
1652 frame_->Push(eax); // Materialize result on the stack.
1653 frame_->CallRuntime(Runtime::kTraceExit, 1);
1654 }
1655
1656 // Add a label for checking the size of the code used for returning.
1657 Label check_exit_codesize;
1658 __ bind(&check_exit_codesize);
1659
1660 // Leave the frame and return popping the arguments and the
1661 // receiver.
1662 frame_->Exit();
1663 __ ret((scope_->num_parameters() + 1) * kPointerSize);
1664 DeleteFrame();
1665
1666 // Check that the size of the code used for returning matches what is
1667 // expected by the debugger.
1668 ASSERT_EQ(Debug::kIa32JSReturnSequenceLength,
1669 __ SizeOfCodeGeneratedSince(&check_exit_codesize));
1670 } 1669 }
1671 } 1670 }
1672 } 1671 }
1673 1672
1674 1673
1674 void CodeGenerator::GenerateReturnSequence() {
1675 // The return value is a live (but not currently reference counted)
1676 // reference to eax. This is safe because the frame we will pick up by
1677 // binding the function return target does not contain a reference to eax
1678 // (it is prepared for the return by spilling all registers) and binding
1679 // will not emit merge code that could potentially use eax.
1680 function_return_.Bind();
1681 if (FLAG_trace) {
1682 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
1683 frame_->CallRuntime(Runtime::kTraceExit, 1);
1684 }
1685
1686 // Add a label for checking the size of the code used for returning.
1687 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
1688 __ bind(&check_exit_codesize);
1689
1690 // Leave the frame and return popping the arguments and the
1691 // receiver.
1692 frame_->Exit();
1693 __ ret((scope_->num_parameters() + 1) * kPointerSize);
1694 DeleteFrame();
1695
1696 // Check that the size of the code used for returning matches what is
1697 // expected by the debugger.
1698 ASSERT_EQ(Debug::kIa32JSReturnSequenceLength,
1699 __ SizeOfCodeGeneratedSince(&check_exit_codesize));
1700 }
1701
1702
1675 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) { 1703 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) {
1676 ASSERT(!in_spilled_code()); 1704 ASSERT(!in_spilled_code());
1677 Comment cmnt(masm_, "[ WithEnterStatement"); 1705 Comment cmnt(masm_, "[ WithEnterStatement");
1678 CodeForStatement(node); 1706 CodeForStatement(node);
1679 Load(node->expression()); 1707 Load(node->expression());
1680 Result context(this); 1708 Result context(this);
1681 if (node->is_catch_block()) { 1709 if (node->is_catch_block()) {
1682 context = frame_->CallRuntime(Runtime::kPushCatchContext, 1); 1710 context = frame_->CallRuntime(Runtime::kPushCatchContext, 1);
1683 } else { 1711 } else {
1684 context = frame_->CallRuntime(Runtime::kPushContext, 1); 1712 context = frame_->CallRuntime(Runtime::kPushContext, 1);
(...skipping 4282 matching lines...) Expand 10 before | Expand all | Expand 10 after
5967 5995
5968 // Slow-case: Go through the JavaScript implementation. 5996 // Slow-case: Go through the JavaScript implementation.
5969 __ bind(&slow); 5997 __ bind(&slow);
5970 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 5998 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
5971 } 5999 }
5972 6000
5973 6001
5974 #undef __ 6002 #undef __
5975 6003
5976 } } // namespace v8::internal 6004 } } // namespace v8::internal
OLDNEW
« 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