Revision: 14665
Author:   [email protected]
Date:     Tue May 14 08:30:55 2013
Log: Error found in test262 on ARM: BinaryOpStub could call out to a built-in and push parameters without an enclosing frame. This corrupted stackwalking.

BUG=
[email protected]

Review URL: https://codereview.chromium.org/14813029
http://code.google.com/p/v8/source/detail?r=14665

Modified:
 /branches/bleeding_edge/src/arm/code-stubs-arm.cc
 /branches/bleeding_edge/src/arm/code-stubs-arm.h
 /branches/bleeding_edge/src/arm/simulator-arm.cc
 /branches/bleeding_edge/src/code-stubs.cc
 /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc
 /branches/bleeding_edge/src/ia32/code-stubs-ia32.h
 /branches/bleeding_edge/src/x64/code-stubs-x64.cc
 /branches/bleeding_edge/src/x64/code-stubs-x64.h

=======================================
--- /branches/bleeding_edge/src/arm/code-stubs-arm.cc Tue May 7 14:01:53 2013 +++ /branches/bleeding_edge/src/arm/code-stubs-arm.cc Tue May 14 08:30:55 2013
@@ -2162,8 +2162,12 @@
   GenerateTypeTransition(masm);

   __ bind(&call_runtime);
-  GenerateRegisterArgsPush(masm);
-  GenerateCallRuntime(masm);
+  {
+    FrameScope scope(masm, StackFrame::INTERNAL);
+    GenerateRegisterArgsPush(masm);
+    GenerateCallRuntime(masm);
+  }
+  __ Ret();
 }


@@ -2188,7 +2192,8 @@
   __ CompareObjectType(right, r2, r2, FIRST_NONSTRING_TYPE);
   __ b(ge, &call_runtime);

-  StringAddStub string_add_stub(NO_STRING_CHECK_IN_STUB);
+  StringAddStub string_add_stub((StringAddFlags)
+                                (ERECT_FRAME | NO_STRING_CHECK_IN_STUB));
   GenerateRegisterArgsPush(masm);
   __ TailCallStub(&string_add_stub);

@@ -2459,8 +2464,12 @@
   }

   __ bind(&call_runtime);
-  GenerateRegisterArgsPush(masm);
-  GenerateCallRuntime(masm);
+  {
+    FrameScope scope(masm, StackFrame::INTERNAL);
+    GenerateRegisterArgsPush(masm);
+    GenerateCallRuntime(masm);
+  }
+  __ Ret();
 }


@@ -2507,8 +2516,12 @@
   GenerateTypeTransition(masm);

   __ bind(&call_runtime);
-  GenerateRegisterArgsPush(masm);
-  GenerateCallRuntime(masm);
+  {
+    FrameScope scope(masm, StackFrame::INTERNAL);
+    GenerateRegisterArgsPush(masm);
+    GenerateCallRuntime(masm);
+  }
+  __ Ret();
 }


@@ -2531,8 +2544,12 @@
   }

   __ bind(&call_runtime);
-  GenerateRegisterArgsPush(masm);
-  GenerateCallRuntime(masm);
+  {
+    FrameScope scope(masm, StackFrame::INTERNAL);
+    GenerateRegisterArgsPush(masm);
+    GenerateCallRuntime(masm);
+  }
+  __ Ret();
 }


@@ -2548,7 +2565,8 @@
   __ CompareObjectType(left, r2, r2, FIRST_NONSTRING_TYPE);
   __ b(ge, &left_not_string);

-  StringAddStub string_add_left_stub(NO_STRING_CHECK_LEFT_IN_STUB);
+  StringAddStub string_add_left_stub((StringAddFlags)
+      (ERECT_FRAME | NO_STRING_CHECK_LEFT_IN_STUB));
   GenerateRegisterArgsPush(masm);
   __ TailCallStub(&string_add_left_stub);

@@ -2558,7 +2576,8 @@
   __ CompareObjectType(right, r2, r2, FIRST_NONSTRING_TYPE);
   __ b(ge, &call_runtime);

