| Index: src/arm/codegen-arm.cc
|
| ===================================================================
|
| --- src/arm/codegen-arm.cc (revision 4835)
|
| +++ src/arm/codegen-arm.cc (working copy)
|
| @@ -342,56 +342,27 @@
|
| }
|
| }
|
|
|
| - // Generate the return sequence if necessary.
|
| - if (has_valid_frame() || function_return_.is_linked()) {
|
| - if (!function_return_.is_linked()) {
|
| - CodeForReturnPosition(info->function());
|
| + // 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.
|
| + ASSERT(!function_return_is_shadowed_);
|
| + frame_->PrepareForReturn();
|
| + __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
|
| + if (function_return_.is_bound()) {
|
| + function_return_.Jump();
|
| + } else {
|
| + function_return_.Bind();
|
| + GenerateReturnSequence();
|
| }
|
| - // exit
|
| - // r0: result
|
| - // sp: stack pointer
|
| - // fp: frame pointer
|
| - // cp: callee's context
|
| - __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
|
| -
|
| + } 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.
|
| function_return_.Bind();
|
| - if (FLAG_trace) {
|
| - // Push the return value on the stack as the parameter.
|
| - // Runtime::TraceExit returns the parameter as it is.
|
| - frame_->EmitPush(r0);
|
| - frame_->CallRuntime(Runtime::kTraceExit, 1);
|
| - }
|
| -
|
| -#ifdef DEBUG
|
| - // Add a label for checking the size of the code used for returning.
|
| - Label check_exit_codesize;
|
| - masm_->bind(&check_exit_codesize);
|
| -#endif
|
| - // Make sure that the constant pool is not emitted inside of the return
|
| - // sequence.
|
| - { Assembler::BlockConstPoolScope block_const_pool(masm_);
|
| - // Tear down the frame which will restore the caller's frame pointer and
|
| - // the link register.
|
| - frame_->Exit();
|
| -
|
| - // Here we use masm_-> instead of the __ macro to avoid the code coverage
|
| - // tool from instrumenting as we rely on the code size here.
|
| - int32_t sp_delta = (scope()->num_parameters() + 1) * kPointerSize;
|
| - masm_->add(sp, sp, Operand(sp_delta));
|
| - masm_->Jump(lr);
|
| -
|
| -#ifdef DEBUG
|
| - // Check that the size of the code used for returning matches what is
|
| - // expected by the debugger. If the sp_delts above cannot be encoded in
|
| - // the add instruction the add will generate two instructions.
|
| - int return_sequence_length =
|
| - masm_->InstructionsGeneratedSince(&check_exit_codesize);
|
| - CHECK(return_sequence_length ==
|
| - Assembler::kJSReturnSequenceInstructions ||
|
| - return_sequence_length ==
|
| - Assembler::kJSReturnSequenceInstructions + 1);
|
| -#endif
|
| - }
|
| + GenerateReturnSequence();
|
| }
|
|
|
| // Adjust for function-level loop nesting.
|
| @@ -1958,9 +1929,57 @@
|
| // returning thus making it easier to merge.
|
| frame_->EmitPop(r0);
|
| frame_->PrepareForReturn();
|
| + if (function_return_.is_bound()) {
|
| + // If the function return label is already bound we reuse the
|
| + // code by jumping to the return site.
|
| + function_return_.Jump();
|
| + } else {
|
| + function_return_.Bind();
|
| + GenerateReturnSequence();
|
| + }
|
| + }
|
| +}
|
|
|
| - function_return_.Jump();
|
| +
|
| +void CodeGenerator::GenerateReturnSequence() {
|
| + if (FLAG_trace) {
|
| + // Push the return value on the stack as the parameter.
|
| + // Runtime::TraceExit returns the parameter as it is.
|
| + frame_->EmitPush(r0);
|
| + frame_->CallRuntime(Runtime::kTraceExit, 1);
|
| }
|
| +
|
| +#ifdef DEBUG
|
| + // Add a label for checking the size of the code used for returning.
|
| + Label check_exit_codesize;
|
| + masm_->bind(&check_exit_codesize);
|
| +#endif
|
| + // Make sure that the constant pool is not emitted inside of the return
|
| + // sequence.
|
| + { Assembler::BlockConstPoolScope block_const_pool(masm_);
|
| + // Tear down the frame which will restore the caller's frame pointer and
|
| + // the link register.
|
| + frame_->Exit();
|
| +
|
| + // Here we use masm_-> instead of the __ macro to avoid the code coverage
|
| + // tool from instrumenting as we rely on the code size here.
|
| + int32_t sp_delta = (scope()->num_parameters() + 1) * kPointerSize;
|
| + masm_->add(sp, sp, Operand(sp_delta));
|
| + masm_->Jump(lr);
|
| + DeleteFrame();
|
| +
|
| +#ifdef DEBUG
|
| + // Check that the size of the code used for returning matches what is
|
| + // expected by the debugger. If the sp_delts above cannot be encoded in
|
| + // the add instruction the add will generate two instructions.
|
| + int return_sequence_length =
|
| + masm_->InstructionsGeneratedSince(&check_exit_codesize);
|
| + CHECK(return_sequence_length ==
|
| + Assembler::kJSReturnSequenceInstructions ||
|
| + return_sequence_length ==
|
| + Assembler::kJSReturnSequenceInstructions + 1);
|
| +#endif
|
| + }
|
| }
|
|
|
|
|
|
|