Emitting the common return sequence in the top-level compiler in one function for...
authorfschneider@chromium.org <fschneider@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 4 Nov 2009 14:11:39 +0000 (14:11 +0000)
committerfschneider@chromium.org <fschneider@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 4 Nov 2009 14:11:39 +0000 (14:11 +0000)
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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3213 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/arm/fast-codegen-arm.cc
src/fast-codegen.h
src/ia32/fast-codegen-ia32.cc
src/x64/fast-codegen-x64.cc

index 7aeea93bf26beb1fff9bce5db4c7254a6722affc..21e4791493cf0356ef131014876c82ce0ddfca53 100644 (file)
@@ -102,26 +102,51 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun) {
     // 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::DeclareGlobals(Handle<FixedArray> pairs) {
 
 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 @@ void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
     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());
 }
 
 
index 6a645fe38e89c55ab6282dddfce6637031ee5653..0d1bca40e07295c7f35e91df2b0cfa1074597a4e 100644 (file)
@@ -73,6 +73,10 @@ class FastCodeGenerator: public AstVisitor {
   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);
 
index 12f90cd01c377dff993b3231642e48fbf3917e4f..6c0a814a3ed6bd2fbec9408da3bcee792e55ae6c 100644 (file)
@@ -91,30 +91,42 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun) {
   }
 
   { 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());
+    EmitReturnSequence(function_->end_position());
   }
-  { 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);
+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::DeclareGlobals(Handle<FixedArray> pairs) {
 
 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 @@ void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
     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());
 }
 
 
index caa47367cc363ddcc6b08d36d2ca455cfb10d8d1..2f1b64d00aa9b9bdd7ccc0e80bbeb143c906a947 100644 (file)
@@ -90,44 +90,52 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun) {
   }
 
   { 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);
+    EmitReturnSequence(function_->end_position());
   }
-  { 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();
-      }
+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) {
   switch (context) {
     case Expression::kUninitialized:
@@ -282,7 +290,6 @@ void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
 
 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 @@ void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
     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());
 }