-  StringAddStub string_add_right_stub(NO_STRING_CHECK_RIGHT_IN_STUB);
+  StringAddStub string_add_right_stub((StringAddFlags)
+      (ERECT_FRAME | NO_STRING_CHECK_RIGHT_IN_STUB));
   GenerateRegisterArgsPush(masm);
   __ TailCallStub(&string_add_right_stub);

@@ -5822,7 +5841,7 @@
   __ ldr(r1, MemOperand(sp, 0 * kPointerSize));  // Second argument.

   // Make sure that both arguments are strings if not known in advance.
-  if (flags_ == NO_STRING_ADD_FLAGS) {
+  if ((flags_ & NO_STRING_ADD_FLAGS) != 0) {
     __ JumpIfEitherSmi(r0, r1, &call_runtime);
     // Load instance types.
     __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset));
@@ -6114,13 +6133,47 @@

   // Just jump to runtime to add the two strings.
   __ bind(&call_runtime);
-  __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
+  if ((flags_ & ERECT_FRAME) != 0) {
+    GenerateRegisterArgsPop(masm);
+    // Build a frame
+    {
+      FrameScope scope(masm, StackFrame::INTERNAL);
+      GenerateRegisterArgsPush(masm);
+      __ CallRuntime(Runtime::kStringAdd, 2);
+    }
+    __ Ret();
+  } else {
+    __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
+  }

   if (call_builtin.is_linked()) {
     __ bind(&call_builtin);
-    __ InvokeBuiltin(builtin_id, JUMP_FUNCTION);
+    if ((flags_ & ERECT_FRAME) != 0) {
+      GenerateRegisterArgsPop(masm);
+      // Build a frame
+      {
+        FrameScope scope(masm, StackFrame::INTERNAL);
+        GenerateRegisterArgsPush(masm);
+        __ InvokeBuiltin(builtin_id, CALL_FUNCTION);
+      }
+      __ Ret();
+    } else {
+      __ InvokeBuiltin(builtin_id, JUMP_FUNCTION);
+    }
   }
 }
+
+
+void StringAddStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
+  __ push(r0);
+  __ push(r1);
+}
+
+
+void StringAddStub::GenerateRegisterArgsPop(MacroAssembler* masm) {
+  __ pop(r1);
+  __ pop(r0);
+}


 void StringAddStub::GenerateConvertArgument(MacroAssembler* masm,
=======================================
--- /branches/bleeding_edge/src/arm/code-stubs-arm.h Thu Apr 25 09:00:32 2013 +++ /branches/bleeding_edge/src/arm/code-stubs-arm.h Tue May 14 08:30:55 2013
@@ -211,11 +211,13 @@

 // Flag that indicates how to generate code for the stub StringAddStub.
 enum StringAddFlags {
-  NO_STRING_ADD_FLAGS = 0,
+  NO_STRING_ADD_FLAGS = 1 << 0,
   // Omit left string check in stub (left is definitely a string).
-  NO_STRING_CHECK_LEFT_IN_STUB = 1 << 0,
+  NO_STRING_CHECK_LEFT_IN_STUB = 1 << 1,
   // Omit right string check in stub (right is definitely a string).
-  NO_STRING_CHECK_RIGHT_IN_STUB = 1 << 1,
+  NO_STRING_CHECK_RIGHT_IN_STUB = 1 << 2,
+  // Stub needs a frame before calling the runtime
+  ERECT_FRAME = 1 << 3,
   // Omit both string checks in stub.
   NO_STRING_CHECK_IN_STUB =
       NO_STRING_CHECK_LEFT_IN_STUB | NO_STRING_CHECK_RIGHT_IN_STUB
@@ -241,6 +243,9 @@
                                Register scratch4,
                                Label* slow);

+  void GenerateRegisterArgsPush(MacroAssembler* masm);
+  void GenerateRegisterArgsPop(MacroAssembler* masm);
+
   const StringAddFlags flags_;
 };

