Revision: 3213 Author: [email protected] Date: Wed Nov 4 06:11:39 2009 Log: Emitting the common return sequence in the top-level compiler in one function for each platform.
I factored out the code for emitting the return sequence since we had this code duplicated in the top-level compiler. Review URL: http://codereview.chromium.org/354024 http://code.google.com/p/v8/source/detail?r=3213 Modified: /branches/bleeding_edge/src/arm/fast-codegen-arm.cc /branches/bleeding_edge/src/fast-codegen.h /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc /branches/bleeding_edge/src/x64/fast-codegen-x64.cc ======================================= --- /branches/bleeding_edge/src/arm/fast-codegen-arm.cc Tue Nov 3 08:08:35 2009 +++ /branches/bleeding_edge/src/arm/fast-codegen-arm.cc Wed Nov 4 06:11:39 2009 @@ -102,26 +102,51 @@ // body. __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); } - { Comment cmnt(masm_, "Return sequence"); - if (return_label_.is_bound()) { - __ b(&return_label_); - } else { - __ bind(&return_label_); - SetReturnPosition(fun); - if (FLAG_trace) { - // Push the return value on the stack as the parameter. - // Runtime::TraceExit returns its parameter in r0. - __ push(r0); - __ CallRuntime(Runtime::kTraceExit, 1); - } - __ RecordJSReturn(); - __ mov(sp, fp); - __ ldm(ia_w, sp, fp.bit() | lr.bit()); - int num_parameters = function_->scope()->num_parameters(); - __ add(sp, sp, Operand((num_parameters + 1) * kPointerSize)); - __ Jump(lr); - } - } + EmitReturnSequence(function_->end_position()); +} + + +void FastCodeGenerator::EmitReturnSequence(int position) { + Comment cmnt(masm_, "[ Return sequence"); + if (return_label_.is_bound()) { + __ b(&return_label_); + } else { + __ bind(&return_label_); + if (FLAG_trace) { + // Push the return value on the stack as the parameter. + // Runtime::TraceExit returns its parameter in r0. + __ push(r0); + __ 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 + CodeGenerator::RecordPositions(masm_, position); + __ RecordJSReturn(); + __ mov(sp, fp); + __ ldm(ia_w, sp, fp.bit() | lr.bit()); + int num_parameters = function_->scope()->num_parameters(); + __ add(sp, sp, Operand((num_parameters + 1) * kPointerSize)); + __ Jump(lr); + } +#ifdef DEBUG + // Check that the size of the code used for returning matches what is + // expected by the debugger. The add instruction above is an addressing + // mode 1 instruction where there are restrictions on which immediate values + // can be encoded in the instruction and which immediate values requires + // use of an additional instruction for moving the immediate to a temporary + // register. + int expected_return_sequence_length = CodeGenerator::kJSReturnSequenceLength; + if (!masm_->ImmediateFitsAddrMode1Instruction((num_parameters + 1) * + kPointerSize)) { + // Additional mov instruction generated. + expected_return_sequence_length++; + } + ASSERT_EQ(expected_return_sequence_length, + masm_->InstructionsGeneratedSince(&check_exit_codesize)); +#endif } @@ -259,7 +284,6 @@ void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { Comment cmnt(masm_, "[ ReturnStatement"); - SetStatementPosition(stmt); Expression* expr = stmt->expression(); // Complete the statement based on the type of the subexpression. if (expr->AsLiteral() != NULL) { @@ -269,21 +293,7 @@ Visit(expr); __ pop(r0); } - if (return_label_.is_bound()) { - __ b(&return_label_); - } else { - __ bind(&return_label_); - if (FLAG_trace) { - __ push(r0); - __ CallRuntime(Runtime::kTraceExit, 1); - } - __ RecordJSReturn(); - __ mov(sp, fp); - __ ldm(ia_w, sp, fp.bit() | lr.bit()); - int num_parameters = function_->scope()->num_parameters(); - __ add(sp, sp, Operand((num_parameters + 1) * kPointerSize)); - __ Jump(lr); - } + EmitReturnSequence(stmt->statement_pos()); } ======================================= --- /branches/bleeding_edge/src/fast-codegen.h Tue Nov 3 06:48:59 2009 +++ /branches/bleeding_edge/src/fast-codegen.h Wed Nov 4 06:11:39 2009 @@ -73,6 +73,10 @@ Handle<JSFunction> BuildBoilerplate(FunctionLiteral* fun); void DeclareGlobals(Handle<FixedArray> pairs); + // Platform-specific return sequence + void EmitReturnSequence(int position); + + // Platform-specific code sequences for calls void EmitCallWithStub(Call* expr); void EmitCallWithIC(Call* expr, RelocInfo::Mode reloc_info); ======================================= --- /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc Tue Nov 3 06:48:59 2009 +++ /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc Wed Nov 4 06:11:39 2009 @@ -91,30 +91,42 @@ } { Comment cmnt(masm_, "[ return <undefined>;"); - // Emit a 'return undefined' in case control fell off the end of the - // body. + // Emit a 'return undefined' in case control fell off the end of the body. __ mov(eax, Factory::undefined_value()); - } - { Comment cmnt(masm_, "[ Return sequence"); - SetReturnPosition(fun); - - if (return_label_.is_bound()) { - __ jmp(&return_label_); - } else { - // Common return label - __ bind(&return_label_); - - if (FLAG_trace) { - __ push(eax); - __ CallRuntime(Runtime::kTraceExit, 1); - } - __ RecordJSReturn(); - // Do not use the leave instruction here because it is too short to - // patch with the code required by the debugger. - __ mov(esp, ebp); - __ pop(ebp); - __ ret((fun->scope()->num_parameters() + 1) * kPointerSize); - } + EmitReturnSequence(function_->end_position()); + } +} + + +void FastCodeGenerator::EmitReturnSequence(int position) { + Comment cmnt(masm_, "[ Return sequence"); + if (return_label_.is_bound()) { + __ jmp(&return_label_); + } else { + // Common return label + __ bind(&return_label_); + if (FLAG_trace) { + __ push(eax); + __ 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 + CodeGenerator::RecordPositions(masm_, position); + __ RecordJSReturn(); + // Do not use the leave instruction here because it is too short to + // patch with the code required by the debugger. + __ mov(esp, ebp); + __ pop(ebp); + __ ret((function_->scope()->num_parameters() + 1) * kPointerSize); +#ifdef ENABLE_DEBUGGER_SUPPORT + // Check that the size of the code used for returning matches what is + // expected by the debugger. + ASSERT_EQ(Debug::kIa32JSReturnSequenceLength, + masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); +#endif } } @@ -270,7 +282,6 @@ void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { Comment cmnt(masm_, "[ ReturnStatement"); - SetStatementPosition(stmt); Expression* expr = stmt->expression(); if (expr->AsLiteral() != NULL) { __ mov(eax, expr->AsLiteral()->handle()); @@ -279,25 +290,7 @@ Visit(expr); __ pop(eax); } - - if (return_label_.is_bound()) { - __ jmp(&return_label_); - } else { - __ bind(&return_label_); - - if (FLAG_trace) { - __ push(eax); - __ CallRuntime(Runtime::kTraceExit, 1); - } - - __ RecordJSReturn(); - - // Do not use the leave instruction here because it is too short to - // patch with the code required by the debugger. - __ mov(esp, ebp); - __ pop(ebp); - __ ret((function_->scope()->num_parameters() + 1) * kPointerSize); - } + EmitReturnSequence(stmt->statement_pos()); } ======================================= --- /branches/bleeding_edge/src/x64/fast-codegen-x64.cc Tue Nov 3 06:48:59 2009 +++ /branches/bleeding_edge/src/x64/fast-codegen-x64.cc Wed Nov 4 06:11:39 2009 @@ -90,42 +90,50 @@ } { Comment cmnt(masm_, "[ return <undefined>;"); - // Emit a 'return undefined' in case control fell off the end of the - // body. + // Emit a 'return undefined' in case control fell off the end of the body. __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); - } - { Comment cmnt(masm_, "Return sequence"); - SetReturnPosition(fun); - - if (return_label_.is_bound()) { - __ jmp(&return_label_); - } else { - __ bind(&return_label_); - - if (FLAG_trace) { - __ push(rax); - __ CallRuntime(Runtime::kTraceExit, 1); - } - __ RecordJSReturn(); - - // Do not use the leave instruction here because it is too short to - // patch with the code required by the debugger. - __ movq(rsp, rbp); - __ pop(rbp); - __ ret((fun->scope()->num_parameters() + 1) * kPointerSize); -#ifdef ENABLE_DEBUGGER_SUPPORT - // Add padding that will be overwritten by a debugger breakpoint. We - // have just generated "movq rsp, rbp; pop rbp; ret k" with length 7 - // (3 + 1 + 3). - const int kPadding = Debug::kX64JSReturnSequenceLength - 7; - for (int i = 0; i < kPadding; ++i) { - masm_->int3(); - } + EmitReturnSequence(function_->end_position()); + } +} + + +void FastCodeGenerator::EmitReturnSequence(int position) { + Comment cmnt(masm_, "[ Return sequence"); + if (return_label_.is_bound()) { + __ jmp(&return_label_); + } else { + __ bind(&return_label_); + if (FLAG_trace) { + __ push(rax); + __ 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 - } + CodeGenerator::RecordPositions(masm_, position); + __ RecordJSReturn(); + // Do not use the leave instruction here because it is too short to + // patch with the code required by the debugger. + __ movq(rsp, rbp); + __ pop(rbp); + __ ret((function_->scope()->num_parameters() + 1) * kPointerSize); +#ifdef ENABLE_DEBUGGER_SUPPORT + // Add padding that will be overwritten by a debugger breakpoint. We + // have just generated "movq rsp, rbp; pop rbp; ret k" with length 7 + // (3 + 1 + 3). + const int kPadding = Debug::kX64JSReturnSequenceLength - 7; + for (int i = 0; i < kPadding; ++i) { + masm_->int3(); + } + // Check that the size of the code used for returning matches what is + // expected by the debugger. + ASSERT_EQ(Debug::Debug::kX64JSReturnSequenceLength, + masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); +#endif } } - void FastCodeGenerator::Move(Expression::Context context, Register source) { @@ -282,7 +290,6 @@ void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { Comment cmnt(masm_, "[ ReturnStatement"); - SetStatementPosition(stmt); Expression* expr = stmt->expression(); if (expr->AsLiteral() != NULL) { __ Move(rax, expr->AsLiteral()->handle()); @@ -291,33 +298,7 @@ ASSERT_EQ(Expression::kValue, expr->context()); __ pop(rax); } - - if (return_label_.is_bound()) { - __ jmp(&return_label_); - } else { - __ bind(&return_label_); - - if (FLAG_trace) { - __ push(rax); - __ CallRuntime(Runtime::kTraceExit, 1); - } - - __ RecordJSReturn(); - // Do not use the leave instruction here because it is too short to - // patch with the code required by the debugger. - __ movq(rsp, rbp); - __ pop(rbp); - __ ret((function_->scope()->num_parameters() + 1) * kPointerSize); -#ifdef ENABLE_DEBUGGER_SUPPORT - // Add padding that will be overwritten by a debugger breakpoint. We - // have just generated "movq rsp, rbp; pop rbp; ret k" with length 7 - // (3 + 1 + 3). - const int kPadding = Debug::kX64JSReturnSequenceLength - 7; - for (int i = 0; i < kPadding; ++i) { - masm_->int3(); - } -#endif - } + EmitReturnSequence(stmt->statement_pos()); } --~--~---------~--~----~------------~-------~--~----~ v8-dev mailing list [email protected] http://groups.google.com/group/v8-dev -~----------~----~----~----~------~----~------~--~---