=======================================
--- /branches/bleeding_edge/src/arm/simulator-arm.cc Tue Apr 30 04:34:43 2013 +++ /branches/bleeding_edge/src/arm/simulator-arm.cc Tue May 14 08:30:55 2013
@@ -412,7 +412,7 @@
           HeapObject* obj = reinterpret_cast<HeapObject*>(*cur);
           int value = *cur;
           Heap* current_heap = v8::internal::Isolate::Current()->heap();
-          if (current_heap->Contains(obj) || ((value & 1) == 0)) {
+          if (((value & 1) == 0) || current_heap->Contains(obj)) {
             PrintF(" (");
             if ((value & 1) == 0) {
               PrintF("smi %d", value / 2);
=======================================
--- /branches/bleeding_edge/src/code-stubs.cc   Mon Apr 29 08:09:22 2013
+++ /branches/bleeding_edge/src/code-stubs.cc   Tue May 14 08:30:55 2013
@@ -232,37 +232,37 @@
 void BinaryOpStub::GenerateCallRuntime(MacroAssembler* masm) {
   switch (op_) {
     case Token::ADD:
-      __ InvokeBuiltin(Builtins::ADD, JUMP_FUNCTION);
+      __ InvokeBuiltin(Builtins::ADD, CALL_FUNCTION);
       break;
     case Token::SUB:
-      __ InvokeBuiltin(Builtins::SUB, JUMP_FUNCTION);
+      __ InvokeBuiltin(Builtins::SUB, CALL_FUNCTION);
       break;
     case Token::MUL:
-      __ InvokeBuiltin(Builtins::MUL, JUMP_FUNCTION);
+      __ InvokeBuiltin(Builtins::MUL, CALL_FUNCTION);
       break;
     case Token::DIV:
-      __ InvokeBuiltin(Builtins::DIV, JUMP_FUNCTION);
+      __ InvokeBuiltin(Builtins::DIV, CALL_FUNCTION);
       break;
     case Token::MOD:
-      __ InvokeBuiltin(Builtins::MOD, JUMP_FUNCTION);
+      __ InvokeBuiltin(Builtins::MOD, CALL_FUNCTION);
       break;
     case Token::BIT_OR:
-      __ InvokeBuiltin(Builtins::BIT_OR, JUMP_FUNCTION);
+      __ InvokeBuiltin(Builtins::BIT_OR, CALL_FUNCTION);
       break;
     case Token::BIT_AND:
-      __ InvokeBuiltin(Builtins::BIT_AND, JUMP_FUNCTION);
+      __ InvokeBuiltin(Builtins::BIT_AND, CALL_FUNCTION);
       break;
     case Token::BIT_XOR:
-      __ InvokeBuiltin(Builtins::BIT_XOR, JUMP_FUNCTION);
+      __ InvokeBuiltin(Builtins::BIT_XOR, CALL_FUNCTION);
       break;
     case Token::SAR:
-      __ InvokeBuiltin(Builtins::SAR, JUMP_FUNCTION);
+      __ InvokeBuiltin(Builtins::SAR, CALL_FUNCTION);
       break;
     case Token::SHR:
-      __ InvokeBuiltin(Builtins::SHR, JUMP_FUNCTION);
+      __ InvokeBuiltin(Builtins::SHR, CALL_FUNCTION);
       break;
     case Token::SHL:
-      __ InvokeBuiltin(Builtins::SHL, JUMP_FUNCTION);
+      __ InvokeBuiltin(Builtins::SHL, CALL_FUNCTION);
       break;
     default:
       UNREACHABLE();
=======================================
--- /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Mon May 13 23:53:46 2013 +++ /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Tue May 14 08:30:55 2013
@@ -1225,6 +1225,14 @@
       3,
       1);
 }
+
+
+static void BinaryOpStub_GenerateRegisterArgsPop(MacroAssembler* masm) {
+  __ pop(ecx);
+  __ pop(eax);
+  __ pop(edx);
+  __ push(ecx);
+}


 static void BinaryOpStub_GenerateSmiCode(
@@ -1662,7 +1670,6 @@
     case Token::SUB:
     case Token::MUL:
     case Token::DIV:
-      GenerateRegisterArgsPush(masm);
       break;
     case Token::MOD:
     case Token::BIT_OR:
@@ -1671,11 +1678,19 @@
     case Token::SAR:
     case Token::SHL:
     case Token::SHR:
+      BinaryOpStub_GenerateRegisterArgsPop(masm);
       break;
     default:
       UNREACHABLE();
   }
-  GenerateCallRuntime(masm);
+
+  {
+    FrameScope scope(masm, StackFrame::INTERNAL);
+    __ push(edx);
+    __ push(eax);
+    GenerateCallRuntime(masm);
+  }
+  __ ret(0);
 }


@@ -1700,7 +1715,8 @@
   __ CmpObjectType(right, FIRST_NONSTRING_TYPE, ecx);
   __ j(above_equal, &call_runtime, Label::kNear);

-  StringAddStub string_add_stub(NO_STRING_CHECK_IN_STUB);
+  StringAddStub string_add_stub((StringAddFlags)
+                                (ERECT_FRAME | NO_STRING_CHECK_IN_STUB));
   GenerateRegisterArgsPush(masm);
   __ TailCallStub(&string_add_stub);

@@ -1892,7 +1908,6 @@
     case Token::SUB:
     case Token::MUL:
     case Token::DIV:
-      GenerateRegisterArgsPush(masm);
       break;
     case Token::MOD:
       return;  // Handled above.
@@ -1902,11 +1917,19 @@
     case Token::SAR:
     case Token::SHL:
     case Token::SHR:
+      BinaryOpStub_GenerateRegisterArgsPop(masm);
       break;
     default:
       UNREACHABLE();
   }
-  GenerateCallRuntime(masm);
+
+  {
+    FrameScope scope(masm, StackFrame::INTERNAL);
+    __ push(edx);
+    __ push(eax);
+    GenerateCallRuntime(masm);
+  }
+  __ ret(0);
 }


@@ -2109,7 +2132,6 @@
     case Token::MUL:
     case Token::DIV:
     case Token::MOD:
-      GenerateRegisterArgsPush(masm);
       break;
     case Token::BIT_OR:
     case Token::BIT_AND:
@@ -2117,11 +2139,19 @@
     case Token::SAR:
     case Token::SHL:
     case Token::SHR:
+      BinaryOpStub_GenerateRegisterArgsPop(masm);
       break;
     default:
       UNREACHABLE();
   }
-  GenerateCallRuntime(masm);
+
+  {
+    FrameScope scope(masm, StackFrame::INTERNAL);
+    __ push(edx);
+    __ push(eax);
+    GenerateCallRuntime(masm);
+  }
+  __ ret(0);
 }


@@ -2287,7 +2317,6 @@
     case Token::SUB:
     case Token::MUL:
     case Token::DIV:
-      GenerateRegisterArgsPush(masm);
       break;
     case Token::MOD:
     case Token::BIT_OR:
@@ -2296,11 +2325,19 @@
     case Token::SAR:
     case Token::SHL:
     case Token::SHR:
+      BinaryOpStub_GenerateRegisterArgsPop(masm);
       break;
     default:
       UNREACHABLE();
   }
-  GenerateCallRuntime(masm);
+
+  {
+    FrameScope scope(masm, StackFrame::INTERNAL);
+    __ push(edx);
+    __ push(eax);
+    GenerateCallRuntime(masm);
+  }
+  __ ret(0);
 }


@@ -2317,7 +2354,8 @@
   __ CmpObjectType(left, FIRST_NONSTRING_TYPE, ecx);
   __ j(above_equal, &left_not_string, Label::kNear);

-  StringAddStub string_add_left_stub(NO_STRING_CHECK_LEFT_IN_STUB);
+  StringAddStub string_add_left_stub((StringAddFlags)
+      (ERECT_FRAME | NO_STRING_CHECK_LEFT_IN_STUB));
   GenerateRegisterArgsPush(masm);
   __ TailCallStub(&string_add_left_stub);

@@ -2327,7 +2365,8 @@
   __ CmpObjectType(right, FIRST_NONSTRING_TYPE, ecx);
   __ j(above_equal, &call_runtime, Label::kNear);

-  StringAddStub string_add_right_stub(NO_STRING_CHECK_RIGHT_IN_STUB);
+  StringAddStub string_add_right_stub((StringAddFlags)
+      (ERECT_FRAME | NO_STRING_CHECK_RIGHT_IN_STUB));
   GenerateRegisterArgsPush(masm);
   __ TailCallStub(&string_add_right_stub);

@@ -5737,7 +5776,7 @@
   __ mov(edx, Operand(esp, 1 * kPointerSize));  // Second argument.

   // Make sure that both arguments are strings if not known in advance.
-  if (flags_ == NO_STRING_ADD_FLAGS) {
+  if ((flags_ & NO_STRING_ADD_FLAGS) != 0) {
     __ JumpIfSmi(eax, &call_runtime);
     __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, ebx);
     __ j(above_equal, &call_runtime);
@@ -6045,13 +6084,50 @@
   __ Drop(2);
   // Just jump to runtime to add the two strings.
   __ bind(&call_runtime);
-  __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
+  if ((flags_ & ERECT_FRAME) != 0) {
+    GenerateRegisterArgsPop(masm, ecx);
+    // Build a frame
+    {
+      FrameScope scope(masm, StackFrame::INTERNAL);
+      GenerateRegisterArgsPush(masm);
+      __ CallRuntime(Runtime::kStringAdd, 2);
+    }
+    __ ret(0);
+  } else {
+    __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
+  }

   if (call_builtin.is_linked()) {
     __ bind(&call_builtin);
-    __ InvokeBuiltin(builtin_id, JUMP_FUNCTION);
+    if ((flags_ & ERECT_FRAME) != 0) {
+      GenerateRegisterArgsPop(masm, ecx);
+      // Build a frame
+      {
+        FrameScope scope(masm, StackFrame::INTERNAL);
+        GenerateRegisterArgsPush(masm);
+        __ InvokeBuiltin(builtin_id, CALL_FUNCTION);
+      }
+      __ ret(0);
+    } else {
+      __ InvokeBuiltin(builtin_id, JUMP_FUNCTION);
+    }
   }
 }
+
+
+void StringAddStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
+  __ push(eax);
+  __ push(edx);
+}
+
+
+void StringAddStub::GenerateRegisterArgsPop(MacroAssembler* masm,
+                                            Register temp) {
+  __ pop(temp);
+  __ pop(edx);
+  __ pop(eax);
+  __ push(temp);
+}


 void StringAddStub::GenerateConvertArgument(MacroAssembler* masm,
=======================================
--- /branches/bleeding_edge/src/ia32/code-stubs-ia32.h Thu Apr 25 09:00:32 2013 +++ /branches/bleeding_edge/src/ia32/code-stubs-ia32.h Tue May 14 08:30:55 2013
@@ -218,13 +218,14 @@
 };


-// Flag that indicates how to generate code for the stub StringAddStub.
 enum StringAddFlags {
-  NO_STRING_ADD_FLAGS = 0,
+  NO_STRING_ADD_FLAGS = 1 << 0,
   // Omit left string check in stub (left is definitely a string).
-  NO_STRING_CHECK_LEFT_IN_STUB = 1 << 0,
+  NO_STRING_CHECK_LEFT_IN_STUB = 1 << 1,
   // Omit right string check in stub (right is definitely a string).
-  NO_STRING_CHECK_RIGHT_IN_STUB = 1 << 1,
+  NO_STRING_CHECK_RIGHT_IN_STUB = 1 << 2,
+  // Stub needs a frame before calling the runtime
+  ERECT_FRAME = 1 << 3,
   // Omit both string checks in stub.
   NO_STRING_CHECK_IN_STUB =
       NO_STRING_CHECK_LEFT_IN_STUB | NO_STRING_CHECK_RIGHT_IN_STUB
@@ -249,6 +250,9 @@
                                Register scratch3,
                                Label* slow);

+  void GenerateRegisterArgsPush(MacroAssembler* masm);
+  void GenerateRegisterArgsPop(MacroAssembler* masm, Register temp);
+
   const StringAddFlags flags_;
 };

=======================================
--- /branches/bleeding_edge/src/x64/code-stubs-x64.cc Tue May 7 14:01:53 2013 +++ /branches/bleeding_edge/src/x64/code-stubs-x64.cc Tue May 14 08:30:55 2013
@@ -1270,6 +1270,17 @@
              "BinaryStub_GenerateFloatingPointCode.");
   }
 }
+
+
+static void BinaryOpStub_GenerateRegisterArgsPushUnderReturn(
+    MacroAssembler* masm) {
+  // Push arguments, but ensure they are under the return address
+  // for a tail call.
+  __ pop(rcx);
+  __ push(rdx);
+  __ push(rax);
+  __ push(rcx);
+}


 void BinaryOpStub::GenerateAddStrings(MacroAssembler* masm) {
@@ -1284,8 +1295,9 @@
   __ JumpIfSmi(left, &left_not_string, Label::kNear);
   __ CmpObjectType(left, FIRST_NONSTRING_TYPE, rcx);
   __ j(above_equal, &left_not_string, Label::kNear);
-  StringAddStub string_add_left_stub(NO_STRING_CHECK_LEFT_IN_STUB);
-  GenerateRegisterArgsPush(masm);
+  StringAddStub string_add_left_stub((StringAddFlags)
+      (ERECT_FRAME | NO_STRING_CHECK_LEFT_IN_STUB));
+  BinaryOpStub_GenerateRegisterArgsPushUnderReturn(masm);
   __ TailCallStub(&string_add_left_stub);

   // Left operand is not a string, test right.
@@ -1294,8 +1306,9 @@
   __ CmpObjectType(right, FIRST_NONSTRING_TYPE, rcx);
   __ j(above_equal, &call_runtime, Label::kNear);

-  StringAddStub string_add_right_stub(NO_STRING_CHECK_RIGHT_IN_STUB);
-  GenerateRegisterArgsPush(masm);
+  StringAddStub string_add_right_stub((StringAddFlags)
+      (ERECT_FRAME | NO_STRING_CHECK_RIGHT_IN_STUB));
+  BinaryOpStub_GenerateRegisterArgsPushUnderReturn(masm);
   __ TailCallStub(&string_add_right_stub);

   // Neither argument is a string.
@@ -1322,8 +1335,12 @@

   if (call_runtime.is_linked()) {
     __ bind(&call_runtime);
-    GenerateRegisterArgsPush(masm);
-    GenerateCallRuntime(masm);
+    {
+      FrameScope scope(masm, StackFrame::INTERNAL);
+      GenerateRegisterArgsPush(masm);
+      GenerateCallRuntime(masm);
+    }
+    __ Ret();
   }
 }

@@ -1356,8 +1373,9 @@
   __ CmpObjectType(right, FIRST_NONSTRING_TYPE, rcx);
   __ j(above_equal, &call_runtime);

-  StringAddStub string_add_stub(NO_STRING_CHECK_IN_STUB);
-  GenerateRegisterArgsPush(masm);
+  StringAddStub string_add_stub((StringAddFlags)
+                                (ERECT_FRAME | NO_STRING_CHECK_IN_STUB));
+  BinaryOpStub_GenerateRegisterArgsPushUnderReturn(masm);
   __ TailCallStub(&string_add_stub);

   __ bind(&call_runtime);
@@ -1442,8 +1460,12 @@
   GenerateTypeTransition(masm);

   __ bind(&gc_required);
-  GenerateRegisterArgsPush(masm);
-  GenerateCallRuntime(masm);
+  {
+    FrameScope scope(masm, StackFrame::INTERNAL);
+    GenerateRegisterArgsPush(masm);
+    GenerateCallRuntime(masm);
+  }
+  __ Ret();
 }


@@ -1462,8 +1484,12 @@
   }

   __ bind(&call_runtime);
-  GenerateRegisterArgsPush(masm);
-  GenerateCallRuntime(masm);
+  {
+    FrameScope scope(masm, StackFrame::INTERNAL);
+    GenerateRegisterArgsPush(masm);
+    GenerateCallRuntime(masm);
+  }
+  __ Ret();
 }


@@ -1507,10 +1533,8 @@


 void BinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
-  __ pop(rcx);
   __ push(rdx);
   __ push(rax);
-  __ push(rcx);
 }


@@ -4791,7 +4815,7 @@
__ movq(rdx, Operand(rsp, 1 * kPointerSize)); // Second argument (right).

   // Make sure that both arguments are strings if not known in advance.
-  if (flags_ == NO_STRING_ADD_FLAGS) {
+  if ((flags_ & NO_STRING_ADD_FLAGS) != 0) {
     __ JumpIfSmi(rax, &call_runtime);
     __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, r8);
     __ j(above_equal, &call_runtime);
@@ -5068,13 +5092,51 @@

   // Just jump to runtime to add the two strings.
   __ bind(&call_runtime);
-  __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
+
+  if ((flags_ & ERECT_FRAME) != 0) {
+    GenerateRegisterArgsPop(masm, rcx);
+    // Build a frame
+    {
+      FrameScope scope(masm, StackFrame::INTERNAL);
+      GenerateRegisterArgsPush(masm);
+      __ CallRuntime(Runtime::kStringAdd, 2);
+    }
+    __ Ret();
+  } else {
+    __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
+  }

   if (call_builtin.is_linked()) {
     __ bind(&call_builtin);
-    __ InvokeBuiltin(builtin_id, JUMP_FUNCTION);
+    if ((flags_ & ERECT_FRAME) != 0) {
+      GenerateRegisterArgsPop(masm, rcx);
+      // Build a frame
+      {
+        FrameScope scope(masm, StackFrame::INTERNAL);
+        GenerateRegisterArgsPush(masm);
+        __ InvokeBuiltin(builtin_id, CALL_FUNCTION);
+      }
+      __ Ret();
+    } else {
+      __ InvokeBuiltin(builtin_id, JUMP_FUNCTION);
+    }
   }
 }
+
+
+void StringAddStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
+  __ push(rax);
+  __ push(rdx);
+}
+
+
+void StringAddStub::GenerateRegisterArgsPop(MacroAssembler* masm,
+                                            Register temp) {
+  __ pop(temp);
+  __ pop(rdx);
+  __ pop(rax);
+  __ push(temp);
+}


 void StringAddStub::GenerateConvertArgument(MacroAssembler* masm,
=======================================
--- /branches/bleeding_edge/src/x64/code-stubs-x64.h Thu Apr 25 09:00:32 2013 +++ /branches/bleeding_edge/src/x64/code-stubs-x64.h Tue May 14 08:30:55 2013
@@ -207,11 +207,13 @@

 // Flag that indicates how to generate code for the stub StringAddStub.
 enum StringAddFlags {
-  NO_STRING_ADD_FLAGS = 0,
+  NO_STRING_ADD_FLAGS = 1 << 0,
   // Omit left string check in stub (left is definitely a string).
-  NO_STRING_CHECK_LEFT_IN_STUB = 1 << 0,
+  NO_STRING_CHECK_LEFT_IN_STUB = 1 << 1,
   // Omit right string check in stub (right is definitely a string).
-  NO_STRING_CHECK_RIGHT_IN_STUB = 1 << 1,
+  NO_STRING_CHECK_RIGHT_IN_STUB = 1 << 2,
+  // Stub needs a frame before calling the runtime
+  ERECT_FRAME = 1 << 3,
   // Omit both string checks in stub.
   NO_STRING_CHECK_IN_STUB =
       NO_STRING_CHECK_LEFT_IN_STUB | NO_STRING_CHECK_RIGHT_IN_STUB
@@ -236,6 +238,9 @@
                                Register scratch3,
                                Label* slow);

+  void GenerateRegisterArgsPush(MacroAssembler* masm);
+  void GenerateRegisterArgsPop(MacroAssembler* masm, Register temp);
+
   const StringAddFlags flags_;
 };

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to